From f35aace69f9471787cb89f5a41502832cc6141b5 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Tue, 21 Apr 2015 10:36:33 +0200 Subject: [PATCH] Use shorter temporary file names for kpartx The loopback handling in the Linux kernel limits the filenames of files associated to loopback devices, see also linux/loop.h. This is reflected also on userspace, as kpartx will silently do nothing (exiting with 0) when requesting to remove a filename longer than 64 characters, as that name will obviously not match the truncated filename. The result of this is that, when extracting qcow2 images for the first time, if the qcow2 filename is long enough then the loopback device will not be removed, remaining as stale in the host. As a workaround, use a temporary file name when convering a qcow2 image to raw, instead of using the base name of the qcow2 file. While this still will not fix the issue when manually using a long temporary directory (e.g. TMP_DIR=/very/long/etc...), at least should avoid it in other cases. Change-Id: Ibf46cd313a9d89412c0e1068fa0993be6c5a29db --- elements/redhat-common/bin/extract-image | 11 +++++------ elements/rhel/root.d/10-rhel-cloud-image | 9 ++++----- elements/ubuntu-core/root.d/10-cache-ubuntu-image | 9 ++++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/elements/redhat-common/bin/extract-image b/elements/redhat-common/bin/extract-image index e6a361f05..79feb0791 100755 --- a/elements/redhat-common/bin/extract-image +++ b/elements/redhat-common/bin/extract-image @@ -48,12 +48,11 @@ function extract_image() { trap "$EACTION" EXIT echo "Working in $WORKING" - RAW_FILE=$(basename $BASE_IMAGE_FILE) - RAW_FILE=${RAW_FILE%.qcow2}.raw + RAW_FILE=$(mktemp --tmpdir=$WORKING XXXXXX.raw) - qemu-img convert -f qcow2 -O raw $CACHED_IMAGE $WORKING/$RAW_FILE + qemu-img convert -f qcow2 -O raw $CACHED_IMAGE $RAW_FILE - ROOT_PARTITON=p$(sudo kpartx -l $WORKING/$RAW_FILE | awk "/loop[0-9]+p/"|wc -l) + ROOT_PARTITON=p$(sudo kpartx -l $RAW_FILE | awk "/loop[0-9]+p/"|wc -l) sudo udevadm settle # kpartx fails if no /dev/loop* exists, "losetup -f" prints first unused @@ -62,7 +61,7 @@ function extract_image() { # XXX: Parsing stdout is dangerous, would like a better way to discover # the device used for the image. - ROOT_LOOPDEV=$(sudo kpartx -av $WORKING/$RAW_FILE | \ + ROOT_LOOPDEV=$(sudo kpartx -av $RAW_FILE | \ awk "/loop[0-9]+$ROOT_PARTITON/ {print \$3}") # If running inside Docker, make our nodes manually, because udev will not be working. if [ -f /.dockerenv ]; then @@ -72,7 +71,7 @@ function extract_image() { echo "Error: Could not find /dev/mapper/$ROOT_LOOPDEV" exit 1 fi - EACTION="sudo kpartx -d $WORKING/$RAW_FILE ; $EACTION" + EACTION="sudo kpartx -d $RAW_FILE ; $EACTION" trap "$EACTION" EXIT mkdir $WORKING/mnt sudo mount /dev/mapper/$ROOT_LOOPDEV $WORKING/mnt diff --git a/elements/rhel/root.d/10-rhel-cloud-image b/elements/rhel/root.d/10-rhel-cloud-image index 90771df94..1571249fd 100755 --- a/elements/rhel/root.d/10-rhel-cloud-image +++ b/elements/rhel/root.d/10-rhel-cloud-image @@ -31,13 +31,12 @@ else WORKING=$(mktemp -d) EACTION="rm -r $WORKING" trap "$EACTION" EXIT - RAW_FILE=$(basename $BASE_IMAGE_FILE) - RAW_FILE=${RAW_FILE%.qcow2}.raw - qemu-img convert -f qcow2 -O raw $DIB_IMAGE_CACHE/$BASE_IMAGE_FILE $WORKING/$RAW_FILE + RAW_FILE=$(mktemp --tmpdir=$WORKING XXXXXX.raw) + qemu-img convert -f qcow2 -O raw $DIB_IMAGE_CACHE/$BASE_IMAGE_FILE $RAW_FILE MAGIC_BIT=p1 # NOTE: On RHEL, partprobe of /dev/loop0 does not create /dev/loop0p2, # while kpartx at least creates /dev/mapper/loop0p2. - LOOPDEV=$(sudo kpartx -av $WORKING/$RAW_FILE | awk "/loop[0-9]+$MAGIC_BIT/ {print \$3}") + LOOPDEV=$(sudo kpartx -av $RAW_FILE | awk "/loop[0-9]+$MAGIC_BIT/ {print \$3}") # If running inside Docker, make our nodes manually, because udev will not be working. if [ -f /.dockerenv ]; then sudo dmsetup --noudevsync mknodes @@ -48,7 +47,7 @@ else echo "Error: Could not find /dev/mapper/$LOOPDEV" exit 1 fi - EACTION="sudo kpartx -d $WORKING/$RAW_FILE;$EACTION" + EACTION="sudo kpartx -d $RAW_FILE;$EACTION" trap "$EACTION" EXIT mkdir $WORKING/mnt sudo mount /dev/mapper/$LOOPDEV $WORKING/mnt diff --git a/elements/ubuntu-core/root.d/10-cache-ubuntu-image b/elements/ubuntu-core/root.d/10-cache-ubuntu-image index ea7062317..550fdc2e8 100755 --- a/elements/ubuntu-core/root.d/10-cache-ubuntu-image +++ b/elements/ubuntu-core/root.d/10-cache-ubuntu-image @@ -52,13 +52,12 @@ else WORKING=$(mktemp -d) EACTION="rm -r $WORKING" trap "$EACTION" EXIT - RAW_FILE=$(basename $BASE_IMAGE_FILE) - RAW_FILE=${RAW_FILE%.img}.raw - qemu-img convert -f qcow2 -O raw $CACHED_FILE $WORKING/$RAW_FILE + RAW_FILE=$(mktemp --tmpdir=$WORKING XXXXXX.raw) + qemu-img convert -f qcow2 -O raw $CACHED_FILE $RAW_FILE MAGIC_BIT=p1 # NOTE: On RHEL, partprobe of /dev/loop0 does not create /dev/loop0p2, # while kpartx at least creates /dev/mapper/loop0p2. - LOOPDEV=$(sudo kpartx -av $WORKING/$RAW_FILE | awk "/loop[0-9]+$MAGIC_BIT/ {print \$3}") + LOOPDEV=$(sudo kpartx -av $RAW_FILE | awk "/loop[0-9]+$MAGIC_BIT/ {print \$3}") # If running inside Docker, make our nodes manually, because udev will not be working. if [ -f /.dockerenv ]; then sudo dmsetup --noudevsync mknodes @@ -69,7 +68,7 @@ else echo "Error: Could not find /dev/mapper/$LOOPDEV" exit 1 fi - EACTION="sudo kpartx -d $WORKING/$RAW_FILE;$EACTION" + EACTION="sudo kpartx -d $RAW_FILE;$EACTION" trap "$EACTION" EXIT mkdir $WORKING/mnt sudo mount /dev/mapper/$LOOPDEV $WORKING/mnt