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