Author: jh
Date: Sat Feb 19 14:27:14 2011
New Revision: 218852
URL: http://svn.freebsd.org/changeset/base/218852

Log:
  Don't restore old mount options and flags if VFS_MOUNT(9) succeeds but
  vfs_export() fails. Restoring old options and flags after successful
  VFS_MOUNT(9) call may cause the file system internal state to become
  inconsistent with mount options and flags. Specifically the FFS super
  block fs_ronly field and the MNT_RDONLY flag may get out of sync.
  
  PR:           kern/133614
  Discussed on: freebsd-hackers

Modified:
  head/sys/kern/vfs_mount.c

Modified: head/sys/kern/vfs_mount.c
==============================================================================
--- head/sys/kern/vfs_mount.c   Sat Feb 19 13:23:13 2011        (r218851)
+++ head/sys/kern/vfs_mount.c   Sat Feb 19 14:27:14 2011        (r218852)
@@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$");
 #define        VFS_MOUNTARG_SIZE_MAX   (1024 * 64)
 
 static int     vfs_domount(struct thread *td, const char *fstype,
-                   char *fspath, int fsflags, void *fsdata);
+                   char *fspath, int fsflags, struct vfsoptlist **optlist);
 static void    free_mntarg(struct mntarg *ma);
 
 static int     usermount = 0;
@@ -667,7 +667,7 @@ vfs_donmount(struct thread *td, int fsfl
                goto bail;
        }
 
-       error = vfs_domount(td, fstype, fspath, fsflags, optlist);
+       error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
 bail:
        /* copyout the errmsg */
        if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
@@ -683,7 +683,7 @@ bail:
                }
        }
 
-       if (error != 0)
+       if (optlist != NULL)
                vfs_freeopts(optlist);
        return (error);
 }
@@ -762,12 +762,12 @@ mount(td, uap)
  */
 static int
 vfs_domount_first(
-       struct thread *td,      /* Calling thread. */
-       struct vfsconf *vfsp,   /* File system type. */
-       char *fspath,           /* Mount path. */
-       struct vnode *vp,       /* Vnode to be covered. */
-       int fsflags,            /* Flags common to all filesystems. */
-       void *fsdata            /* Options local to the filesystem. */
+       struct thread *td,              /* Calling thread. */
+       struct vfsconf *vfsp,           /* File system type. */
+       char *fspath,                   /* Mount path. */
+       struct vnode *vp,               /* Vnode to be covered. */
+       int fsflags,                    /* Flags common to all filesystems. */
+       struct vfsoptlist **optlist     /* Options local to the filesystem. */
        )
 {
        struct vattr va;
@@ -807,7 +807,7 @@ vfs_domount_first(
        /* Allocate and initialize the filesystem. */
        mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred);
        /* XXXMAC: pass to vfs_mount_alloc? */
-       mp->mnt_optnew = fsdata;
+       mp->mnt_optnew = *optlist;
        /* Set the mount level flags. */
        mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
 
@@ -830,6 +830,7 @@ vfs_domount_first(
        if (mp->mnt_opt != NULL)
                vfs_freeopts(mp->mnt_opt);
        mp->mnt_opt = mp->mnt_optnew;
+       *optlist = NULL;
        (void)VFS_STATFS(mp, &mp->mnt_stat);
 
        /*
@@ -872,16 +873,16 @@ vfs_domount_first(
  */
 static int
 vfs_domount_update(
-       struct thread *td,      /* Calling thread. */
-       struct vnode *vp,       /* Mount point vnode. */
-       int fsflags,            /* Flags common to all filesystems. */
-       void *fsdata            /* Options local to the filesystem. */
+       struct thread *td,              /* Calling thread. */
+       struct vnode *vp,               /* Mount point vnode. */
+       int fsflags,                    /* Flags common to all filesystems. */
+       struct vfsoptlist **optlist     /* Options local to the filesystem. */
        )
 {
        struct oexport_args oexport;
        struct export_args export;
        struct mount *mp;
-       int error, flag;
+       int error, export_error, flag;
 
        mtx_assert(&Giant, MA_OWNED);
        ASSERT_VOP_ELOCKED(vp, __func__);
@@ -932,7 +933,7 @@ vfs_domount_update(
        if ((mp->mnt_flag & MNT_ASYNC) == 0)
                mp->mnt_kern_flag &= ~MNTK_ASYNC;
        MNT_IUNLOCK(mp);
-       mp->mnt_optnew = fsdata;
+       mp->mnt_optnew = *optlist;
        vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
 
        /*
@@ -942,11 +943,12 @@ vfs_domount_update(
         */
        error = VFS_MOUNT(mp);
 
+       export_error = 0;
        if (error == 0) {
                /* Process the export option. */
                if (vfs_copyopt(mp->mnt_optnew, "export", &export,
                    sizeof(export)) == 0) {
-                       error = vfs_export(mp, &export);
+                       export_error = vfs_export(mp, &export);
                } else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport,
                    sizeof(oexport)) == 0) {
                        export.ex_flags = oexport.ex_flags;
@@ -958,7 +960,7 @@ vfs_domount_update(
                        export.ex_masklen = oexport.ex_masklen;
                        export.ex_indexfile = oexport.ex_indexfile;
                        export.ex_numsecflavors = 0;
-                       error = vfs_export(mp, &export);
+                       export_error = vfs_export(mp, &export);
                }
        }
 
@@ -988,6 +990,7 @@ vfs_domount_update(
        if (mp->mnt_opt != NULL)
                vfs_freeopts(mp->mnt_opt);
        mp->mnt_opt = mp->mnt_optnew;
+       *optlist = NULL;
        (void)VFS_STATFS(mp, &mp->mnt_stat);
        /*
         * Prevent external consumers of mount options from reading
@@ -1005,7 +1008,7 @@ end:
        vp->v_iflag &= ~VI_MOUNT;
        VI_UNLOCK(vp);
        vrele(vp);
-       return (error);
+       return (error != 0 ? error : export_error);
 }
 
 /*
@@ -1013,11 +1016,11 @@ end:
  */
 static int
 vfs_domount(
-       struct thread *td,      /* Calling thread. */
-       const char *fstype,     /* Filesystem type. */
-       char *fspath,           /* Mount path. */
-       int fsflags,            /* Flags common to all filesystems. */
-       void *fsdata            /* Options local to the filesystem. */
+       struct thread *td,              /* Calling thread. */
+       const char *fstype,             /* Filesystem type. */
+       char *fspath,                   /* Mount path. */
+       int fsflags,                    /* Flags common to all filesystems. */
+       struct vfsoptlist **optlist     /* Options local to the filesystem. */
        )
 {
        struct vfsconf *vfsp;
@@ -1087,9 +1090,9 @@ vfs_domount(
        vp = nd.ni_vp;
        if ((fsflags & MNT_UPDATE) == 0) {
                error = vfs_domount_first(td, vfsp, fspath, vp, fsflags,
-                   fsdata);
+                   optlist);
        } else {
-               error = vfs_domount_update(td, vp, fsflags, fsdata);
+               error = vfs_domount_update(td, vp, fsflags, optlist);
        }
        mtx_unlock(&Giant);
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to