diff options
-rw-r--r-- | sys/fs/tmpfs/tmpfs_vfsops.c | 29 | ||||
-rw-r--r-- | sys/kern/vfs_mount.c | 42 | ||||
-rw-r--r-- | sys/sys/mount.h | 2 |
3 files changed, 57 insertions, 16 deletions
diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c index 0afc809..6bb1a44 100644 --- a/sys/fs/tmpfs/tmpfs_vfsops.c +++ b/sys/fs/tmpfs/tmpfs_vfsops.c @@ -132,12 +132,10 @@ tmpfs_mount(struct mount *mp) { struct tmpfs_mount *tmp; struct tmpfs_node *root; - size_t pages; - uint32_t nodes; int error; /* Size counters. */ - u_int nodes_max; - u_quad_t size_max, maxfilesize; + u_quad_t pages; + off_t nodes_max, size_max, maxfilesize; /* Root node attributes. */ uid_t root_uid; @@ -173,12 +171,11 @@ tmpfs_mount(struct mount *mp) if (mp->mnt_cred->cr_ruid != 0 || vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1) root_mode = va.va_mode; - if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1) + if (vfs_getopt_size(mp->mnt_optnew, "inodes", &nodes_max) != 0) nodes_max = 0; - if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1) + if (vfs_getopt_size(mp->mnt_optnew, "size", &size_max) != 0) size_max = 0; - if (vfs_scanopt(mp->mnt_optnew, "maxfilesize", "%qu", - &maxfilesize) != 1) + if (vfs_getopt_size(mp->mnt_optnew, "maxfilesize", &maxfilesize) != 0) maxfilesize = 0; /* Do not allow mounts if we do not have enough memory to preserve @@ -190,7 +187,8 @@ tmpfs_mount(struct mount *mp) * allowed to use, based on the maximum size the user passed in * the mount structure. A value of zero is treated as if the * maximum available space was requested. */ - if (size_max < PAGE_SIZE || size_max > SIZE_MAX - PAGE_SIZE) + if (size_max < PAGE_SIZE || size_max > OFF_MAX - PAGE_SIZE || + (SIZE_MAX < OFF_MAX && size_max / PAGE_SIZE >= SIZE_MAX)) pages = SIZE_MAX; else pages = howmany(size_max, PAGE_SIZE); @@ -198,21 +196,20 @@ tmpfs_mount(struct mount *mp) if (nodes_max <= 3) { if (pages > UINT32_MAX - 3) - nodes = UINT32_MAX; + nodes_max = UINT32_MAX; else - nodes = pages + 3; - } else - nodes = nodes_max; - MPASS(nodes >= 3); + nodes_max = pages + 3; + } + MPASS(nodes_max >= 3); /* Allocate the tmpfs mount structure and fill it. */ tmp = (struct tmpfs_mount *)malloc(sizeof(struct tmpfs_mount), M_TMPFSMNT, M_WAITOK | M_ZERO); mtx_init(&tmp->allnode_lock, "tmpfs allnode lock", NULL, MTX_DEF); - tmp->tm_nodes_max = nodes; + tmp->tm_nodes_max = nodes_max; tmp->tm_nodes_inuse = 0; - tmp->tm_maxfilesize = maxfilesize > 0 ? maxfilesize : UINT64_MAX; + tmp->tm_maxfilesize = maxfilesize > 0 ? maxfilesize : OFF_MAX; LIST_INIT(&tmp->tm_nodes_used); tmp->tm_pages_max = pages; diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 93387ca..657fa92 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1520,6 +1520,48 @@ vfs_getopt_pos(struct vfsoptlist *opts, const char *name) return (-1); } +int +vfs_getopt_size(struct vfsoptlist *opts, const char *name, off_t *value) +{ + char *opt_value, *vtp; + quad_t iv; + int error, opt_len; + + error = vfs_getopt(opts, name, (void **)&opt_value, &opt_len); + if (error != 0) + return (error); + if (opt_len == 0 || opt_value == NULL) + return (EINVAL); + if (opt_value[0] == '\0' || opt_value[opt_len - 1] != '\0') + return (EINVAL); + iv = strtoq(opt_value, &vtp, 0); + if (vtp == opt_value || (vtp[0] != '\0' && vtp[1] != '\0')) + return (EINVAL); + if (iv < 0) + return (EINVAL); + switch (vtp[0]) { + case 't': + case 'T': + iv *= 1024; + case 'g': + case 'G': + iv *= 1024; + case 'm': + case 'M': + iv *= 1024; + case 'k': + case 'K': + iv *= 1024; + case '\0': + break; + default: + return (EINVAL); + } + *value = iv; + + return (0); +} + char * vfs_getopts(struct vfsoptlist *opts, const char *name, int *error) { diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 2b6041e..2a3c4a4 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -718,6 +718,8 @@ int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w, uint64_t val); int vfs_getopt(struct vfsoptlist *, const char *, void **, int *); int vfs_getopt_pos(struct vfsoptlist *opts, const char *name); +int vfs_getopt_size(struct vfsoptlist *opts, const char *name, + off_t *value); char *vfs_getopts(struct vfsoptlist *, const char *, int *error); int vfs_copyopt(struct vfsoptlist *, const char *, void *, int); int vfs_filteropt(struct vfsoptlist *, const char **legal); |