Description of problem: If you attach a loop device to a backing file which is less than 512 bytes in length, then losetup -a will not show the loop device as being in use. It certainly *is* in use, however, since attempting to attach to the invisible devices results in EBUSY Create some files of various sizes: # touch one # dd if=/dev/zero of=two count=1 bs=511 1+0 records in 1+0 records out 511 bytes (511 B) copied, 8.128e-05 s, 6.3 MB/s # dd if=/dev/zero of=three count=1 bs=512 1+0 records in 1+0 records out 512 bytes (512 B) copied, 6.9564e-05 s, 7.4 MB/s Attach them to loop devices: # for i in one two three ; do losetup -f $i ; done See what is claimed to be in use # losetup -a /dev/loop2: [fd00]:3174665 (/root/three) Test what is actually in use: # dd if=/dev/zero of=four count=1 bs=512 1+0 records in 1+0 records out 512 bytes (512 B) copied, 9.1725e-05 s, 5.6 MB/s # losetup /dev/loop0 four losetup: /dev/loop0: device is busy # losetup /dev/loop1 four losetup: /dev/loop1: device is busy Release the devices that losetup claims are not actually in use # losetup -d /dev/loop0 # losetup -d /dev/loop1 Version-Release number of selected component (if applicable): util-linux-2.19.1-1.fc15.x86_64 How reproducible: Always for files < 512 bytes in length Steps to Reproduce: See above
I know about this problem. The losetup(8) uses the /proc/partitions file to get list of the devices, unfortunately this file contains only devices bigger than 1KiB... yeah, kernel sucks. The solution is to scan /sys/block/loopN.
I suspect that: bd_set_size(bdev, size << 9); in: drivers/block/loop.c should round up to the next sector. I guess a 600 bytes big loop device is only 512 bytes in size too?
The kernel needs to round down to the next full 512 bytes block. If the entire file is smaller than 512, the size of the volume will be 0, which is expected behavior. If the kernel wouldn't do that, it would need to pad stuff with \0 on read and write on the last unaligned block. Talked to Tejun, we think that losetup should always truncate the size at 512 bytes boundaries. And possibly even warn if the filesize is not aligned to sector boundaries, as the trailing bytes that are smaller than a sector will be ignored by the kernel. Even when the loop device is zeroed out, the file might still contain garbage at the end after that. Loop has blockdevice semantics, so there is nothing really the kernel can do with the last bytes of the files that don't fit into a 512 bytes sector. So losetup should probably inform the user that the remainder of the file is ignored by the kernel, and that this might not be what it was asked for. Having a file < 512 bytes makes no sense for a blockdevice mapping. The loop device can not be read or write, we can only handle full blocks. That the kernel allows that is questionable, but we think that losetup should already check these values at device setup.
If losetup wants to warn, or even refuse, to attach files < 512 bytes in size that'd be fine. I didn't intentionally want a < 512 byte file - it was a total mistake :-) In the particular scenario I originally encountered this problem with though, I was doing the ioctl()s to attach the (mistakenly zero length) file to the loop device directly from libvirt, and then wondering why 'losetup -a' didn't show them. So it would still be desirable to find a way to get 'losetup -a' to report such files, or for the kernel itself to refuse to allow it.
(In reply to comment #3) > Having a file < 512 bytes makes no sense for a blockdevice mapping. The loop > device can not be read or write, we can only handle full blocks. That the > kernel allows that is questionable There is possible to modify the device capacity. I can imagine scenario when you associate an empty file (or set sizelimit=0) and later modify the size by LOOP_SET_CAPACITY ioctl. > but we think that losetup should > already check these values at device setup. I'll add the warning about misaligned or too small sizes to losetup(1). The stupid thing is that the empty loopdev is not in /proc/partitions, so if we want to support this crazy feature then we have to _scan_ /sys/block/ :-(
Fixed by upstream commit e4062c72d1733b0b99ed1c6269c996d6194e869b (new version scans /sys/block). Not urgen issue, Fedora package will be updated after upgrade to the new upstream version.