]> err.no Git - util-linux/commitdiff
mount: read /sys for loopdev backing file
authorKarel Zak <kzak@redhat.com>
Wed, 1 Dec 2010 22:02:17 +0000 (23:02 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 1 Dec 2010 22:02:17 +0000 (23:02 +0100)
On systems without /etc/mtab (or everywhere if kernel >= 2.6.37)
we use loop autoclear flag and then the backing file name is not
stored in /etc/mtab. mount(8) uses sysfs to get the filename (or
LOOP_GET_STATU* ioctls on old kernels).

Signed-off-by: Karel Zak <kzak@redhat.com>
mount/lomount.c
mount/lomount.h
mount/mount.c

index 90149536a5ccbfaaae9d340a2de1acb44e4b4b8b..4d99d9f6f374df60c95df0cf84b3c00e98951a34 100644 (file)
@@ -109,6 +109,33 @@ static char *loopfile_from_sysfs(const char *device)
        return res;
 }
 
+char *loopdev_get_loopfile(const char *device)
+{
+       char *res = loopfile_from_sysfs(device);
+
+       if (!res) {
+               struct loop_info lo;
+               struct loop_info64 lo64;
+               int fd;
+
+               if ((fd = open(device, O_RDONLY)) < 0)
+                       return NULL;
+
+               if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0) {
+                       lo64.lo_file_name[LO_NAME_SIZE-2] = '*';
+                       lo64.lo_file_name[LO_NAME_SIZE-1] = 0;
+                       res = xstrdup((char *) lo64.lo_file_name);
+
+               } else if (ioctl(fd, LOOP_GET_STATUS, &lo) == 0) {
+                       lo.lo_name[LO_NAME_SIZE-2] = '*';
+                       lo.lo_name[LO_NAME_SIZE-1] = 0;
+                       res = xstrdup((char *) lo.lo_name);
+               }
+               close(fd);
+       }
+       return res;
+}
+
 int
 is_loop_device (const char *device) {
        struct stat st;
index 59108d4085683ee1c0de6d487669fc5bfbfa9ca8..de8b76bf4f13a824b73ce83090766f782bfe0b8a 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef UTIL_LINUX_LOMOUNT_H
+#define UTIL_LINUX_LOMOUNT_H
+
 extern int set_loop(const char *, const char *, unsigned long long, unsigned long long,
                    const char *, int, int *);
 extern int del_loop(const char *);
@@ -7,6 +10,10 @@ extern char * find_unused_loop_device(void);
 
 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);
+
 
 #define SETLOOP_RDONLY     (1<<0)  /* Open loop read-only */
 #define SETLOOP_AUTOCLEAR  (1<<1)  /* Automatically detach loop on close (2.6.25?) */
+
+#endif /* !UTIL_LINUX_LOMOUNT_H */
index 9faa6a5b6fa67b1a72b993434aef9a44b7ddfe8b..8c30263cb1a1a3fe666bfba8cfca8c7636030ca5 100644 (file)
@@ -249,9 +249,23 @@ parse_string_opt(char *s) {
 /* Report on a single mount.  */
 static void
 print_one (const struct my_mntent *me) {
+
+       char *fsname = NULL;
+
        if (mount_quiet)
                return;
-       printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
+
+       /* users assume backing file name rather than /dev/loopN in
+        * mount(8) output if the device has been initialized by mount(8).
+        */
+       if (strncmp(me->mnt_fsname, "/dev/loop", 9) == 0 &&
+           is_loop_autoclear(me->mnt_fsname))
+               fsname = loopdev_get_loopfile(me->mnt_fsname);
+
+       if (!fsname)
+               fsname = (char *) me->mnt_fsname;
+
+       printf ("%s on %s", fsname, me->mnt_dir);
        if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
                printf (" type %s", me->mnt_type);
        if (me->mnt_opts != NULL)
@@ -1206,10 +1220,20 @@ loop_check(const char **spec, const char **type, int *flags,
       if (verbose)
        printf(_("mount: skipping the setup of a loop device\n"));
     } else {
-      /* use autoclear loopdev on system without regular mtab only */
-      int loop_opts = mtab_is_writable() ? 0 : SETLOOP_AUTOCLEAR;
+      int loop_opts;
       int res;
 
+      /* since 2.6.37 we don't have to store backing filename to mtab
+       * because kernel provides the name in /sys
+       */
+      if (get_linux_version() >= KERNEL_VERSION(2, 6, 37) ||
+         mtab_is_writable() == 0) {
+
+       if (verbose)
+         printf(_("mount: enabling autoclear loopdev flag\n"));
+       loop_opts = SETLOOP_AUTOCLEAR;
+      }
+
       if (*flags & MS_RDONLY)
         loop_opts |= SETLOOP_RDONLY;