1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <sys/param.h>
  28 #include <sys/sysmacros.h>
  29 #include <sys/kmem.h>
  30 #include <sys/time.h>
  31 #include <sys/pathname.h>
  32 #include <sys/vfs.h>
  33 #include <sys/vfs_opreg.h>
  34 #include <sys/vnode.h>
  35 #include <sys/stat.h>
  36 #include <sys/uio.h>
  37 #include <sys/stat.h>
  38 #include <sys/errno.h>
  39 #include <sys/cmn_err.h>
  40 #include <sys/cred.h>
  41 #include <sys/statvfs.h>
  42 #include <sys/mount.h>
  43 #include <sys/debug.h>
  44 #include <sys/systm.h>
  45 #include <sys/mntent.h>
  46 #include <fs/fs_subr.h>
  47 #include <vm/page.h>
  48 #include <vm/anon.h>
  49 #include <sys/model.h>
  50 #include <sys/policy.h>
  51 
  52 #include <sys/fs/swapnode.h>
  53 #include <sys/fs/tmp.h>
  54 #include <sys/fs/tmpnode.h>
  55 
  56 static int tmpfsfstype;
  57 
  58 /*
  59  * tmpfs vfs operations.
  60  */
  61 static int tmpfsinit(int, char *);
  62 static int tmp_mount(struct vfs *, struct vnode *,
  63         struct mounta *, struct cred *);
  64 static int tmp_unmount(struct vfs *, int, struct cred *);
  65 static int tmp_root(struct vfs *, struct vnode **);
  66 static int tmp_statvfs(struct vfs *, struct statvfs64 *);
  67 static int tmp_vget(struct vfs *, struct vnode **, struct fid *);
  68 
  69 /*
  70  * Loadable module wrapper
  71  */
  72 #include <sys/modctl.h>
  73 
  74 static mntopts_t tmpfs_proto_opttbl;
  75 
  76 static vfsdef_t vfw = {
  77         VFSDEF_VERSION,
  78         "tmpfs",
  79         tmpfsinit,
  80         VSW_HASPROTO|VSW_CANREMOUNT|VSW_STATS|VSW_ZMOUNT,
  81         &tmpfs_proto_opttbl
  82 };
  83 
  84 /*
  85  * in-kernel mnttab options
  86  */
  87 static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL };
  88 static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL };
  89 
  90 static mntopt_t tmpfs_options[] = {
  91         /* Option name          Cancel Opt      Arg     Flags           Data */
  92         { MNTOPT_XATTR,         xattr_cancel,   NULL,   MO_DEFAULT,     NULL},
  93         { MNTOPT_NOXATTR,       noxattr_cancel, NULL,   NULL,           NULL},
  94         { "size",               NULL,           "0",    MO_HASVALUE,    NULL}
  95 };
  96 
  97 
  98 static mntopts_t tmpfs_proto_opttbl = {
  99         sizeof (tmpfs_options) / sizeof (mntopt_t),
 100         tmpfs_options
 101 };
 102 
 103 /*
 104  * Module linkage information
 105  */
 106 static struct modlfs modlfs = {
 107         &mod_fsops, "filesystem for tmpfs", &vfw
 108 };
 109 
 110 static struct modlinkage modlinkage = {
 111         MODREV_1, { &modlfs, NULL }
 112 };
 113 
 114 int
 115 _init()
 116 {
 117         return (mod_install(&modlinkage));
 118 }
 119 
 120 int
 121 _fini()
 122 {
 123         int error;
 124 
 125         error = mod_remove(&modlinkage);
 126         if (error)
 127                 return (error);
 128         /*
 129          * Tear down the operations vectors
 130          */
 131         (void) vfs_freevfsops_by_type(tmpfsfstype);
 132         vn_freevnodeops(tmp_vnodeops);
 133         return (0);
 134 }
 135 
 136 int
 137 _info(struct modinfo *modinfop)
 138 {
 139         return (mod_info(&modlinkage, modinfop));
 140 }
 141 
 142 /*
 143  * The following are patchable variables limiting the amount of system
 144  * resources tmpfs can use.
 145  *
 146  * tmpfs_maxkmem limits the amount of kernel kmem_alloc memory
 147  * tmpfs can use for it's data structures (e.g. tmpnodes, directory entries)
 148  * It is not determined by setting a hard limit but rather as a percentage of
 149  * physical memory which is determined when tmpfs is first used in the system.
 150  *
 151  * tmpfs_minfree is the minimum amount of swap space that tmpfs leaves for
 152  * the rest of the system.  In other words, if the amount of free swap space
 153  * in the system (i.e. anoninfo.ani_free) drops below tmpfs_minfree, tmpfs
 154  * anon allocations will fail.
 155  *
 156  * There is also a per mount limit on the amount of swap space
 157  * (tmount.tm_anonmax) settable via a mount option.
 158  */
 159 size_t tmpfs_maxkmem = 0;
 160 size_t tmpfs_minfree = 0;
 161 size_t tmp_kmemspace;           /* bytes of kernel heap used by all tmpfs */
 162 
 163 static major_t tmpfs_major;
 164 static minor_t tmpfs_minor;
 165 static kmutex_t tmpfs_minor_lock;
 166 
 167 /*
 168  * initialize global tmpfs locks and such
 169  * called when loading tmpfs module
 170  */
 171 static int
 172 tmpfsinit(int fstype, char *name)
 173 {
 174         static const fs_operation_def_t tmp_vfsops_template[] = {
 175                 { VFSNAME_MOUNT,        { .vfs_mount = tmp_mount } },
 176                 { VFSNAME_UNMOUNT,      { .vfs_unmount = tmp_unmount } },
 177                 { VFSNAME_ROOT,         { .vfs_root = tmp_root } },
 178                 { VFSNAME_STATVFS,      { .vfs_statvfs = tmp_statvfs } },
 179                 { VFSNAME_VGET,         { .vfs_vget = tmp_vget } },
 180                 { NULL,                 { NULL } }
 181         };
 182         int error;
 183         extern  void    tmpfs_hash_init();
 184 
 185         tmpfs_hash_init();
 186         tmpfsfstype = fstype;
 187         ASSERT(tmpfsfstype != 0);
 188 
 189         error = vfs_setfsops(fstype, tmp_vfsops_template, NULL);
 190         if (error != 0) {
 191                 cmn_err(CE_WARN, "tmpfsinit: bad vfs ops template");
 192                 return (error);
 193         }
 194 
 195         error = vn_make_ops(name, tmp_vnodeops_template, &tmp_vnodeops);
 196         if (error != 0) {
 197                 (void) vfs_freevfsops_by_type(fstype);
 198                 cmn_err(CE_WARN, "tmpfsinit: bad vnode ops template");
 199                 return (error);
 200         }
 201 
 202         /*
 203          * tmpfs_minfree doesn't need to be some function of configured
 204          * swap space since it really is an absolute limit of swap space
 205          * which still allows other processes to execute.
 206          */
 207         if (tmpfs_minfree == 0) {
 208                 /*
 209                  * Set if not patched
 210                  */
 211                 tmpfs_minfree = btopr(TMPMINFREE);
 212         }
 213 
 214         /*
 215          * The maximum amount of space tmpfs can allocate is
 216          * TMPMAXPROCKMEM percent of kernel memory
 217          */
 218         if (tmpfs_maxkmem == 0)
 219                 tmpfs_maxkmem = MAX(PAGESIZE, kmem_maxavail() / TMPMAXFRACKMEM);
 220 
 221         if ((tmpfs_major = getudev()) == (major_t)-1) {
 222                 cmn_err(CE_WARN, "tmpfsinit: Can't get unique device number.");
 223                 tmpfs_major = 0;
 224         }
 225         mutex_init(&tmpfs_minor_lock, NULL, MUTEX_DEFAULT, NULL);
 226         return (0);
 227 }
 228 
 229 static int
 230 tmp_mount(
 231         struct vfs *vfsp,
 232         struct vnode *mvp,
 233         struct mounta *uap,
 234         struct cred *cr)
 235 {
 236         struct tmount *tm = NULL;
 237         struct tmpnode *tp;
 238         struct pathname dpn;
 239         int error;
 240         pgcnt_t anonmax;
 241         struct vattr rattr;
 242         int got_attrs;
 243 
 244         char *sizestr;
 245 
 246         if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0)
 247                 return (error);
 248 
 249         if (mvp->v_type != VDIR)
 250                 return (ENOTDIR);
 251 
 252         mutex_enter(&mvp->v_lock);
 253         if ((uap->flags & MS_REMOUNT) == 0 && (uap->flags & MS_OVERLAY) == 0 &&
 254             (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
 255                 mutex_exit(&mvp->v_lock);
 256                 return (EBUSY);
 257         }
 258         mutex_exit(&mvp->v_lock);
 259 
 260         /*
 261          * Having the resource be anything but "swap" doesn't make sense.
 262          */
 263         vfs_setresource(vfsp, "swap", 0);
 264 
 265         /*
 266          * now look for options we understand...
 267          */
 268 
 269         /* tmpfs doesn't support read-only mounts */
 270         if (vfs_optionisset(vfsp, MNTOPT_RO, NULL)) {
 271                 error = EINVAL;
 272                 goto out;
 273         }
 274 
 275         /*
 276          * tm_anonmax is set according to the mount arguments
 277          * if any.  Otherwise, it is set to a maximum value.
 278          */
 279         if (vfs_optionisset(vfsp, "size", &sizestr)) {
 280                 if ((error = tmp_convnum(sizestr, &anonmax)) != 0)
 281                         goto out;
 282         } else {
 283                 anonmax = ULONG_MAX;
 284         }
 285 
 286         if (error = pn_get(uap->dir,
 287             (uap->flags & MS_SYSSPACE) ? UIO_SYSSPACE : UIO_USERSPACE, &dpn))
 288                 goto out;
 289 
 290         if (uap->flags & MS_REMOUNT) {
 291                 tm = (struct tmount *)VFSTOTM(vfsp);
 292 
 293                 /*
 294                  * If we change the size so its less than what is currently
 295                  * being used, we allow that. The file system will simply be
 296                  * full until enough files have been removed to get below the
 297                  * new max.
 298                  */
 299                 mutex_enter(&tm->tm_contents);
 300                 tm->tm_anonmax = anonmax;
 301                 mutex_exit(&tm->tm_contents);
 302                 goto out;
 303         }
 304 
 305         if ((tm = tmp_memalloc(sizeof (struct tmount), 0)) == NULL) {
 306                 pn_free(&dpn);
 307                 error = ENOMEM;
 308                 goto out;
 309         }
 310 
 311         /*
 312          * find an available minor device number for this mount
 313          */
 314         mutex_enter(&tmpfs_minor_lock);
 315         do {
 316                 tmpfs_minor = (tmpfs_minor + 1) & L_MAXMIN32;
 317                 tm->tm_dev = makedevice(tmpfs_major, tmpfs_minor);
 318         } while (vfs_devismounted(tm->tm_dev));
 319         mutex_exit(&tmpfs_minor_lock);
 320 
 321         /*
 322          * Set but don't bother entering the mutex
 323          * (tmount not on mount list yet)
 324          */
 325         mutex_init(&tm->tm_contents, NULL, MUTEX_DEFAULT, NULL);
 326         mutex_init(&tm->tm_renamelck, NULL, MUTEX_DEFAULT, NULL);
 327 
 328         tm->tm_vfsp = vfsp;
 329         tm->tm_anonmax = anonmax;
 330 
 331         vfsp->vfs_data = (caddr_t)tm;
 332         vfsp->vfs_fstype = tmpfsfstype;
 333         vfsp->vfs_dev = tm->tm_dev;
 334         vfsp->vfs_bsize = PAGESIZE;
 335         vfsp->vfs_flag |= VFS_NOTRUNC;
 336         vfs_make_fsid(&vfsp->vfs_fsid, tm->tm_dev, tmpfsfstype);
 337         tm->tm_mntpath = tmp_memalloc(dpn.pn_pathlen + 1, TMP_MUSTHAVE);
 338         (void) strcpy(tm->tm_mntpath, dpn.pn_path);
 339 
 340         /*
 341          * allocate and initialize root tmpnode structure
 342          */
 343         bzero(&rattr, sizeof (struct vattr));
 344         rattr.va_mode = (mode_t)(S_IFDIR | 0777);       /* XXX modes */
 345         rattr.va_type = VDIR;
 346         rattr.va_rdev = 0;
 347         tp = tmp_memalloc(sizeof (struct tmpnode), TMP_MUSTHAVE);
 348         tmpnode_init(tm, tp, &rattr, cr);
 349 
 350         /*
 351          * Get the mode, uid, and gid from the underlying mount point.
 352          */
 353         rattr.va_mask = AT_MODE|AT_UID|AT_GID;  /* Hint to getattr */
 354         got_attrs = VOP_GETATTR(mvp, &rattr, 0, cr, NULL);
 355 
 356         rw_enter(&tp->tn_rwlock, RW_WRITER);
 357         TNTOV(tp)->v_flag |= VROOT;
 358 
 359         /*
 360          * If the getattr succeeded, use its results.  Otherwise allow
 361          * the previously set hardwired defaults to prevail.
 362          */
 363         if (got_attrs == 0) {
 364                 tp->tn_mode = rattr.va_mode;
 365                 tp->tn_uid = rattr.va_uid;
 366                 tp->tn_gid = rattr.va_gid;
 367         }
 368 
 369         /*
 370          * initialize linked list of tmpnodes so that the back pointer of
 371          * the root tmpnode always points to the last one on the list
 372          * and the forward pointer of the last node is null
 373          */
 374         tp->tn_back = tp;
 375         tp->tn_forw = NULL;
 376         tp->tn_nlink = 0;
 377         tm->tm_rootnode = tp;
 378 
 379         tdirinit(tp, tp);
 380 
 381         rw_exit(&tp->tn_rwlock);
 382 
 383         pn_free(&dpn);
 384         error = 0;
 385 
 386 out:
 387         if (error == 0)
 388                 vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS);
 389 
 390         return (error);
 391 }
 392 
 393 static int
 394 tmp_unmount(struct vfs *vfsp, int flag, struct cred *cr)
 395 {
 396         struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
 397         struct tmpnode *tnp, *cancel;
 398         struct vnode    *vp;
 399         int error;
 400 
 401         if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0)
 402                 return (error);
 403 
 404         /*
 405          * forced unmount is not supported by this file system
 406          * and thus, ENOTSUP, is being returned.
 407          */
 408         if (flag & MS_FORCE)
 409                 return (ENOTSUP);
 410 
 411         mutex_enter(&tm->tm_contents);
 412 
 413         /*
 414          * If there are no open files, only the root node should have
 415          * a reference count.
 416          * With tm_contents held, nothing can be added or removed.
 417          * There may be some dirty pages.  To prevent fsflush from
 418          * disrupting the unmount, put a hold on each node while scanning.
 419          * If we find a previously referenced node, undo the holds we have
 420          * placed and fail EBUSY.
 421          */
 422         tnp = tm->tm_rootnode;
 423         if (TNTOV(tnp)->v_count > 1) {
 424                 mutex_exit(&tm->tm_contents);
 425                 return (EBUSY);
 426         }
 427 
 428         for (tnp = tnp->tn_forw; tnp; tnp = tnp->tn_forw) {
 429                 if ((vp = TNTOV(tnp))->v_count > 0) {
 430                         cancel = tm->tm_rootnode->tn_forw;
 431                         while (cancel != tnp) {
 432                                 vp = TNTOV(cancel);
 433                                 ASSERT(vp->v_count > 0);
 434                                 VN_RELE(vp);
 435                                 cancel = cancel->tn_forw;
 436                         }
 437                         mutex_exit(&tm->tm_contents);
 438                         return (EBUSY);
 439                 }
 440                 VN_HOLD(vp);
 441         }
 442 
 443         /*
 444          * We can drop the mutex now because no one can find this mount
 445          */
 446         mutex_exit(&tm->tm_contents);
 447 
 448         /*
 449          * Free all kmemalloc'd and anonalloc'd memory associated with
 450          * this filesystem.  To do this, we go through the file list twice,
 451          * once to remove all the directory entries, and then to remove
 452          * all the files.  We do this because there is useful code in
 453          * tmpnode_free which assumes that the directory entry has been
 454          * removed before the file.
 455          */
 456         /*
 457          * Remove all directory entries
 458          */
 459         for (tnp = tm->tm_rootnode; tnp; tnp = tnp->tn_forw) {
 460                 rw_enter(&tnp->tn_rwlock, RW_WRITER);
 461                 if (tnp->tn_type == VDIR)
 462                         tdirtrunc(tnp);
 463                 if (tnp->tn_vnode->v_flag & V_XATTRDIR) {
 464                         /*
 465                          * Account for implicit attrdir reference.
 466                          */
 467                         ASSERT(tnp->tn_nlink > 0);
 468                         DECR_COUNT(&tnp->tn_nlink, &tnp->tn_tlock);
 469                 }
 470                 rw_exit(&tnp->tn_rwlock);
 471         }
 472 
 473         ASSERT(tm->tm_rootnode);
 474 
 475         /*
 476          * All links are gone, v_count is keeping nodes in place.
 477          * VN_RELE should make the node disappear, unless somebody
 478          * is holding pages against it.  Nap and retry until it disappears.
 479          *
 480          * We re-acquire the lock to prevent others who have a HOLD on
 481          * a tmpnode via its pages or anon slots from blowing it away
 482          * (in tmp_inactive) while we're trying to get to it here. Once
 483          * we have a HOLD on it we know it'll stick around.
 484          *
 485          */
 486         mutex_enter(&tm->tm_contents);
 487         /*
 488          * Remove all the files (except the rootnode) backwards.
 489          */
 490         while ((tnp = tm->tm_rootnode->tn_back) != tm->tm_rootnode) {
 491                 mutex_exit(&tm->tm_contents);
 492                 /*
 493                  * Inhibit tmp_inactive from touching attribute directory
 494                  * as all nodes will be released here.
 495                  * Note we handled the link count in pass 2 above.
 496                  */
 497                 rw_enter(&tnp->tn_rwlock, RW_WRITER);
 498                 tnp->tn_xattrdp = NULL;
 499                 rw_exit(&tnp->tn_rwlock);
 500                 vp = TNTOV(tnp);
 501                 VN_RELE(vp);
 502                 mutex_enter(&tm->tm_contents);
 503                 /*
 504                  * It's still there after the RELE. Someone else like pageout
 505                  * has a hold on it so wait a bit and then try again - we know
 506                  * they'll give it up soon.
 507                  */
 508                 if (tnp == tm->tm_rootnode->tn_back) {
 509                         VN_HOLD(vp);
 510                         mutex_exit(&tm->tm_contents);
 511                         delay(hz / 4);
 512                         mutex_enter(&tm->tm_contents);
 513                 }
 514         }
 515         mutex_exit(&tm->tm_contents);
 516 
 517         tm->tm_rootnode->tn_xattrdp = NULL;
 518         VN_RELE(TNTOV(tm->tm_rootnode));
 519 
 520         ASSERT(tm->tm_mntpath);
 521 
 522         tmp_memfree(tm->tm_mntpath, strlen(tm->tm_mntpath) + 1);
 523 
 524         ASSERT(tm->tm_anonmem == 0);
 525 
 526         mutex_destroy(&tm->tm_contents);
 527         mutex_destroy(&tm->tm_renamelck);
 528         tmp_memfree(tm, sizeof (struct tmount));
 529 
 530         return (0);
 531 }
 532 
 533 /*
 534  * return root tmpnode for given vnode
 535  */
 536 static int
 537 tmp_root(struct vfs *vfsp, struct vnode **vpp)
 538 {
 539         struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
 540         struct tmpnode *tp = tm->tm_rootnode;
 541         struct vnode *vp;
 542 
 543         ASSERT(tp);
 544 
 545         vp = TNTOV(tp);
 546         VN_HOLD(vp);
 547         *vpp = vp;
 548         return (0);
 549 }
 550 
 551 static int
 552 tmp_statvfs(struct vfs *vfsp, struct statvfs64 *sbp)
 553 {
 554         struct tmount   *tm = (struct tmount *)VFSTOTM(vfsp);
 555         ulong_t blocks;
 556         dev32_t d32;
 557         zoneid_t eff_zid;
 558         struct zone *zp;
 559 
 560         /*
 561          * The file system may have been mounted by the global zone on
 562          * behalf of the non-global zone.  In that case, the tmount zone_id
 563          * will be the global zone.  We still want to show the swap cap inside
 564          * the zone in this case, even though the file system was mounted by
 565          * the global zone.
 566          */
 567         if (curproc->p_zone->zone_id != GLOBAL_ZONEUNIQID)
 568                 zp = curproc->p_zone;
 569         else
 570                 zp = tm->tm_vfsp->vfs_zone;
 571 
 572         if (zp == NULL)
 573                 eff_zid = GLOBAL_ZONEUNIQID;
 574         else
 575                 eff_zid = zp->zone_id;
 576 
 577         sbp->f_bsize = PAGESIZE;
 578         sbp->f_frsize = PAGESIZE;
 579 
 580         /*
 581          * Find the amount of available physical and memory swap
 582          */
 583         mutex_enter(&anoninfo_lock);
 584         ASSERT(k_anoninfo.ani_max >= k_anoninfo.ani_phys_resv);
 585         blocks = (ulong_t)CURRENT_TOTAL_AVAILABLE_SWAP;
 586         mutex_exit(&anoninfo_lock);
 587 
 588         /*
 589          * If tm_anonmax for this mount is less than the available swap space
 590          * (minus the amount tmpfs can't use), use that instead
 591          */
 592         if (blocks > tmpfs_minfree)
 593                 sbp->f_bfree = MIN(blocks - tmpfs_minfree,
 594                     tm->tm_anonmax - tm->tm_anonmem);
 595         else
 596                 sbp->f_bfree = 0;
 597 
 598         sbp->f_bavail = sbp->f_bfree;
 599 
 600         /*
 601          * Total number of blocks is what's available plus what's been used
 602          */
 603         sbp->f_blocks = (fsblkcnt64_t)(sbp->f_bfree + tm->tm_anonmem);
 604 
 605         if (eff_zid != GLOBAL_ZONEUNIQID &&
 606             zp->zone_max_swap_ctl != UINT64_MAX) {
 607                 /*
 608                  * If the fs is used by a non-global zone with a swap cap,
 609                  * then report the capped size.
 610                  */
 611                 rctl_qty_t cap, used;
 612                 pgcnt_t pgcap, pgused;
 613 
 614                 mutex_enter(&zp->zone_mem_lock);
 615                 cap = zp->zone_max_swap_ctl;
 616                 used = zp->zone_max_swap;
 617                 mutex_exit(&zp->zone_mem_lock);
 618 
 619                 pgcap = btop(cap);
 620                 pgused = btop(used);
 621 
 622                 sbp->f_bfree = MIN(pgcap - pgused, sbp->f_bfree);
 623                 sbp->f_bavail = sbp->f_bfree;
 624                 sbp->f_blocks = MIN(pgcap, sbp->f_blocks);
 625         }
 626 
 627         /*
 628          * The maximum number of files available is approximately the number
 629          * of tmpnodes we can allocate from the remaining kernel memory
 630          * available to tmpfs.  This is fairly inaccurate since it doesn't
 631          * take into account the names stored in the directory entries.
 632          */
 633         if (tmpfs_maxkmem > tmp_kmemspace)
 634                 sbp->f_ffree = (tmpfs_maxkmem - tmp_kmemspace) /
 635                     (sizeof (struct tmpnode) + sizeof (struct tdirent));
 636         else
 637                 sbp->f_ffree = 0;
 638 
 639         sbp->f_files = tmpfs_maxkmem /
 640             (sizeof (struct tmpnode) + sizeof (struct tdirent));
 641         sbp->f_favail = (fsfilcnt64_t)(sbp->f_ffree);
 642         (void) cmpldev(&d32, vfsp->vfs_dev);
 643         sbp->f_fsid = d32;
 644         (void) strcpy(sbp->f_basetype, vfssw[tmpfsfstype].vsw_name);
 645         (void) strncpy(sbp->f_fstr, tm->tm_mntpath, sizeof (sbp->f_fstr));
 646         /*
 647          * ensure null termination
 648          */
 649         sbp->f_fstr[sizeof (sbp->f_fstr) - 1] = '\0';
 650         sbp->f_flag = vf_to_stf(vfsp->vfs_flag);
 651         sbp->f_namemax = MAXNAMELEN - 1;
 652         return (0);
 653 }
 654 
 655 static int
 656 tmp_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp)
 657 {
 658         struct tfid *tfid;
 659         struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
 660         struct tmpnode *tp = NULL;
 661 
 662         tfid = (struct tfid *)fidp;
 663         *vpp = NULL;
 664 
 665         mutex_enter(&tm->tm_contents);
 666         for (tp = tm->tm_rootnode; tp; tp = tp->tn_forw) {
 667                 mutex_enter(&tp->tn_tlock);
 668                 if (tp->tn_nodeid == tfid->tfid_ino) {
 669                         /*
 670                          * If the gen numbers don't match we know the
 671                          * file won't be found since only one tmpnode
 672                          * can have this number at a time.
 673                          */
 674                         if (tp->tn_gen != tfid->tfid_gen || tp->tn_nlink == 0) {
 675                                 mutex_exit(&tp->tn_tlock);
 676                                 mutex_exit(&tm->tm_contents);
 677                                 return (0);
 678                         }
 679                         *vpp = (struct vnode *)TNTOV(tp);
 680 
 681                         VN_HOLD(*vpp);
 682 
 683                         if ((tp->tn_mode & S_ISVTX) &&
 684                             !(tp->tn_mode & (S_IXUSR | S_IFDIR))) {
 685                                 mutex_enter(&(*vpp)->v_lock);
 686                                 (*vpp)->v_flag |= VISSWAP;
 687                                 mutex_exit(&(*vpp)->v_lock);
 688                         }
 689                         mutex_exit(&tp->tn_tlock);
 690                         mutex_exit(&tm->tm_contents);
 691                         return (0);
 692                 }
 693                 mutex_exit(&tp->tn_tlock);
 694         }
 695         mutex_exit(&tm->tm_contents);
 696         return (0);
 697 }