Home | History | Annotate | Download | only in tmpfs
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     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_STATS,
     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_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");
    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 ((tm = tmp_memalloc(sizeof (struct tmount), 0)) == NULL) {
    291 		pn_free(&dpn);
    292 		error = ENOMEM;
    293 		goto out;
    294 	}
    295 
    296 	/*
    297 	 * find an available minor device number for this mount
    298 	 */
    299 	mutex_enter(&tmpfs_minor_lock);
    300 	do {
    301 		tmpfs_minor = (tmpfs_minor + 1) & L_MAXMIN32;
    302 		tm->tm_dev = makedevice(tmpfs_major, tmpfs_minor);
    303 	} while (vfs_devismounted(tm->tm_dev));
    304 	mutex_exit(&tmpfs_minor_lock);
    305 
    306 	/*
    307 	 * Set but don't bother entering the mutex
    308 	 * (tmount not on mount list yet)
    309 	 */
    310 	mutex_init(&tm->tm_contents, NULL, MUTEX_DEFAULT, NULL);
    311 	mutex_init(&tm->tm_renamelck, NULL, MUTEX_DEFAULT, NULL);
    312 
    313 	tm->tm_vfsp = vfsp;
    314 	tm->tm_anonmax = anonmax;
    315 
    316 	vfsp->vfs_data = (caddr_t)tm;
    317 	vfsp->vfs_fstype = tmpfsfstype;
    318 	vfsp->vfs_dev = tm->tm_dev;
    319 	vfsp->vfs_bsize = PAGESIZE;
    320 	vfsp->vfs_flag |= VFS_NOTRUNC;
    321 	vfs_make_fsid(&vfsp->vfs_fsid, tm->tm_dev, tmpfsfstype);
    322 	tm->tm_mntpath = tmp_memalloc(dpn.pn_pathlen + 1, TMP_MUSTHAVE);
    323 	(void) strcpy(tm->tm_mntpath, dpn.pn_path);
    324 
    325 	/*
    326 	 * allocate and initialize root tmpnode structure
    327 	 */
    328 	bzero(&rattr, sizeof (struct vattr));
    329 	rattr.va_mode = (mode_t)(S_IFDIR | 0777);	/* XXX modes */
    330 	rattr.va_type = VDIR;
    331 	rattr.va_rdev = 0;
    332 	tp = tmp_memalloc(sizeof (struct tmpnode), TMP_MUSTHAVE);
    333 	tmpnode_init(tm, tp, &rattr, cr);
    334 
    335 	/*
    336 	 * Get the mode, uid, and gid from the underlying mount point.
    337 	 */
    338 	rattr.va_mask = AT_MODE|AT_UID|AT_GID;	/* Hint to getattr */
    339 	got_attrs = VOP_GETATTR(mvp, &rattr, 0, cr, NULL);
    340 
    341 	rw_enter(&tp->tn_rwlock, RW_WRITER);
    342 	TNTOV(tp)->v_flag |= VROOT;
    343 
    344 	/*
    345 	 * If the getattr succeeded, use its results.  Otherwise allow
    346 	 * the previously set hardwired defaults to prevail.
    347 	 */
    348 	if (got_attrs == 0) {
    349 		tp->tn_mode = rattr.va_mode;
    350 		tp->tn_uid = rattr.va_uid;
    351 		tp->tn_gid = rattr.va_gid;
    352 	}
    353 
    354 	/*
    355 	 * initialize linked list of tmpnodes so that the back pointer of
    356 	 * the root tmpnode always points to the last one on the list
    357 	 * and the forward pointer of the last node is null
    358 	 */
    359 	tp->tn_back = tp;
    360 	tp->tn_forw = NULL;
    361 	tp->tn_nlink = 0;
    362 	tm->tm_rootnode = tp;
    363 
    364 	tdirinit(tp, tp);
    365 
    366 	rw_exit(&tp->tn_rwlock);
    367 
    368 	pn_free(&dpn);
    369 	error = 0;
    370 
    371 out:
    372 	if (error == 0)
    373 		vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS);
    374 
    375 	return (error);
    376 }
    377 
    378 static int
    379 tmp_unmount(struct vfs *vfsp, int flag, struct cred *cr)
    380 {
    381 	struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
    382 	struct tmpnode *tnp, *cancel;
    383 	struct vnode	*vp;
    384 	int error;
    385 
    386 	if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0)
    387 		return (error);
    388 
    389 	/*
    390 	 * forced unmount is not supported by this file system
    391 	 * and thus, ENOTSUP, is being returned.
    392 	 */
    393 	if (flag & MS_FORCE)
    394 		return (ENOTSUP);
    395 
    396 	mutex_enter(&tm->tm_contents);
    397 
    398 	/*
    399 	 * If there are no open files, only the root node should have
    400 	 * a reference count.
    401 	 * With tm_contents held, nothing can be added or removed.
    402 	 * There may be some dirty pages.  To prevent fsflush from
    403 	 * disrupting the unmount, put a hold on each node while scanning.
    404 	 * If we find a previously referenced node, undo the holds we have
    405 	 * placed and fail EBUSY.
    406 	 */
    407 	tnp = tm->tm_rootnode;
    408 	if (TNTOV(tnp)->v_count > 1) {
    409 		mutex_exit(&tm->tm_contents);
    410 		return (EBUSY);
    411 	}
    412 
    413 	for (tnp = tnp->tn_forw; tnp; tnp = tnp->tn_forw) {
    414 		if ((vp = TNTOV(tnp))->v_count > 0) {
    415 			cancel = tm->tm_rootnode->tn_forw;
    416 			while (cancel != tnp) {
    417 				vp = TNTOV(cancel);
    418 				ASSERT(vp->v_count > 0);
    419 				VN_RELE(vp);
    420 				cancel = cancel->tn_forw;
    421 			}
    422 			mutex_exit(&tm->tm_contents);
    423 			return (EBUSY);
    424 		}
    425 		VN_HOLD(vp);
    426 	}
    427 
    428 	/*
    429 	 * We can drop the mutex now because no one can find this mount
    430 	 */
    431 	mutex_exit(&tm->tm_contents);
    432 
    433 	/*
    434 	 * Free all kmemalloc'd and anonalloc'd memory associated with
    435 	 * this filesystem.  To do this, we go through the file list twice,
    436 	 * once to remove all the directory entries, and then to remove
    437 	 * all the files.  We do this because there is useful code in
    438 	 * tmpnode_free which assumes that the directory entry has been
    439 	 * removed before the file.
    440 	 */
    441 	/*
    442 	 * Remove all directory entries
    443 	 */
    444 	for (tnp = tm->tm_rootnode; tnp; tnp = tnp->tn_forw) {
    445 		rw_enter(&tnp->tn_rwlock, RW_WRITER);
    446 		if (tnp->tn_type == VDIR)
    447 			tdirtrunc(tnp);
    448 		if (tnp->tn_vnode->v_flag & V_XATTRDIR) {
    449 			/*
    450 			 * Account for implicit attrdir reference.
    451 			 */
    452 			ASSERT(tnp->tn_nlink > 0);
    453 			DECR_COUNT(&tnp->tn_nlink, &tnp->tn_tlock);
    454 		}
    455 		rw_exit(&tnp->tn_rwlock);
    456 	}
    457 
    458 	ASSERT(tm->tm_rootnode);
    459 
    460 	/*
    461 	 * All links are gone, v_count is keeping nodes in place.
    462 	 * VN_RELE should make the node disappear, unless somebody
    463 	 * is holding pages against it.  Nap and retry until it disappears.
    464 	 *
    465 	 * We re-acquire the lock to prevent others who have a HOLD on
    466 	 * a tmpnode via its pages or anon slots from blowing it away
    467 	 * (in tmp_inactive) while we're trying to get to it here. Once
    468 	 * we have a HOLD on it we know it'll stick around.
    469 	 *
    470 	 */
    471 	mutex_enter(&tm->tm_contents);
    472 	/*
    473 	 * Remove all the files (except the rootnode) backwards.
    474 	 */
    475 	while ((tnp = tm->tm_rootnode->tn_back) != tm->tm_rootnode) {
    476 		mutex_exit(&tm->tm_contents);
    477 		/*
    478 		 * Inhibit tmp_inactive from touching attribute directory
    479 		 * as all nodes will be released here.
    480 		 * Note we handled the link count in pass 2 above.
    481 		 */
    482 		rw_enter(&tnp->tn_rwlock, RW_WRITER);
    483 		tnp->tn_xattrdp = NULL;
    484 		rw_exit(&tnp->tn_rwlock);
    485 		vp = TNTOV(tnp);
    486 		VN_RELE(vp);
    487 		mutex_enter(&tm->tm_contents);
    488 		/*
    489 		 * It's still there after the RELE. Someone else like pageout
    490 		 * has a hold on it so wait a bit and then try again - we know
    491 		 * they'll give it up soon.
    492 		 */
    493 		if (tnp == tm->tm_rootnode->tn_back) {
    494 			VN_HOLD(vp);
    495 			mutex_exit(&tm->tm_contents);
    496 			delay(hz / 4);
    497 			mutex_enter(&tm->tm_contents);
    498 		}
    499 	}
    500 	mutex_exit(&tm->tm_contents);
    501 
    502 	tm->tm_rootnode->tn_xattrdp = NULL;
    503 	VN_RELE(TNTOV(tm->tm_rootnode));
    504 
    505 	ASSERT(tm->tm_mntpath);
    506 
    507 	tmp_memfree(tm->tm_mntpath, strlen(tm->tm_mntpath) + 1);
    508 
    509 	ASSERT(tm->tm_anonmem == 0);
    510 
    511 	mutex_destroy(&tm->tm_contents);
    512 	mutex_destroy(&tm->tm_renamelck);
    513 	tmp_memfree(tm, sizeof (struct tmount));
    514 
    515 	return (0);
    516 }
    517 
    518 /*
    519  * return root tmpnode for given vnode
    520  */
    521 static int
    522 tmp_root(struct vfs *vfsp, struct vnode **vpp)
    523 {
    524 	struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
    525 	struct tmpnode *tp = tm->tm_rootnode;
    526 	struct vnode *vp;
    527 
    528 	ASSERT(tp);
    529 
    530 	vp = TNTOV(tp);
    531 	VN_HOLD(vp);
    532 	*vpp = vp;
    533 	return (0);
    534 }
    535 
    536 static int
    537 tmp_statvfs(struct vfs *vfsp, struct statvfs64 *sbp)
    538 {
    539 	struct tmount	*tm = (struct tmount *)VFSTOTM(vfsp);
    540 	ulong_t	blocks;
    541 	dev32_t d32;
    542 	zoneid_t eff_zid;
    543 	struct zone *zp;
    544 
    545 	/*
    546 	 * The file system may have been mounted by the global zone on
    547 	 * behalf of the non-global zone.  In that case, the tmount zone_id
    548 	 * will be the global zone.  We still want to show the swap cap inside
    549 	 * the zone in this case, even though the file system was mounted by
    550 	 * the global zone.
    551 	 */
    552 	if (curproc->p_zone->zone_id != GLOBAL_ZONEUNIQID)
    553 		zp = curproc->p_zone;
    554 	else
    555 		zp = tm->tm_vfsp->vfs_zone;
    556 
    557 	if (zp == NULL)
    558 		eff_zid = GLOBAL_ZONEUNIQID;
    559 	else
    560 		eff_zid = zp->zone_id;
    561 
    562 	sbp->f_bsize = PAGESIZE;
    563 	sbp->f_frsize = PAGESIZE;
    564 
    565 	/*
    566 	 * Find the amount of available physical and memory swap
    567 	 */
    568 	mutex_enter(&anoninfo_lock);
    569 	ASSERT(k_anoninfo.ani_max >= k_anoninfo.ani_phys_resv);
    570 	blocks = (ulong_t)CURRENT_TOTAL_AVAILABLE_SWAP;
    571 	mutex_exit(&anoninfo_lock);
    572 
    573 	/*
    574 	 * If tm_anonmax for this mount is less than the available swap space
    575 	 * (minus the amount tmpfs can't use), use that instead
    576 	 */
    577 	if (blocks > tmpfs_minfree)
    578 		sbp->f_bfree = MIN(blocks - tmpfs_minfree,
    579 		    tm->tm_anonmax - tm->tm_anonmem);
    580 	else
    581 		sbp->f_bfree = 0;
    582 
    583 	sbp->f_bavail = sbp->f_bfree;
    584 
    585 	/*
    586 	 * Total number of blocks is what's available plus what's been used
    587 	 */
    588 	sbp->f_blocks = (fsblkcnt64_t)(sbp->f_bfree + tm->tm_anonmem);
    589 
    590 	if (eff_zid != GLOBAL_ZONEUNIQID &&
    591 	    zp->zone_max_swap_ctl != UINT64_MAX) {
    592 		/*
    593 		 * If the fs is used by a non-global zone with a swap cap,
    594 		 * then report the capped size.
    595 		 */
    596 		rctl_qty_t cap, used;
    597 		pgcnt_t pgcap, pgused;
    598 
    599 		mutex_enter(&zp->zone_mem_lock);
    600 		cap = zp->zone_max_swap_ctl;
    601 		used = zp->zone_max_swap;
    602 		mutex_exit(&zp->zone_mem_lock);
    603 
    604 		pgcap = btop(cap);
    605 		pgused = btop(used);
    606 
    607 		sbp->f_bfree = MIN(pgcap - pgused, sbp->f_bfree);
    608 		sbp->f_bavail = sbp->f_bfree;
    609 		sbp->f_blocks = MIN(pgcap, sbp->f_blocks);
    610 	}
    611 
    612 	/*
    613 	 * The maximum number of files available is approximately the number
    614 	 * of tmpnodes we can allocate from the remaining kernel memory
    615 	 * available to tmpfs.  This is fairly inaccurate since it doesn't
    616 	 * take into account the names stored in the directory entries.
    617 	 */
    618 	if (tmpfs_maxkmem > tmp_kmemspace)
    619 		sbp->f_ffree = (tmpfs_maxkmem - tmp_kmemspace) /
    620 		    (sizeof (struct tmpnode) + sizeof (struct tdirent));
    621 	else
    622 		sbp->f_ffree = 0;
    623 
    624 	sbp->f_files = tmpfs_maxkmem /
    625 	    (sizeof (struct tmpnode) + sizeof (struct tdirent));
    626 	sbp->f_favail = (fsfilcnt64_t)(sbp->f_ffree);
    627 	(void) cmpldev(&d32, vfsp->vfs_dev);
    628 	sbp->f_fsid = d32;
    629 	(void) strcpy(sbp->f_basetype, vfssw[tmpfsfstype].vsw_name);
    630 	(void) strncpy(sbp->f_fstr, tm->tm_mntpath, sizeof (sbp->f_fstr));
    631 	/*
    632 	 * ensure null termination
    633 	 */
    634 	sbp->f_fstr[sizeof (sbp->f_fstr) - 1] = '\0';
    635 	sbp->f_flag = vf_to_stf(vfsp->vfs_flag);
    636 	sbp->f_namemax = MAXNAMELEN - 1;
    637 	return (0);
    638 }
    639 
    640 static int
    641 tmp_vget(struct vfs *vfsp, struct vnode **vpp, struct fid *fidp)
    642 {
    643 	struct tfid *tfid;
    644 	struct tmount *tm = (struct tmount *)VFSTOTM(vfsp);
    645 	struct tmpnode *tp = NULL;
    646 
    647 	tfid = (struct tfid *)fidp;
    648 	*vpp = NULL;
    649 
    650 	mutex_enter(&tm->tm_contents);
    651 	for (tp = tm->tm_rootnode; tp; tp = tp->tn_forw) {
    652 		mutex_enter(&tp->tn_tlock);
    653 		if (tp->tn_nodeid == tfid->tfid_ino) {
    654 			/*
    655 			 * If the gen numbers don't match we know the
    656 			 * file won't be found since only one tmpnode
    657 			 * can have this number at a time.
    658 			 */
    659 			if (tp->tn_gen != tfid->tfid_gen || tp->tn_nlink == 0) {
    660 				mutex_exit(&tp->tn_tlock);
    661 				mutex_exit(&tm->tm_contents);
    662 				return (0);
    663 			}
    664 			*vpp = (struct vnode *)TNTOV(tp);
    665 
    666 			VN_HOLD(*vpp);
    667 
    668 			if ((tp->tn_mode & S_ISVTX) &&
    669 			    !(tp->tn_mode & (S_IXUSR | S_IFDIR))) {
    670 				mutex_enter(&(*vpp)->v_lock);
    671 				(*vpp)->v_flag |= VISSWAP;
    672 				mutex_exit(&(*vpp)->v_lock);
    673 			}
    674 			mutex_exit(&tp->tn_tlock);
    675 			mutex_exit(&tm->tm_contents);
    676 			return (0);
    677 		}
    678 		mutex_exit(&tp->tn_tlock);
    679 	}
    680 	mutex_exit(&tm->tm_contents);
    681 	return (0);
    682 }
    683