summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2020-06-17 19:29:56 +0100
committerJo-Philipp Wich <jo@mein.io>2020-06-17 23:20:48 +0200
commitd34ea8eb1e12259a315cdef7aa0cd3ceaea68e00 (patch)
treeb8671c3e1bcc5e6b4857a0cb37940554ce2efcee
parent84269037b75de93bdd4ea75b7f50ba77ba976377 (diff)
downloadfstools-d34ea8eb1e12259a315cdef7aa0cd3ceaea68e00.tar.gz
Use autoclear for overlay loopback device
During a sysupgrade on a block-based device, the partition table might get updated. The partitions have to be completely unused by the time partx is invoked, or it fails thus: partx: /dev/mmcblk1: error deleting partition 3 partx: /dev/mmcblk1: error adding partition 3 That's cosmetic in some cases, but in others where the old root partition overlaps with the new partition where the config is stored during the reboot, it causes a sysugprade failure (resulting in the backup being lost and a completely clean system image). Although we carefully unmount the root and overlay file systems, the problem is that the loopback device used for the overlay isn't being torn down, and it still has a refcount on the root block partition (in the above case, /dev/mmcblk1p3). Installing losetup and adding 'losetup -D' to the switch_to_ramfs() function makes it work nicely. But the better option that doesn't add a new dependency is to use the autoclear flag when setting up the loop device, so it goes away automatically when the overlay file system is unmounted. To make that work sanely, we have to *not* close the fd right after configuring it — or it'll go away immediately. We could store the fd in the volume struct and either add destructor method or close it after performing the mount… but honestly it just seems simpler and saner to "leak" the fd in the knowledge that it'll get closed when the process exits in a few milliseconds anyway. We can revisit that if anyone really feels strongly about it. Dissent is best expressed in 'diff -up' form. Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r--libfstools/rootdisk.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/libfstools/rootdisk.c b/libfstools/rootdisk.c
index 5a6dcb9..dc861a9 100644
--- a/libfstools/rootdisk.c
+++ b/libfstools/rootdisk.c
@@ -231,12 +231,19 @@ static int rootdisk_create_loop(struct rootdev_volume *p)
snprintf((char *) info.lo_file_name, sizeof(info.lo_file_name), "%s",
rootdev);
info.lo_offset = p->offset;
+ info.lo_flags |= LO_FLAGS_AUTOCLEAR;
if (ioctl(fd, LOOP_SET_STATUS64, &info) != 0) {
ioctl(fd, LOOP_CLR_FD, 0);
continue;
}
+ /*
+ * Don't close fd. Leave it open until this process exits, to avoid
+ * the autoclear from happening too soon.
+ */
+ fd = -1;
+
ret = 0;
break;
}