Skip to content

Commit 0f4fd69

Browse files
committed
tmpfs: Overhaul option handling on remount
On remount, we must accept all the same options as on initial mount. For parameters which we're unable to modify on the fly, fail only if the new value is different from the existing one. PR: 295096 MFC after: 1 week Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D57044 (cherry picked from commit 1cfc208)
1 parent f3ded0f commit 0f4fd69

1 file changed

Lines changed: 62 additions & 38 deletions

File tree

sys/fs/tmpfs/tmpfs_vfsops.c

Lines changed: 62 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,6 @@ static const char *tmpfs_opts[] = {
9393
"export", "union", "nonc", "nomtime", "nosymfollow", "pgread", NULL
9494
};
9595

96-
static const char *tmpfs_updateopts[] = {
97-
"from", "easize", "export", "nomtime", "size", "nosymfollow", NULL
98-
};
99-
10096
static int
10197
tmpfs_update_mtime_lazy_filter(struct vnode *vp, void *arg)
10298
{
@@ -325,6 +321,7 @@ tmpfs_mount(struct mount *mp)
325321
sizeof(struct tmpfs_dirent) + sizeof(struct tmpfs_node));
326322
struct tmpfs_mount *tmp;
327323
struct tmpfs_node *root;
324+
struct vfsoptlist *opts;
328325
int error;
329326
bool nomtime, nonc, pgread;
330327
/* Size counters. */
@@ -338,44 +335,71 @@ tmpfs_mount(struct mount *mp)
338335

339336
struct vattr va;
340337

341-
if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts))
338+
opts = mp->mnt_optnew;
339+
if (vfs_filteropt(opts, tmpfs_opts))
342340
return (EINVAL);
343341

344342
if (mp->mnt_flag & MNT_UPDATE) {
345-
/* Only support update mounts for certain options. */
346-
if (vfs_filteropt(mp->mnt_optnew, tmpfs_updateopts) != 0)
347-
return (EOPNOTSUPP);
348343
tmp = VFS_TO_TMPFS(mp);
349-
if (vfs_getopt_size(mp->mnt_optnew, "size", &size_max) == 0) {
350-
/*
351-
* On-the-fly resizing is not supported (yet). We still
352-
* need to have "size" listed as "supported", otherwise
353-
* trying to update fs that is listed in fstab with size
354-
* parameter, say trying to change rw to ro or vice
355-
* versa, would cause vfs_filteropt() to bail.
356-
*/
357-
if (size_max != tmp->tm_size_max)
358-
return (EOPNOTSUPP);
359-
}
360-
if (vfs_getopt_size(mp->mnt_optnew, "easize", &ea_max_size) == 0) {
344+
345+
/*
346+
* These options cannot (yet) be modified on the fly, but
347+
* mount(8) will still pass them when remounting, so we
348+
* will silently ignore them as long as the value is
349+
* unchanged.
350+
*/
351+
if (vfs_scanopt(opts, "gid", "%d", &root_gid) == 1 &&
352+
root_gid != tmp->tm_root->tn_gid)
353+
return (EOPNOTSUPP);
354+
if (vfs_scanopt(opts, "uid", "%d", &root_uid) == 1 &&
355+
root_uid != tmp->tm_root->tn_uid)
356+
return (EOPNOTSUPP);
357+
if (vfs_scanopt(opts, "mode", "%ho", &root_mode) == 1 &&
358+
(root_mode & S_IFMT) != (tmp->tm_root->tn_mode & S_IFMT))
359+
return (EOPNOTSUPP);
360+
if (vfs_getopt_size(opts, "inodes", &nodes_max) == 0 &&
361+
nodes_max != 0 && nodes_max != tmp->tm_nodes_max)
362+
return (EOPNOTSUPP);
363+
if (vfs_getopt_size(opts, "size", &size_max) == 0 &&
364+
size_max != 0 && size_max != tmp->tm_size_max)
365+
return (EOPNOTSUPP);
366+
if (vfs_getopt_size(opts, "maxfilesize", &maxfilesize) == 0 &&
367+
maxfilesize != 0 && maxfilesize != tmp->tm_maxfilesize)
368+
return (EOPNOTSUPP);
369+
if (tmp->tm_nonc !=
370+
(vfs_getopt(opts, "nonc", NULL, NULL) == 0))
371+
return (EOPNOTSUPP);
372+
if (tmp->tm_pgread !=
373+
(vfs_getopt(opts, "pgread", NULL, NULL) == 0))
374+
return (EOPNOTSUPP);
375+
376+
/*
377+
* These options can be modified.
378+
*/
379+
if (vfs_getopt_size(opts, "easize", &ea_max_size) != 0)
361380
tmp->tm_ea_memory_max = ea_max_size;
362-
}
363-
if (vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0) &&
364-
!tmp->tm_ronly) {
381+
tmp->tm_nomtime = (vfs_getopt(opts, "nomtime", NULL, 0) == 0);
382+
383+
/*
384+
* Handle read-write to read-only or vice versa.
385+
*/
386+
if (vfs_flagopt(opts, "ro", NULL, 0) && !tmp->tm_ronly) {
365387
/* RW -> RO */
366388
return (tmpfs_rw_to_ro(mp));
367-
} else if (!vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0) &&
368-
tmp->tm_ronly) {
389+
}
390+
if (!vfs_flagopt(opts, "ro", NULL, 0) && tmp->tm_ronly) {
369391
/* RO -> RW */
370392
tmp->tm_ronly = 0;
371393
MNT_ILOCK(mp);
372394
mp->mnt_flag &= ~MNT_RDONLY;
373395
MNT_IUNLOCK(mp);
374396
}
375-
tmp->tm_nomtime = vfs_getopt(mp->mnt_optnew, "nomtime", NULL,
376-
0) == 0;
397+
398+
/*
399+
* Check if fast path lookup is still supported.
400+
*/
377401
MNT_ILOCK(mp);
378-
if ((mp->mnt_flag & MNT_UNION) == 0) {
402+
if (!tmp->tm_nonc && (mp->mnt_flag & MNT_UNION) == 0) {
379403
mp->mnt_kern_flag |= MNTK_FPLOOKUP;
380404
} else {
381405
mp->mnt_kern_flag &= ~MNTK_FPLOOKUP;
@@ -391,25 +415,25 @@ tmpfs_mount(struct mount *mp)
391415
return (error);
392416

393417
if (mp->mnt_cred->cr_ruid != 0 ||
394-
vfs_scanopt(mp->mnt_optnew, "gid", "%d", &root_gid) != 1)
418+
vfs_scanopt(opts, "gid", "%d", &root_gid) != 1)
395419
root_gid = va.va_gid;
396420
if (mp->mnt_cred->cr_ruid != 0 ||
397-
vfs_scanopt(mp->mnt_optnew, "uid", "%d", &root_uid) != 1)
421+
vfs_scanopt(opts, "uid", "%d", &root_uid) != 1)
398422
root_uid = va.va_uid;
399423
if (mp->mnt_cred->cr_ruid != 0 ||
400-
vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1)
424+
vfs_scanopt(opts, "mode", "%ho", &root_mode) != 1)
401425
root_mode = va.va_mode;
402-
if (vfs_getopt_size(mp->mnt_optnew, "inodes", &nodes_max) != 0)
426+
if (vfs_getopt_size(opts, "inodes", &nodes_max) != 0)
403427
nodes_max = 0;
404-
if (vfs_getopt_size(mp->mnt_optnew, "size", &size_max) != 0)
428+
if (vfs_getopt_size(opts, "size", &size_max) != 0)
405429
size_max = 0;
406-
if (vfs_getopt_size(mp->mnt_optnew, "maxfilesize", &maxfilesize) != 0)
430+
if (vfs_getopt_size(opts, "maxfilesize", &maxfilesize) != 0)
407431
maxfilesize = 0;
408-
if (vfs_getopt_size(mp->mnt_optnew, "easize", &ea_max_size) != 0)
432+
if (vfs_getopt_size(opts, "easize", &ea_max_size) != 0)
409433
ea_max_size = 0;
410-
nonc = vfs_getopt(mp->mnt_optnew, "nonc", NULL, NULL) == 0;
411-
nomtime = vfs_getopt(mp->mnt_optnew, "nomtime", NULL, NULL) == 0;
412-
pgread = vfs_getopt(mp->mnt_optnew, "pgread", NULL, NULL) == 0;
434+
nonc = vfs_getopt(opts, "nonc", NULL, NULL) == 0;
435+
nomtime = vfs_getopt(opts, "nomtime", NULL, NULL) == 0;
436+
pgread = vfs_getopt(opts, "pgread", NULL, NULL) == 0;
413437

414438
/* Do not allow mounts if we do not have enough memory to preserve
415439
* the minimum reserved pages. */

0 commit comments

Comments
 (0)