From 817a2fd9202facea9e37e861c90659595b48cdba Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 7 Apr 2010 09:34:43 -0700 Subject: [PATCH] tmpfs - Add additional mount options * Add named mount options for guid, uid, mode (root inode) * Add named mount options ofr inodes, size, and maxfilesize. Submitted-by: Naoya Sugioka --- sbin/mount_tmpfs/mount_tmpfs.8 | 18 +++-- sbin/mount_tmpfs/mount_tmpfs.c | 131 +++++++++++++++++++++++++++++---- share/man/man5/tmpfs.5 | 17 ++++- sys/vfs/tmpfs/tmpfs_args.h | 10 ++- sys/vfs/tmpfs/tmpfs_vfsops.c | 12 ++- 5 files changed, 162 insertions(+), 26 deletions(-) diff --git a/sbin/mount_tmpfs/mount_tmpfs.8 b/sbin/mount_tmpfs/mount_tmpfs.8 index c3a9afc948..d9fcfab44b 100644 --- a/sbin/mount_tmpfs/mount_tmpfs.8 +++ b/sbin/mount_tmpfs/mount_tmpfs.8 @@ -36,6 +36,7 @@ .Nd mount an efficient memory file system .Sh SYNOPSIS .Nm +.Op Fl f Ar maxfilesize .Op Fl g Ar group .Op Fl m Ar mode .Op Fl n Ar nodes @@ -61,6 +62,8 @@ described below. .Pp The following options are supported: .Bl -tag -width XoXoptions +.It Fl f Ar maxfilesize +Specifies the maximum file size of the file system. .It Fl g Ar group Specifies the group name or GID of the root inode of the file system. Defaults to the mount point's GID. @@ -78,9 +81,11 @@ Options are specified with a flag followed by a comma-separated string of options. See the .Xr mount 8 +and +.Xr tmpfs 5 man page for possible options and their meanings. .It Fl s Ar size -Specifies the total file system size in bytes. +Specifies the total file system size. If zero is given (the default), the available amount of memory (including main memory and swap space) will be used. Note that four megabytes are always reserved for the system and cannot @@ -118,13 +123,14 @@ group, with a restricted 0700 mode: .Pp .Ic "mount -t tmpfs -o -s20M -o -ujoe -o -gusers -o -m0700 tmpfs /mnt" .Pp -See -.Pa /usr/share/examples/fstab/fstab.ramdisk -for some examples on how to add tmpfs entries to -.Pa /etc/fstab . +or +.Pp +.Ic "mount -t tmpfs -o size=20M,uid=joe,gid=users,mode=0700 tmpfs /mnt" +.Pp .Sh SEE ALSO .Xr fstab 5 , -.Xr mount 8 +.Xr mount 8 , +.Xr tmpfs 5 .Sh HISTORY The .Nm diff --git a/sbin/mount_tmpfs/mount_tmpfs.c b/sbin/mount_tmpfs/mount_tmpfs.c index 98d221d231..9fbeaa1c85 100644 --- a/sbin/mount_tmpfs/mount_tmpfs.c +++ b/sbin/mount_tmpfs/mount_tmpfs.c @@ -58,8 +58,18 @@ /* --------------------------------------------------------------------- */ +#define MOPT_TMPFSOPTS \ + { "gid=", 0, MNT_GID, 1}, \ + { "uid=", 0, MNT_UID, 1}, \ + { "mode=", 0, MNT_MODE, 1}, \ + { "inodes=", 0, MNT_INODES, 1}, \ + { "size=", 0, MNT_SIZE, 1}, \ + { "maxfilesize=", 0, MNT_MAXFSIZE, 1} + + static const struct mntopt mopts[] = { MOPT_STDOPTS, + MOPT_TMPFSOPTS, MOPT_NULL }; @@ -68,6 +78,7 @@ static const struct mntopt mopts[] = { static gid_t a_gid(char *); static uid_t a_uid(char *); static mode_t a_mask(char *); +static int64_t a_number(char *s); static void usage(void) __dead2; /* --------------------------------------------------------------------- */ @@ -82,14 +93,16 @@ mount_tmpfs_parseargs(int argc, char *argv[], gid_t gid; uid_t uid; mode_t mode; - int64_t tmpnumber; struct stat sb; + int extend_flags = 0; + char *ptr, *delim; /* Set default values for mount point arguments. */ memset(args, 0, sizeof(*args)); args->ta_version = TMPFS_ARGS_VERSION; args->ta_size_max = 0; args->ta_nodes_max = 0; + args->ta_maxfsize_max = 0; *mntflags = 0; gidset = 0; gid = 0; @@ -97,8 +110,12 @@ mount_tmpfs_parseargs(int argc, char *argv[], modeset = 0; mode = 0; optind = optreset = 1; - while ((ch = getopt(argc, argv, "g:m:n:o:s:u:")) != -1 ) { + while ((ch = getopt(argc, argv, "f:g:m:n:o:s:u:")) != -1 ) { switch (ch) { + case 'f': + args->ta_maxfsize_max = a_number(optarg); + break; + case 'g': gid = a_gid(optarg); gidset = 1; @@ -110,23 +127,96 @@ mount_tmpfs_parseargs(int argc, char *argv[], break; case 'n': - if (dehumanize_number(optarg, &tmpnumber) < 0) { - fprintf(stderr, "bad number for -n\n"); - usage(); - } - args->ta_nodes_max = tmpnumber; + args->ta_nodes_max = a_number(optarg); break; case 'o': - getmntopts(optarg, mopts, mntflags, 0); + getmntopts(optarg, mopts, mntflags, &extend_flags); + if (extend_flags & MNT_GID) { + ptr = strstr(optarg, "gid="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + gid = a_gid(ptr + 4); + *delim = ','; + } else + gid = a_gid(ptr + 4); + gidset = 1; + } + extend_flags ^= MNT_GID; + } + if (extend_flags & MNT_UID) { + ptr = strstr(optarg, "uid="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + uid = a_uid(ptr + 4); + *delim = ','; + } else + uid = a_uid(ptr + 4); + uidset = 1; + } + extend_flags ^= MNT_UID; + } + if (extend_flags & MNT_MODE) { + ptr = strstr(optarg, "mode="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + mode = a_mask(ptr + 5); + *delim = ','; + } else + mode = a_mask(ptr + 5); + modeset = 1; + } + extend_flags ^= MNT_MODE; + } + if (extend_flags & MNT_INODES) { + ptr = strstr(optarg, "inodes="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + args->ta_nodes_max = a_number(ptr + 7); + *delim = ','; + } else + args->ta_nodes_max = a_number(ptr + 7); + } + extend_flags ^= MNT_INODES; + } + if (extend_flags & MNT_SIZE) { + ptr = strstr(optarg, "size="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + args->ta_size_max = a_number(ptr + 5); + *delim = ','; + } else + args->ta_size_max = a_number(ptr + 5); + } + extend_flags ^= MNT_SIZE; + } + if (extend_flags & MNT_MAXFSIZE) { + ptr = strstr(optarg, "maxfilesize="); + if(ptr) { + delim = strstr(ptr, ","); + if (delim) { + *delim = '\0'; + args->ta_maxfsize_max = a_number(ptr + 12); + *delim = ','; + } else + args->ta_maxfsize_max = a_number(ptr + 12); + } + extend_flags ^= MNT_MAXFSIZE; + } break; case 's': - if (dehumanize_number(optarg, &tmpnumber) < 0) { - fprintf(stderr, "bad number for -s\n"); - usage(); - } - args->ta_size_max = tmpnumber; + args->ta_size_max = a_number(optarg); break; case 'u': @@ -205,19 +295,30 @@ a_mask(char *s) done = 0; if (*s >= '0' && *s <= '7') { done = 1; - rv = strtol(optarg, &ep, 8); + rv = strtol(s, &ep, 8); } if (!done || rv < 0 || *ep) errx(EX_USAGE, "invalid file mode: %s", s); return (rv); } +static int64_t +a_number(char *s) +{ + int64_t rv=0; + + if (dehumanize_number(s, &rv) < 0 || rv < 0) + errx(EX_USAGE, "bad number for option: %s", s); + fprintf(stderr, "%ld", rv); + return (rv); +} + static void usage(void) { (void)fprintf(stderr, "Usage: %s [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n" - " [-u user] tmpfs mountpoint\n", getprogname()); + " [-u user] [-f maxfilesize] tmpfs mountpoint\n", getprogname()); exit(1); } diff --git a/share/man/man5/tmpfs.5 b/share/man/man5/tmpfs.5 index e2184f0234..f0e2ecce37 100644 --- a/share/man/man5/tmpfs.5 +++ b/share/man/man5/tmpfs.5 @@ -61,9 +61,9 @@ permissions in octal format. .It Cm inodes maximum number of inodes. .It Cm size -maximum size (in bytes) for the file system. +maximum size for the file system. .It Cm maxfilesize -maximum file size (in bytes). +maximum file size of the file system. .El .Sh DESCRIPTION In the @@ -99,6 +99,19 @@ By default allows up to 100% of swap space to be used. If this is not desirable then the size option should be used to limit its size. +.El +.Pp +Every option that accepts a numerical value as its argument can take a +trailing +.Sq b +to indicate bytes (the default), a trailing +.Sq k +to indicate kilobytes, a trailing +.Sq M +to indicate megabytes or a trailing +.Sq G +to indicate gigabytes. +Note that both lowercase and uppercase forms of these letters are allowed. .Sh EXAMPLES To mount a .Nm diff --git a/sys/vfs/tmpfs/tmpfs_args.h b/sys/vfs/tmpfs/tmpfs_args.h index 6601ebdf54..2212438aae 100644 --- a/sys/vfs/tmpfs/tmpfs_args.h +++ b/sys/vfs/tmpfs/tmpfs_args.h @@ -37,13 +37,14 @@ * This structure is used to communicate mount parameters between userland * and kernel space. */ -#define TMPFS_ARGS_VERSION 1 +#define TMPFS_ARGS_VERSION 2 struct tmpfs_args { int ta_version; /* Size counters. */ ino_t ta_nodes_max; off_t ta_size_max; + size_t ta_maxfsize_max; /* Root node attributes. */ uid_t ta_root_uid; @@ -51,4 +52,11 @@ struct tmpfs_args { mode_t ta_root_mode; }; +#define MNT_GID 0x00000001 +#define MNT_UID 0x00000002 +#define MNT_MODE 0x00000004 +#define MNT_INODES 0x00000008 +#define MNT_SIZE 0x00000010 +#define MNT_MAXFSIZE 0x00000020 + #endif /* _VFS_TMPFS_TMPFS_ARGS_H_ */ diff --git a/sys/vfs/tmpfs/tmpfs_vfsops.c b/sys/vfs/tmpfs/tmpfs_vfsops.c index d18388952c..470b61ff2a 100644 --- a/sys/vfs/tmpfs/tmpfs_vfsops.c +++ b/sys/vfs/tmpfs/tmpfs_vfsops.c @@ -138,10 +138,12 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) vm_pindex_t pages; vm_pindex_t pages_limit; ino_t nodes; + u_int64_t maxfsize; int error; /* Size counters. */ ino_t nodes_max; off_t size_max; + size_t maxfsize_max; size_t size; /* Root node attributes. */ @@ -162,6 +164,7 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) bzero(&args, sizeof(args)); size_max = 0; nodes_max = 0; + maxfsize_max = 0; if (path) { if (data) { @@ -171,6 +174,7 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) } size_max = args.ta_size_max; nodes_max = args.ta_nodes_max; + maxfsize_max = args.ta_maxfsize_max; root_uid = args.ta_root_uid; root_gid = args.ta_root_gid; root_mode = args.ta_root_mode; @@ -206,13 +210,17 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) else nodes = nodes_max; + maxfsize = IDX_TO_OFF(pages_limit); + if (maxfsize_max != 0 && maxfsize > maxfsize_max) + maxfsize = maxfsize_max; + /* Allocate the tmpfs mount structure and fill it. */ tmp = kmalloc(sizeof(*tmp), M_TMPFSMNT, M_WAITOK | M_ZERO); lockinit(&(tmp->allnode_lock), "tmpfs allnode lock", 0, LK_CANRECURSE); tmp->tm_nodes_max = nodes; tmp->tm_nodes_inuse = 0; - tmp->tm_maxfilesize = IDX_TO_OFF(pages_limit); + tmp->tm_maxfilesize = maxfsize; LIST_INIT(&tmp->tm_nodes_used); tmp->tm_pages_max = pages; @@ -472,7 +480,7 @@ tmpfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) sbp->f_files = freenodes + tmp->tm_nodes_inuse; sbp->f_ffree = freenodes; - /* sbp->f_owner = tmp->tn_uid; */ + sbp->f_owner = tmp->tm_root->tn_uid; return 0; } -- 2.41.0