Author: sobomax
Date: Fri Mar 22 21:31:21 2019
New Revision: 345425
URL: https://svnweb.freebsd.org/changeset/base/345425

Log:
  Make it possible to update TMPFS mount point from read-only to read-write
  and vice versa.
  
  Reviewed by:  delphij
  Approved by:  delphij
  MFC after:    2 weeks
  Differential Revision:        https://reviews.freebsd.org/D19682

Modified:
  head/sys/fs/tmpfs/tmpfs.h
  head/sys/fs/tmpfs/tmpfs_vfsops.c

Modified: head/sys/fs/tmpfs/tmpfs.h
==============================================================================
--- head/sys/fs/tmpfs/tmpfs.h   Fri Mar 22 19:43:50 2019        (r345424)
+++ head/sys/fs/tmpfs/tmpfs.h   Fri Mar 22 21:31:21 2019        (r345425)
@@ -325,6 +325,11 @@ LIST_HEAD(tmpfs_node_list, tmpfs_node);
  */
 struct tmpfs_mount {
        /*
+        * Original value of the "size" parameter, for reference purposes,
+        * mostly.
+        */
+       off_t                   tm_size_max;
+       /*
         * Maximum number of memory pages available for use by the file
         * system, set during mount time.  This variable must never be
         * used directly as it may be bigger than the current amount of

Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vfsops.c    Fri Mar 22 19:43:50 2019        
(r345424)
+++ head/sys/fs/tmpfs/tmpfs_vfsops.c    Fri Mar 22 21:31:21 2019        
(r345425)
@@ -88,7 +88,7 @@ static const char *tmpfs_opts[] = {
 };
 
 static const char *tmpfs_updateopts[] = {
-       "from", "export", NULL
+       "from", "export", "size", NULL
 };
 
 static int
@@ -134,6 +134,8 @@ tmpfs_node_fini(void *mem, int size)
        mtx_destroy(&node->tn_interlock);
 }
 
+#define TMPFS_SC(mp) ((struct tmpfs_mount *)(mp)->mnt_data)
+
 static int
 tmpfs_mount(struct mount *mp)
 {
@@ -141,7 +143,7 @@ tmpfs_mount(struct mount *mp)
            sizeof(struct tmpfs_dirent) + sizeof(struct tmpfs_node));
        struct tmpfs_mount *tmp;
        struct tmpfs_node *root;
-       int error;
+       int error, flags;
        bool nonc;
        /* Size counters. */
        u_quad_t pages;
@@ -161,9 +163,41 @@ tmpfs_mount(struct mount *mp)
                /* Only support update mounts for certain options. */
                if (vfs_filteropt(mp->mnt_optnew, tmpfs_updateopts) != 0)
                        return (EOPNOTSUPP);
-               if (vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0) !=
-                   ((struct tmpfs_mount *)mp->mnt_data)->tm_ronly)
-                       return (EOPNOTSUPP);
+               if (vfs_getopt_size(mp->mnt_optnew, "size", &size_max) == 0) {
+                       /*
+                        * On-the-fly resizing is not supported (yet). We still
+                        * need to have "size" listed as "supported", otherwise
+                        * trying to update fs that is listed in fstab with size
+                        * parameter, say trying to change rw to ro or vice
+                        * versa, would cause vfs_filteropt() to bail.
+                        */
+                       if (size_max != TMPFS_SC(mp)->tm_size_max)
+                               return (EOPNOTSUPP);
+               }
+               if (vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0) &&
+                   !(TMPFS_SC(mp)->tm_ronly)) {
+                       /* RW -> RO */
+                       error = VFS_SYNC(mp, MNT_WAIT);
+                       if (error)
+                               return (error);
+                       flags = WRITECLOSE;
+                       if (mp->mnt_flag & MNT_FORCE)
+                               flags |= FORCECLOSE;
+                       error = vflush(mp, 0, flags, curthread);
+                       if (error)
+                               return (error);
+                       TMPFS_SC(mp)->tm_ronly = 1;
+                       MNT_ILOCK(mp);
+                       mp->mnt_flag |= MNT_RDONLY;
+                       MNT_IUNLOCK(mp);
+               } else if (!vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0) &&
+                   TMPFS_SC(mp)->tm_ronly) {
+                       /* RO -> RW */
+                       TMPFS_SC(mp)->tm_ronly = 0;
+                       MNT_ILOCK(mp);
+                       mp->mnt_flag &= ~MNT_RDONLY;
+                       MNT_IUNLOCK(mp);
+               }
                return (0);
        }
 
@@ -229,6 +263,7 @@ tmpfs_mount(struct mount *mp)
        tmp->tm_maxfilesize = maxfilesize > 0 ? maxfilesize : OFF_MAX;
        LIST_INIT(&tmp->tm_nodes_used);
 
+       tmp->tm_size_max = size_max;
        tmp->tm_pages_max = pages;
        tmp->tm_pages_used = 0;
        new_unrhdr64(&tmp->tm_ino_unr, 2);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to