From db3b5b76a783ddcd247e9cf3299781167e75f9f9 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 1 Dec 2010 23:02:17 +0100 Subject: [PATCH] mount: read /sys for loopdev backing file 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 --- mount/lomount.c | 27 +++++++++++++++++++++++++++ mount/lomount.h | 7 +++++++ mount/mount.c | 30 +++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/mount/lomount.c b/mount/lomount.c index 90149536..4d99d9f6 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -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; diff --git a/mount/lomount.h b/mount/lomount.h index 59108d40..de8b76bf 100644 --- a/mount/lomount.h +++ b/mount/lomount.h @@ -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 */ diff --git a/mount/mount.c b/mount/mount.c index 9faa6a5b..8c30263c 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -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; -- 2.39.5