forked from pool/util-linux
167 lines
4.8 KiB
Diff
167 lines
4.8 KiB
Diff
From f4612577c942a3683b97632ad0b49671897c2070 Mon Sep 17 00:00:00 2001
|
|
From: Petr Uzel <petr.uzel@suse.cz>
|
|
Date: Thu, 17 Feb 2011 12:52:43 +0100
|
|
Subject: [PATCH] umount: allow unmounting loopdev specified by associated file
|
|
|
|
Make it possible to unmount a filesystem on a loop device if it is
|
|
specified by associated backing file. It does not attempt to unmount
|
|
anything if there are more than one loop device associated with the
|
|
given file.
|
|
|
|
Umount looks for associated loopdevice(s) only if umount is called
|
|
with the regular file as an argument.
|
|
|
|
Before:
|
|
mount -o loop -t ext2 img mnt
|
|
umount -v img
|
|
> Could not find /home/puzel/upstream/util-linux/img in mtab
|
|
> umount: img: not mounted
|
|
|
|
After:
|
|
mount -o loop -t ext2 img mnt
|
|
umount -v img
|
|
> img is associated with /dev/loop0, trying to unmount it
|
|
> /dev/loop0 has been unmounted
|
|
|
|
[kzak@redhat.com: - fix memory leak in lomount.c]
|
|
|
|
Addresses: https://bugzilla.novell.com/show_bug.cgi?id=666161
|
|
Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
|
|
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
---
|
|
mount/lomount.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
mount/lomount.h | 1 +
|
|
mount/umount.c | 22 ++++++++++++++++++++++
|
|
3 files changed, 76 insertions(+), 0 deletions(-)
|
|
|
|
Index: util-linux-2.19/mount/lomount.c
|
|
===================================================================
|
|
--- util-linux-2.19.orig/mount/lomount.c
|
|
+++ util-linux-2.19/mount/lomount.c
|
|
@@ -409,6 +409,51 @@ done:
|
|
return -1;
|
|
}
|
|
|
|
+/* Find loop device associated with given @filename. Used for unmounting loop
|
|
+ * device specified by associated backing file.
|
|
+ *
|
|
+ * returns: 1 no such device/error
|
|
+ * 2 more than one loop device associated with @filename
|
|
+ * 0 exactly one loop device associated with @filename
|
|
+ * (@loopdev points to string containing full device name)
|
|
+ */
|
|
+int
|
|
+find_loopdev_by_backing_file(const char *filename, char **loopdev)
|
|
+{
|
|
+ struct looplist ll;
|
|
+ struct stat filestat;
|
|
+ int fd;
|
|
+ int devs_n = 0; /* number of loop devices found */
|
|
+ char* devname = NULL;
|
|
+
|
|
+ if (stat(filename, &filestat) == -1) {
|
|
+ perror(filename);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
|
|
+ error(_("%s: /dev directory does not exist."), progname);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ while((devs_n < 2) && (fd = looplist_next(&ll)) != -1) {
|
|
+ if (is_associated(fd, &filestat, 0, 0) == 1) {
|
|
+ if (!devname)
|
|
+ devname = xstrdup(ll.name);
|
|
+ devs_n++;
|
|
+ }
|
|
+ close(fd);
|
|
+ }
|
|
+ looplist_close(&ll);
|
|
+
|
|
+ if (devs_n == 1) {
|
|
+ *loopdev = devname;
|
|
+ return 0; /* exactly one loopdev */
|
|
+ }
|
|
+ free(devname);
|
|
+ return devs_n ? 2 : 1; /* more loopdevs or error */
|
|
+}
|
|
+
|
|
#ifdef MAIN
|
|
|
|
static int
|
|
@@ -581,6 +626,7 @@ show_associated_loop_devices(char *filen
|
|
return 0;
|
|
}
|
|
|
|
+
|
|
#endif /* MAIN */
|
|
|
|
/* check if the loopfile is already associated with the same given
|
|
@@ -1054,6 +1100,13 @@ find_unused_loop_device (void) {
|
|
return 0;
|
|
}
|
|
|
|
+int
|
|
+find_loopdev_by_backing_file(const char *filename, char **loopdev)
|
|
+{
|
|
+ mutter();
|
|
+ return 1;
|
|
+}
|
|
+
|
|
#endif /* !LOOP_SET_FD */
|
|
|
|
#ifdef MAIN
|
|
Index: util-linux-2.19/mount/lomount.h
|
|
===================================================================
|
|
--- util-linux-2.19.orig/mount/lomount.h
|
|
+++ util-linux-2.19/mount/lomount.h
|
|
@@ -11,6 +11,7 @@ extern char * find_unused_loop_device(vo
|
|
extern int loopfile_used_with(char *devname, const char *filename, unsigned long long offset);
|
|
extern char *loopfile_used (const char *filename, unsigned long long offset);
|
|
extern char *loopdev_get_loopfile(const char *device);
|
|
+extern int find_loopdev_by_backing_file(const char *filename, char **loopdev);
|
|
|
|
|
|
#define SETLOOP_RDONLY (1<<0) /* Open loop read-only */
|
|
Index: util-linux-2.19/mount/umount.c
|
|
===================================================================
|
|
--- util-linux-2.19.orig/mount/umount.c
|
|
+++ util-linux-2.19/mount/umount.c
|
|
@@ -502,6 +502,7 @@ umount_file (char *arg) {
|
|
const char *file, *options;
|
|
int fstab_has_user, fstab_has_users, fstab_has_owner, fstab_has_group;
|
|
int ok;
|
|
+ struct stat statbuf;
|
|
|
|
if (!*arg) { /* "" would be expanded to `pwd` */
|
|
die(2, _("Cannot unmount \"\"\n"));
|
|
@@ -509,6 +510,27 @@ umount_file (char *arg) {
|
|
}
|
|
|
|
file = canonicalize(arg); /* mtab paths are canonicalized */
|
|
+
|
|
+ /* if file is a regular file, check if it is associated
|
|
+ * with some loop device
|
|
+ */
|
|
+ if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode)) {
|
|
+ char *loopdev = NULL;
|
|
+ switch (find_loopdev_by_backing_file(file, &loopdev)) {
|
|
+ case 0:
|
|
+ if (verbose)
|
|
+ printf(_("%s is associated with %s, trying to unmount it\n"),
|
|
+ arg, loopdev);
|
|
+ file = loopdev;
|
|
+ break;
|
|
+ case 2:
|
|
+ if (verbose)
|
|
+ printf(_("%s is associated with more than one loop device: not unmounting\n"),
|
|
+ arg);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (verbose > 1)
|
|
printf(_("Trying to unmount %s\n"), file);
|
|
|