libnbd provides synchronous and asynchronous C APIs for accessing Network
Block Device servers from userspace. Install shared and static libraries
and nbddump, with optional TLS and URI support, companion tools, FUSE
integration, and Python bindings.
Details
Diff Detail
- Repository
- R11 FreeBSD ports repository
- Lint
Lint Skipped - Unit
Tests Skipped - Build Status
Buildable 78055 Build 74938: arc lint + arc unit
Event Timeline
I've done a quick test with nbdsh, nbdfuse and nbddump. nbdfuse "mounts" the NBD server and the read works fine, but the write seems to be in a loop, even writing a single byte. Everything else works fine.
| net/libnbd/Makefile | ||
|---|---|---|
| 23 | It seems this is not necessary. Same log with or without it: ... checking for ocamlc... no ... No ocamlc (OCaml bytecode compiler), skipping the generator. If this is a noop, you can remove it. | |
Thanks for testing. With a TCP, file-backed nbdkit export, I reproduced the loop when appending one byte at EOF. Normal 64 MiB writes passed checksum verification.
I think this comes from upstream nbdfuse_write() returning zero at/past EOF, causing FreeBSD to retry indefinitely (https://gitlab.com/nbdkit/libnbd/-/blob/master/fuse/operations.c#L417-418). The same code exists in tagged 1.24.3 and current master.. Could you share your exact write command to confirm the same case?
My Unix-socket smoke test used these in separate terminals, with a fresh socket path and empty mount directory:
nbdkit -f -U "$socket" memory size=1M nbdfuse -d -o debug "$mountpoint" --unix "$socket"
| net/libnbd/Makefile | ||
|---|---|---|
| 23 | You're right that the logs match without ocamlc. I added this because --disable-ocaml only disables the bindings, while the generator is controlled separately. It avoids regenerating the release’s existing files when OCaml happens to be installed. Would it make sense to keep it for that case? | |
| net/libnbd/Makefile | ||
|---|---|---|
| 23 | It appears that the target being processed is stamp-generator, but the one found after the else (within HAVE_OCAMLC). This matches the log, suggesting it is not being processed: https://gitlab.com/nbdkit/libnbd/-/blob/v1.24.3/generator/Makefile.am#L101 | |
I have run a few more tests using dd(1), and everything is working correctly. The issue is that the nbd block device does not play well with tools like tee(1) or shell redirection. In practice, this is not a problem, since you will likely have control over the block being written, the offset, etc. The only real issue is that the loop occurs in nbdfuse, while the client simply perceives a hang.
Server:
# nbdkit -t 4 -f file file=/data/nbdkit-test-volume.img fadvise=sequential
Client (FUSE):
# mkdir dir # nbdfuse -vd -o allow_root dir nbd://nbdkit-test-volume ... nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78401000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 ^Cnbdfuse: write: path=/nbd, buf=0x26ff77c01000, count=2, offset=10737418240 nbdfuse: write: path=/nbd, buf=0x26ff78001000, count=2, offset=10737418240 nbdfuse: fuse_loop: fuse loop terminated by signal 2 nbdfuse: destroy: (no parameters) libnbd: debug: nbd1: nbd_close: closing handle libnbd: debug: nbd2: nbd_close: closing handle libnbd: debug: nbd3: nbd_close: closing handle libnbd: debug: nbd4: nbd_close: closing handle
Client:
# pwd /tmp/dir # echo 1 >> nbd
Info:
# nbdinfo nbd://nbdkit-test-volume
protocol: newstyle-fixed without TLS, using structured packets
export="":
export-size: 10737418240 (10G)
content: DOS/MBR boot sector; partition 1 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x3ff,255,63), startsector 1, 20971519 sectors, extended partition table (last)
uri: nbd://nbdkit-test-volume:10809/
contexts:
base:allocation
is_rotational: false
is_read_only: false
can_block_status_payload: false
can_cache: true
can_df: true
can_fast_zero: false
can_flush: true
can_fua: true
can_multi_conn: true
can_trim: false
can_zero: trueAnother test, but using dd(1) (works):
# printf "123456" | dd of=nbd bs=1 seek=0 conv=notrunc 6+0 records in 6+0 records out 6 bytes transferred in 0.002105 secs (2850 bytes/sec) # dd if=nbd bs=6 count=1 seek=0 conv=notrunc | hexdump -C 1+0 records in 1+0 records out 6 bytes transferred in 0.001346 secs (4458 bytes/sec) 00000000 31 32 33 34 35 36 |123456| 00000006
Just to clarify: the port seems ready to be committed. You might want to open an issue in the upstream repository. They could provide guidance for a workaround or a fix for the nbdfuse case. If that works for you, I can go ahead and commit it.
That sounds good, I think we can land this if there's no other notes for me to take care of, I'll open an issue upstream for the problem that you found.