Print this page
OS-4043 tmpfs should support gigabyte sizes
OS-4044 tmpfs should support "mode" option
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
          +++ new/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright (c) 2011, Joyent, Inc. All rights reserved.
       23 + * Copyright 2015 Joyent, Inc.
  24   24   */
  25   25  
  26   26  #include <sys/types.h>
  27   27  #include <sys/param.h>
  28   28  #include <sys/sysmacros.h>
  29   29  #include <sys/kmem.h>
  30   30  #include <sys/time.h>
  31   31  #include <sys/pathname.h>
  32   32  #include <sys/vfs.h>
  33   33  #include <sys/vfs_opreg.h>
↓ open down ↓ 50 lines elided ↑ open up ↑
  84   84  /*
  85   85   * in-kernel mnttab options
  86   86   */
  87   87  static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL };
  88   88  static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL };
  89   89  
  90   90  static mntopt_t tmpfs_options[] = {
  91   91          /* Option name          Cancel Opt      Arg     Flags           Data */
  92   92          { MNTOPT_XATTR,         xattr_cancel,   NULL,   MO_DEFAULT,     NULL},
  93   93          { MNTOPT_NOXATTR,       noxattr_cancel, NULL,   NULL,           NULL},
  94      -        { "size",               NULL,           "0",    MO_HASVALUE,    NULL}
       94 +        { "size",               NULL,           "0",    MO_HASVALUE,    NULL},
       95 +        { "mode",               NULL,           NULL,   MO_HASVALUE,    NULL}
  95   96  };
  96   97  
  97   98  
  98   99  static mntopts_t tmpfs_proto_opttbl = {
  99  100          sizeof (tmpfs_options) / sizeof (mntopt_t),
 100  101          tmpfs_options
 101  102  };
 102  103  
 103  104  /*
 104  105   * Module linkage information
↓ open down ↓ 115 lines elided ↑ open up ↑
 220  221  
 221  222          if ((tmpfs_major = getudev()) == (major_t)-1) {
 222  223                  cmn_err(CE_WARN, "tmpfsinit: Can't get unique device number.");
 223  224                  tmpfs_major = 0;
 224  225          }
 225  226          mutex_init(&tmpfs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
 226  227          return (0);
 227  228  }
 228  229  
 229  230  static int
 230      -tmp_mount(
 231      -        struct vfs *vfsp,
 232      -        struct vnode *mvp,
 233      -        struct mounta *uap,
 234      -        struct cred *cr)
      231 +tmp_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr)
 235  232  {
 236  233          struct tmount *tm = NULL;
 237  234          struct tmpnode *tp;
 238  235          struct pathname dpn;
 239  236          int error;
 240  237          pgcnt_t anonmax;
 241  238          struct vattr rattr;
 242  239          int got_attrs;
      240 +        boolean_t mode_arg = B_FALSE;
      241 +        mode_t root_mode = 0777;
      242 +        char *argstr;
 243  243  
 244      -        char *sizestr;
 245      -
 246  244          if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
 247  245                  return (error);
 248  246  
 249  247          if (mvp->v_type != VDIR)
 250  248                  return (ENOTDIR);
 251  249  
 252  250          mutex_enter(&mvp->v_lock);
 253  251          if ((uap->flags & MS_REMOUNT) == 0 && (uap->flags & MS_OVERLAY) == 0 &&
 254  252              (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
 255  253                  mutex_exit(&mvp->v_lock);
↓ open down ↓ 13 lines elided ↑ open up ↑
 269  267          /* tmpfs doesn't support read-only mounts */
 270  268          if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) {
 271  269                  error = EINVAL;
 272  270                  goto out;
 273  271          }
 274  272  
 275  273          /*
 276  274           * tm_anonmax is set according to the mount arguments
 277  275           * if any.  Otherwise, it is set to a maximum value.
 278  276           */
 279      -        if (vfs_optionisset(vfsp, "size", &sizestr)) {
 280      -                if ((error = tmp_convnum(sizestr, &anonmax)) != 0)
      277 +        if (vfs_optionisset(vfsp, "size", &argstr)) {
      278 +                if ((error = tmp_convnum(argstr, &anonmax)) != 0)
 281  279                          goto out;
 282  280          } else {
 283  281                  anonmax = ULONG_MAX;
 284  282          }
 285  283  
      284 +        /*
      285 +         * The "mode" mount argument allows the operator to override the
      286 +         * permissions of the root of the tmpfs mount.
      287 +         */
      288 +        if (vfs_optionisset(vfsp, "mode", &argstr)) {
      289 +                if ((error = tmp_convmode(argstr, &root_mode)) != 0) {
      290 +                        goto out;
      291 +                }
      292 +                mode_arg = B_TRUE;
      293 +        }
      294 +
 286  295          if (error = pn_get(uap->dir,
 287  296              (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE, &dpn))
 288  297                  goto out;
 289  298  
 290  299          if (uap->flags & MS_REMOUNT) {
 291  300                  tm = (struct tmount *)VFSTOTM(vfsp);
 292  301  
 293  302                  /*
 294  303                   * If we change the size so its less than what is currently
 295  304                   * being used, we allow that. The file system will simply be
↓ open down ↓ 38 lines elided ↑ open up ↑
 334  343          vfsp->vfs_bsize = PAGESIZE;
 335  344          vfsp->vfs_flag |= VFS_NOTRUNC;
 336  345          vfs_make_fsid(&vfsp->vfs_fsid, tm->tm_dev, tmpfsfstype);
 337  346          tm->tm_mntpath = tmp_memalloc(dpn.pn_pathlen + 1, TMP_MUSTHAVE);
 338  347          (void) strcpy(tm->tm_mntpath, dpn.pn_path);
 339  348  
 340  349          /*
 341  350           * allocate and initialize root tmpnode structure
 342  351           */
 343  352          bzero(&rattr, sizeof (struct vattr));
 344      -        rattr.va_mode = (mode_t)(S_IFDIR | 0777);       /* XXX modes */
      353 +        rattr.va_mode = (mode_t)(S_IFDIR | root_mode);
 345  354          rattr.va_type = VDIR;
 346  355          rattr.va_rdev = 0;
 347  356          tp = tmp_memalloc(sizeof (struct tmpnode), TMP_MUSTHAVE);
 348  357          tmpnode_init(tm, tp, &rattr, cr);
 349  358  
 350  359          /*
 351  360           * Get the mode, uid, and gid from the underlying mount point.
 352  361           */
 353  362          rattr.va_mask = AT_MODE|AT_UID|AT_GID;  /* Hint to getattr */
 354  363          got_attrs = VOP_GETATTR(mvp, &rattr, 0, cr, NULL);
 355  364  
 356  365          rw_enter(&tp->tn_rwlock, RW_WRITER);
 357  366          TNTOV(tp)->v_flag |= VROOT;
 358  367  
 359  368          /*
 360  369           * If the getattr succeeded, use its results.  Otherwise allow
 361  370           * the previously set hardwired defaults to prevail.
 362  371           */
 363  372          if (got_attrs == 0) {
 364      -                tp->tn_mode = rattr.va_mode;
      373 +                if (!mode_arg) {
      374 +                        /*
      375 +                         * Only use the underlying mount point for the
      376 +                         * mode if the "mode" mount argument was not
      377 +                         * provided.
      378 +                         */
      379 +                        tp->tn_mode = rattr.va_mode;
      380 +                }
 365  381                  tp->tn_uid = rattr.va_uid;
 366  382                  tp->tn_gid = rattr.va_gid;
 367  383          }
 368  384  
 369  385          /*
 370  386           * initialize linked list of tmpnodes so that the back pointer of
 371  387           * the root tmpnode always points to the last one on the list
 372  388           * and the forward pointer of the last node is null
 373  389           */
 374  390          tp->tn_back = tp;
↓ open down ↓ 323 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX