mount.gfs2: Fix mounting of regular files with -o loop
PATCH 1/1 mount.gfs2: Fix mounting of regular files with -o loop
When we use -o loop, mount(8) sets up the loop device and passes loop=/dev/loopN to mount.gfs2, which currently naively passes this option to mount(2). As gfs2 doesn't recognise the loop option, mounting fails with EINVAL.
This patch stops mount.gfs2 from passing loop=/dev/loopN to mount(2) to fix this problem and also makes sure this option appears in /etc/mtab so that umount(8) can automatically free up the loop device on unmount.
rhbz#729071
--- gfs2/mount/util.c | 29 ++++++++++++++++++++++++++--- gfs2/mount/util.h | 1 + 2 files changed, 27 insertions(+), 3 deletions(-)
gfs2/mount/util.c +26 -3
@@ -150,6 +150,16 @@ void parse_opts(struct mount_options *mo)continue ; } +/* mount(8) will have already set up the loop device for us so +we can safely ignore the loop= option it provides and avoid +getting an EINVAL from gfs2. However, we still need to make +sure the option appears in mtab so that umount(8) can +automatically free up the loop device. */ +if (!strncmp ("loop" , o,4 )) { +strncpy (mo->loopopt, o,PATH_MAX ); +continue ; + } +if (extra_len +1 +strlen (o) >PATH_MAX )die ("extra options string is too long\n" );
@@ -261,6 +271,8 @@ void read_proc_mounts(struct mount_options *mo)char save_opts[PATH_MAX ];char save_device[PATH_MAX ];int found =0 ; +int freq =0 ; +int passno =0 ;struct stat st_mo_dev, st_mounts_dev; file =fopen ("/proc/mounts" ,"r" );
@@ -274,8 +286,14 @@ void read_proc_mounts(struct mount_options *mo) }while (fgets (line,PATH_MAX , file)) { -if (sscanf (line,"%s %s %s %s" , device, path, type, opts) !=4 ) -continue ; +if (mo->loopopt[0 ] =='\0' ) { +if (sscanf (line,"%s %s %s %s" , device, path, type, opts) !=4 ) +continue ; + }else { +if (sscanf (line,"%s %s %s %s %d %d" , + device, path, type, opts, &freq, &passno) !=6 ) +continue ; + }if (strcmp (path, mo->dir)) {if (!strchr (path,'\\' ))continue ;
@@ -301,7 +319,11 @@ void read_proc_mounts(struct mount_options *mo)strncpy (save_device, device,PATH_MAX );strncpy (save_opts, opts,PATH_MAX ); -strncpy (save_line, line,PATH_MAX ); +if (mo->loopopt[0 ] !='\0' ) +snprintf (save_line,PATH_MAX ,"%s %s %s %s,%s %d %d\n" , + device, path, type, opts, mo->loopopt, freq, passno); +else +strncpy (save_line, line,PATH_MAX ); found =1 ; }
@@ -318,6 +340,7 @@ void read_proc_mounts(struct mount_options *mo)log_debug ("read_proc_mounts: device = \"%s\"" , mo->specified_dev);log_debug ("read_proc_mounts: dm device = \"%s\"" , mo->dev);log_debug ("read_proc_mounts: opts = \"%s\"" , mo->opts); +log_debug ("read_proc_mounts: proc_entry = \"%s\"" , mo->proc_entry); }static void gfs2_inum_in (struct gfs2_inum *no,char *buf)
gfs2/mount/util.h +1 -0
@@ -50,6 +50,7 @@ struct mount_options {char dev[PATH_MAX +1 ];char dir[PATH_MAX +1 ];char opts[PATH_MAX +1 ]; +char loopopt[PATH_MAX +1 ];char hostdata[PATH_MAX +1 ];char extra[PATH_MAX +1 ];char extra_plus[PATH_MAX +1 ];
Signature · 1 line
1.7.1
PATCH 1/1 mount.gfs2: Fix mounting of regular files with -o loop
Hi,
Looks good to me. Did you test it with -o remount to be sure it does the right thing for that too?
Steve.
Quoted 97 lines · Andrew Price
When we use -o loop, mount(8) sets up the loop device and passes loop=/dev/loopN to mount.gfs2, which currently naively passes this option to mount(2). As gfs2 doesn't recognise the loop option, mounting fails with EINVAL.
This patch stops mount.gfs2 from passing loop=/dev/loopN to mount(2) to fix this problem and also makes sure this option appears in
/etc/mtabso that umount(8) can automatically free up the loop device on unmount.rhbz#729071
Signed-off-by Andrew Price <[email protected]>--- gfs2/mount/util.c | 29 ++++++++++++++++++++++++++--- gfs2/mount/util.h | 1 + 2 files changed, 27 insertions(+), 3 deletions(-)gfs2/mount/util.c +26
-3@@ -150,6 +150,16 @@ void parse_opts(struct mount_options *mo)continue ; } +/* mount(8) will have already set up the loop device for us so +we can safely ignore the loop= option it provides and avoid +getting an EINVAL from gfs2. However, we still need to make +sure the option appears in mtab so that umount(8) can +automatically free up the loop device. */ +if (!strncmp ("loop" , o,4 )) { +strncpy (mo->loopopt, o,PATH_MAX ); +continue ; + } +if (extra_len +1 +strlen (o) >PATH_MAX )die ("extra options string is too long\n" );@@ -261,6 +271,8 @@ void read_proc_mounts(struct mount_options *mo)char save_opts[PATH_MAX ];char save_device[PATH_MAX ];int found =0 ; +int freq =0 ; +int passno =0 ;struct stat st_mo_dev, st_mounts_dev; file =fopen ("/proc/mounts" ,"r" );@@ -274,8 +286,14 @@ void read_proc_mounts(struct mount_options *mo) }while (fgets (line,PATH_MAX , file)) { -if (sscanf (line,"%s %s %s %s" , device, path, type, opts) !=4 ) -continue ; +if (mo->loopopt[0 ] =='\0' ) { +if (sscanf (line,"%s %s %s %s" , device, path, type, opts) !=4 ) +continue ; + }else { +if (sscanf (line,"%s %s %s %s %d %d" , + device, path, type, opts, &freq, &passno) !=6 ) +continue ; + }if (strcmp (path, mo->dir)) {if (!strchr (path,'\\' ))continue ;@@ -301,7 +319,11 @@ void read_proc_mounts(struct mount_options *mo)strncpy (save_device, device,PATH_MAX );strncpy (save_opts, opts,PATH_MAX ); -strncpy (save_line, line,PATH_MAX ); +if (mo->loopopt[0 ] !='\0' ) +snprintf (save_line,PATH_MAX ,"%s %s %s %s,%s %d %d\n" , + device, path, type, opts, mo->loopopt, freq, passno); +else +strncpy (save_line, line,PATH_MAX ); found =1 ; }@@ -318,6 +340,7 @@ void read_proc_mounts(struct mount_options *mo)log_debug ("read_proc_mounts: device = \"%s\"" , mo->specified_dev);log_debug ("read_proc_mounts: dm device = \"%s\"" , mo->dev);log_debug ("read_proc_mounts: opts = \"%s\"" , mo->opts); +log_debug ("read_proc_mounts: proc_entry = \"%s\"" , mo->proc_entry); }static void gfs2_inum_in (struct gfs2_inum *no,char *buf)gfs2/mount/util.h +1
-0@@ -50,6 +50,7 @@ struct mount_options {char dev[PATH_MAX +1 ];char dir[PATH_MAX +1 ];char opts[PATH_MAX +1 ]; +char loopopt[PATH_MAX +1 ];char hostdata[PATH_MAX +1 ];char extra[PATH_MAX +1 ];char extra_plus[PATH_MAX +1 ];
PATCH 1/1 mount.gfs2: Fix mounting of regular files with -o loop
Quoted 4 lines · Steven Whitehouse
Hi,
Looks good to me. Did you test it with -o remount to be sure it does the right thing for that too?
Yep, testing with -o remount looks fine:
(I added the loop option when testing with remount just to check that it was completely ignored in the remount case and wasn't doubled up)
[root at rhel6-01 mount]# mount -o rw,loop,noatime sparse-file /mnt [root at rhel6-01 mount]# mount | grep gfs2/dev/loop0 on /mnt type gfs2 (rw,noatime,localflocks,localcaching,loop=/dev/loop0) [root at rhel6-01 mount]# mount -vv -o remount,ro,loop /mnt mount /dev/loop0 /mntparse_opts: opts = "ro,remount,noatime,loop=/dev/loop0,localflocks,localcaching"
set flag 1 for "ro", flags = 1
set flag 20 for "remount", flags = 21
set flag 400 for "noatime", flags = 421
add extra localflocks
add extra localcachingparse_opts: flags = 421parse_opts: extra = "localflocks,localcaching"parse_opts: hostdata = ""parse_opts: lockproto = ""parse_opts: locktable = ""
mount(2) okread_proc_mounts: device = "/dev/loop0"read_proc_mounts: dm device = "/dev/loop0"read_proc_mounts: opts = "ro,noatime,localflocks,localcaching"read_proc_mounts: proc_entry = "/dev/loop0 /mnt gfs2 ro,noatime,localflocks,localcaching,loop=/dev/loop0 0 0 "
[root at rhel6-01 mount]# mount | grep gfs2/dev/loop0 on /mnt type gfs2 (ro,noatime,localflocks,localcaching,loop=/dev/loop0)
Andy