tmpfs - Add additional mount options
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 7 Apr 2010 16:34:43 +0000 (09:34 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 7 Apr 2010 16:34:43 +0000 (09:34 -0700)
* Add named mount options for guid, uid, mode (root inode)
* Add named mount options ofr inodes, size, and maxfilesize.

Submitted-by: Naoya Sugioka <naoya.sugioka@gmail.com>
sbin/mount_tmpfs/mount_tmpfs.8
sbin/mount_tmpfs/mount_tmpfs.c
share/man/man5/tmpfs.5
sys/vfs/tmpfs/tmpfs_args.h
sys/vfs/tmpfs/tmpfs_vfsops.c

index c3a9afc..d9fcfab 100644 (file)
@@ -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
index 98d221d..9fbeaa1 100644 (file)
 
 /* --------------------------------------------------------------------- */
 
+#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);
 }
 
index e2184f0..f0e2ecc 100644 (file)
@@ -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
index 6601ebd..2212438 100644 (file)
  * 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_ */
index d183889..470b61f 100644 (file)
@@ -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;
 }