Index: head/sys/fs/tmpfs/tmpfs.h =================================================================== --- head/sys/fs/tmpfs/tmpfs.h +++ head/sys/fs/tmpfs/tmpfs.h @@ -325,6 +325,11 @@ */ 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 Index: head/sys/fs/tmpfs/tmpfs_vfsops.c =================================================================== --- head/sys/fs/tmpfs/tmpfs_vfsops.c +++ head/sys/fs/tmpfs/tmpfs_vfsops.c @@ -88,7 +88,7 @@ }; static const char *tmpfs_updateopts[] = { - "from", "export", NULL + "from", "export", "size", NULL }; static int @@ -134,6 +134,8 @@ 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 @@ 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 @@ /* 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 @@ 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);