Hi Eric, On Tue, May 07, 2024 at 07:02:56AM -0500, Eric Blake wrote:
On Wed, Feb 21, 2024 at 12:26:08PM -0600, Eric Blake wrote:
On Wed, Feb 21, 2024 at 12:19:49PM -0600, Eric Blake wrote:
setupexport() - default to client->server->expected_size (if one was provided), further validating that actual size is large enough when actual size can be computed - if neither treefile or F_WAIT is set, compute actual size by opening one or more files and using size_autodetect() (which does the right thing for block devices, so my earlier thought about over-reliance on stat() was wrong)
but these functions are only reached for NBD_OPT_EXPORT_NAME and NBD_OPT_GO, not NBD_OPT_INFO. The upshot is that for NBD_OPT_GO, there are some scenarios (treefile, F_WAIT) where nbd-server advertises a size of 9223372036854775807 (0x7fffffff_ffffffff) meaning unknown, but a size of 0 there is only possible if the file was successfully opened and really is zero bytes in length. Conversely, NBD_OPT_INFO is always advertising a size of 0, which means most of the time, the size changes between NBD_OPT_INFO and NBD_OPT_GO.
Amending myself: reading size_autodetect(), it tries ioctl(fd, BLKGETSIZE64) first (even when fd is not a block device!), then falls back to fstat(fd) coupled with lseek(SEEK_END) if fstat() reported st_size of 0 and not a regular file; but if all of those fail, it reports UINT64_MAX, which is different than OFFT_MAX.
Another wrinkle:
On BSD systems, lseek(fd_of_block, 0, SEEK_END) behaves identically to lseek(fd_of_block, 0, SEEK_START), because BSD has the idea that the size of a seekable file descriptor is whatever gets reported in stat().st_size which is 0 on block devices (Linux is the odd system out where lseek() and stat() disagree on this point - all other systems surveyed either reliably report the block capacity in st_size and SEEK_END, or use offset 0 in both places). See this POSIX bug for more details:
Sigh :-/
If we are going to report correct capacity of block devices, it requires a LOT more code; compare what nbdkit is adding:
https://gitlab.com/nbdkit/nbdkit/-/merge_requests/54/diffs?commit_id=532b617...
Yeah. In this context, I've never done much on non-Linux systems. We do indeed try stat and lseek, but I didn't realize that was not portable. We also use the BLKGETSIZE64 ioctl to figure out the size of a block device, but that's *definitely* Linux-specific. I'm definitely OK with improving that situation if we can make it happen... -- w@uter.{be,co.za} wouter@{grep.be,fosdem.org,debian.org} I will have a Tin-Actinium-Potassium mixture, thanks.