Bug#829496: kpartx -d ( detach ) option silently fails
Christian Kastner
ckk at debian.org
Wed Jul 13 17:31:07 UTC 2016
Control: tag -1 patch
On Sun, 03 Jul 2016 22:49:18 +0200 Emmanuel Kasper <emmanuel at libera.cc>
wrote:
> Since the 0.6.1-* version of kpartx, the '-d' option does not work anymore.
>
> Simple test case:
>
> # add loopdevice and partition mappings, freedos.raw is here a disk image
> kpartx -av freedos.raw
> add map loop0p1 (253:0): 0 262017 linear 7:0 63
>
> # ask kpartx to detach the loop device
> kpartx -d freedos.raw
>
> # but the loop device is still there
> file --special-files --dereference /dev/loop0
> /dev/loop0: DOS/MBR boot sector; partition 1 : ID=0xe, active, start-CHS (0x0,1,1), end-CHS (0x13,15,63), startsector 63, 262017 sectors
>
> losetup --list
> NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE DIO
> /dev/loop0 0 0 0 0 /home/manu/Projects/emul/i386/kvm/freedos.raw
I ran into this bug when creating bootable VM images using
vmdebootstrap. I noticed that all images, except the first one created
after a reboot, failed to boot.
The problem is that the code that is supposed to detect whether kpartx
is dealing with a loop-device-backed regular file is broken.
Assuming kpartx -d blockdev.img is called, the following happens in
kpartx.c:
> if (stat(device, &buf)) {
> printf("failed to stat() %s\n", device);
> exit (1);
> }
buf gets set with the status of device, which is blockdev.img.
> if (S_ISREG (buf.st_mode)) {
> /* already looped file ? */
> loopdev = find_loop_by_file(device);
This identifies the backing loop device of blockdev.img. Let's assume
that the device is /dev/loop0.
>
> if (!loopdev && what == DELETE)
> exit (0);
>
> if (!loopdev) {
> loopdev = find_unused_loop_device();
>
> if (set_loop(loopdev, device, 0, &ro)) {
> fprintf(stderr, "can't set up loop\n");
> exit (1);
> }
> loopcreated = 1;
> }
The above is not executed, as loopdev has been previously set.
> device = loopdev;
device no longer points to "blockdev.img", but to "/dev/loop0".
>
> if (stat(device, &buf)) {
> printf("failed to stat() %s\n", device);
> exit (1);
> }
> }
buf gets set again, but this time with the status of /dev/loop0.
Later:
> if (S_ISREG (buf.st_mode)) {
^^^
With buf being the status of /dev/loop0, S_ISREG evaluates to false.
Therefore, the following code which would normally remove the backing
loop device does not get called.
> if (del_loop(device)) {
> if (verbose)
> printf("can't del loop: %s\n",
> device);
> exit(1);
> }
> printf("loop deleted : %s\n", device);
> }
> break;
I've sent the attached patch to the upstream mailing list, but it should
also apply cleanly to the Debian version, albeit with some offset.
Regards,
Christian
-------------- next part --------------
A non-text attachment was scrubbed...
Name: kpartx-Fix-check-whether-to-detach-loop-device.patch
Type: text/x-patch
Size: 1644 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/pkg-lvm-maintainers/attachments/20160713/137385a5/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-lvm-maintainers/attachments/20160713/137385a5/attachment.sig>
More information about the pkg-lvm-maintainers
mailing list