1139776Simp/*-
222521Sdyson * Copyright (c) 1992, 1993, 1995
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software donated to Berkeley by
61541Srgrimes * Jan-Simon Pendry.
71541Srgrimes *
81541Srgrimes * Redistribution and use in source and binary forms, with or without
91541Srgrimes * modification, are permitted provided that the following conditions
101541Srgrimes * are met:
111541Srgrimes * 1. Redistributions of source code must retain the above copyright
121541Srgrimes *    notice, this list of conditions and the following disclaimer.
131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer in the
151541Srgrimes *    documentation and/or other materials provided with the distribution.
161541Srgrimes * 4. Neither the name of the University nor the names of its contributors
171541Srgrimes *    may be used to endorse or promote products derived from this software
181541Srgrimes *    without specific prior written permission.
191541Srgrimes *
201541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301541Srgrimes * SUCH DAMAGE.
311541Srgrimes *
321541Srgrimes *	@(#)null_vfsops.c	8.2 (Berkeley) 1/21/94
331541Srgrimes *
341541Srgrimes * @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
3550477Speter * $FreeBSD: stable/11/sys/fs/nullfs/null_vfsops.c 357508 2020-02-04 17:17:40Z kib $
361541Srgrimes */
371541Srgrimes
381541Srgrimes/*
391541Srgrimes * Null Layer
401541Srgrimes * (See null_vnops.c for a description of what this does.)
411541Srgrimes */
421541Srgrimes
431541Srgrimes#include <sys/param.h>
441541Srgrimes#include <sys/systm.h>
45177785Skib#include <sys/fcntl.h>
4622605Smpp#include <sys/kernel.h>
4776166Smarkm#include <sys/lock.h>
4830354Sphk#include <sys/malloc.h>
491541Srgrimes#include <sys/mount.h>
501541Srgrimes#include <sys/namei.h>
5176166Smarkm#include <sys/proc.h>
5276166Smarkm#include <sys/vnode.h>
53232059Smm#include <sys/jail.h>
5476166Smarkm
5577031Sru#include <fs/nullfs/null.h>
561541Srgrimes
57151897Srwatsonstatic MALLOC_DEFINE(M_NULLFSMNT, "nullfs_mount", "NULLFS mount structure");
5830354Sphk
59116271Sphkstatic vfs_fhtovp_t	nullfs_fhtovp;
60132902Sphkstatic vfs_mount_t	nullfs_mount;
61116271Sphkstatic vfs_quotactl_t	nullfs_quotactl;
62116271Sphkstatic vfs_root_t	nullfs_root;
63116271Sphkstatic vfs_sync_t	nullfs_sync;
64116271Sphkstatic vfs_statfs_t	nullfs_statfs;
65116271Sphkstatic vfs_unmount_t	nullfs_unmount;
66116271Sphkstatic vfs_vget_t	nullfs_vget;
67116271Sphkstatic vfs_extattrctl_t	nullfs_extattrctl;
6812595Sbde
691541Srgrimes/*
701541Srgrimes * Mount null layer
711541Srgrimes */
7212769Sphkstatic int
73191990Sattilionullfs_mount(struct mount *mp)
741541Srgrimes{
75357508Skib	struct vnode *lowerrootvp;
761541Srgrimes	struct vnode *nullm_rootvp;
771541Srgrimes	struct null_mount *xmp;
78232059Smm	struct thread *td = curthread;
79344155Skib	struct null_node *nn;
80344155Skib	struct nameidata nd, *ndp;
8197186Smux	char *target;
82344155Skib	int error, len;
83344155Skib	bool isvnunlocked;
841541Srgrimes
8565467Sbp	NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
861541Srgrimes
87232059Smm	if (!prison_allow(td->td_ucred, PR_ALLOW_MOUNT_NULLFS))
88232059Smm		return (EPERM);
89137479Sphk	if (mp->mnt_flag & MNT_ROOTFS)
90137479Sphk		return (EOPNOTSUPP);
91245004Skib
921541Srgrimes	/*
931541Srgrimes	 * Update is a no-op
941541Srgrimes	 */
951541Srgrimes	if (mp->mnt_flag & MNT_UPDATE) {
96159019Srodrigc		/*
97159019Srodrigc		 * Only support update mounts for NFS export.
98159019Srodrigc		 */
99159019Srodrigc		if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0))
100159019Srodrigc			return (0);
101159019Srodrigc		else
102159019Srodrigc			return (EOPNOTSUPP);
1031541Srgrimes	}
1041541Srgrimes
1051541Srgrimes	/*
1061541Srgrimes	 * Get argument
1071541Srgrimes	 */
10897186Smux	error = vfs_getopt(mp->mnt_optnew, "target", (void **)&target, &len);
10997186Smux	if (error || target[len - 1] != '\0')
11097186Smux		return (EINVAL);
1111541Srgrimes
1121541Srgrimes	/*
113226681Spho	 * Unlock lower node to avoid possible deadlock.
11424988Skato	 */
115344155Skib	if (mp->mnt_vnodecovered->v_op == &null_vnodeops &&
116226681Spho	    VOP_ISLOCKED(mp->mnt_vnodecovered) == LK_EXCLUSIVE) {
117175294Sattilio		VOP_UNLOCK(mp->mnt_vnodecovered, 0);
118344155Skib		isvnunlocked = true;
119344155Skib	} else {
120344155Skib		isvnunlocked = false;
12124988Skato	}
122344155Skib
12324988Skato	/*
1241541Srgrimes	 * Find lower node
1251541Srgrimes	 */
126344155Skib	ndp = &nd;
127191990Sattilio	NDINIT(ndp, LOOKUP, FOLLOW|LOCKLEAF, UIO_SYSSPACE, target, curthread);
1283496Sphk	error = namei(ndp);
129240285Skib
13024988Skato	/*
13124988Skato	 * Re-lock vnode.
132240285Skib	 * XXXKIB This is deadlock-prone as well.
13324988Skato	 */
134226686Skib	if (isvnunlocked)
135175202Sattilio		vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY);
13624988Skato
1373496Sphk	if (error)
1381541Srgrimes		return (error);
13954655Seivind	NDFREE(ndp, NDF_ONLY_PNBUF);
1401541Srgrimes
1411541Srgrimes	/*
1421541Srgrimes	 * Sanity check on lower vnode
1431541Srgrimes	 */
1441541Srgrimes	lowerrootvp = ndp->ni_vp;
1451541Srgrimes
14624988Skato	/*
14724988Skato	 * Check multi null mount to avoid `lock against myself' panic.
14824988Skato	 */
149344155Skib	if (mp->mnt_vnodecovered->v_op == &null_vnodeops) {
150344155Skib		nn = VTONULL(mp->mnt_vnodecovered);
151344155Skib		if (nn == NULL || lowerrootvp == nn->null_lowervp) {
152344155Skib			NULLFSDEBUG("nullfs_mount: multi null mount?\n");
153344155Skib			vput(lowerrootvp);
154344155Skib			return (EDEADLK);
155344155Skib		}
15624988Skato	}
15724988Skato
1581541Srgrimes	xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
159245004Skib	    M_NULLFSMNT, M_WAITOK | M_ZERO);
1601541Srgrimes
1611541Srgrimes	/*
162357508Skib	 * Save pointer to underlying FS and the reference to the
163357508Skib	 * lower root vnode.
1641541Srgrimes	 */
1651541Srgrimes	xmp->nullm_vfs = lowerrootvp->v_mount;
166357508Skib	vref(lowerrootvp);
167357508Skib	xmp->nullm_lowerrootvp = lowerrootvp;
168357508Skib	mp->mnt_data = xmp;
1691541Srgrimes
1701541Srgrimes	/*
171357508Skib	 * Make sure the node alias worked.
1721541Srgrimes	 */
173357508Skib	error = null_nodeget(mp, lowerrootvp, &nullm_rootvp);
174357508Skib	if (error != 0) {
175357508Skib		vrele(lowerrootvp);
176229431Skib		free(xmp, M_NULLFSMNT);
1771541Srgrimes		return (error);
1781541Srgrimes	}
1791541Srgrimes
180162647Stegge	if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
181162647Stegge		MNT_ILOCK(mp);
1821541Srgrimes		mp->mnt_flag |= MNT_LOCAL;
183162647Stegge		MNT_IUNLOCK(mp);
184162647Stegge	}
185245004Skib
186245004Skib	xmp->nullm_flags |= NULLM_CACHE;
187309520Skib	if (vfs_getopt(mp->mnt_optnew, "nocache", NULL, NULL) == 0 ||
188309520Skib	    (xmp->nullm_vfs->mnt_kern_flag & MNTK_NULL_NOCACHE) != 0)
189245004Skib		xmp->nullm_flags &= ~NULLM_CACHE;
190245004Skib
191162647Stegge	MNT_ILOCK(mp);
192245004Skib	if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
193245004Skib		mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
194245004Skib		    (MNTK_SHARED_WRITES | MNTK_LOOKUP_SHARED |
195245004Skib		    MNTK_EXTENDED_SHARED);
196245004Skib	}
197240285Skib	mp->mnt_kern_flag |= MNTK_LOOKUP_EXCL_DOTDOT;
198273336Smjg	mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag &
199296388Skib	    (MNTK_USES_BCACHE | MNTK_NO_IOPF | MNTK_UNMAPPED_BUFS);
200162647Stegge	MNT_IUNLOCK(mp);
20122521Sdyson	vfs_getnewfsid(mp);
202245004Skib	if ((xmp->nullm_flags & NULLM_CACHE) != 0) {
203245004Skib		MNT_ILOCK(xmp->nullm_vfs);
204245004Skib		TAILQ_INSERT_TAIL(&xmp->nullm_vfs->mnt_uppers, mp,
205245004Skib		    mnt_upper_link);
206245004Skib		MNT_IUNLOCK(xmp->nullm_vfs);
207245004Skib	}
2081541Srgrimes
209138483Sphk	vfs_mountedfrom(mp, target);
210357508Skib	vput(nullm_rootvp);
211138483Sphk
21265467Sbp	NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
2131541Srgrimes		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
2141541Srgrimes	return (0);
2151541Srgrimes}
2161541Srgrimes
2171541Srgrimes/*
2181541Srgrimes * Free reference to null layer
2191541Srgrimes */
22012769Sphkstatic int
221191990Sattilionullfs_unmount(mp, mntflags)
2221541Srgrimes	struct mount *mp;
2231541Srgrimes	int mntflags;
2241541Srgrimes{
225240285Skib	struct null_mount *mntdata;
226240285Skib	struct mount *ump;
227357508Skib	int error, flags;
2281541Srgrimes
22965467Sbp	NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp);
2301541Srgrimes
23122521Sdyson	if (mntflags & MNT_FORCE)
232240285Skib		flags = FORCECLOSE;
233240285Skib	else
234240285Skib		flags = 0;
2351541Srgrimes
236357508Skib	for (;;) {
237345642Skib		/* There is 1 extra root vnode reference (nullm_rootvp). */
238357508Skib		error = vflush(mp, 0, flags, curthread);
239345642Skib		if (error)
240345642Skib			return (error);
241345642Skib		MNT_ILOCK(mp);
242345642Skib		if (mp->mnt_nvnodelistsize == 0) {
243345642Skib			MNT_IUNLOCK(mp);
244345642Skib			break;
245345642Skib		}
246345642Skib		MNT_IUNLOCK(mp);
247345642Skib		if ((mntflags & MNT_FORCE) == 0)
248345642Skib			return (EBUSY);
249345642Skib	}
2501541Srgrimes
2511541Srgrimes	/*
2521541Srgrimes	 * Finally, throw away the null_mount structure
2531541Srgrimes	 */
25465467Sbp	mntdata = mp->mnt_data;
255240285Skib	ump = mntdata->nullm_vfs;
256245004Skib	if ((mntdata->nullm_flags & NULLM_CACHE) != 0) {
257245004Skib		MNT_ILOCK(ump);
258245004Skib		while ((ump->mnt_kern_flag & MNTK_VGONE_UPPER) != 0) {
259245004Skib			ump->mnt_kern_flag |= MNTK_VGONE_WAITER;
260245004Skib			msleep(&ump->mnt_uppers, &ump->mnt_mtx, 0, "vgnupw", 0);
261245004Skib		}
262245004Skib		TAILQ_REMOVE(&ump->mnt_uppers, mp, mnt_upper_link);
263245004Skib		MNT_IUNLOCK(ump);
264240285Skib	}
265357508Skib	vrele(mntdata->nullm_lowerrootvp);
266232918Skevlo	mp->mnt_data = NULL;
26766356Sbp	free(mntdata, M_NULLFSMNT);
268240285Skib	return (0);
2691541Srgrimes}
2701541Srgrimes
27112769Sphkstatic int
272191990Sattilionullfs_root(mp, flags, vpp)
2731541Srgrimes	struct mount *mp;
274144058Sjeff	int flags;
2751541Srgrimes	struct vnode **vpp;
2761541Srgrimes{
2771541Srgrimes	struct vnode *vp;
278357508Skib	struct null_mount *mntdata;
279357508Skib	int error;
2801541Srgrimes
281357508Skib	mntdata = MOUNTTONULLMOUNT(mp);
282357508Skib	NULLFSDEBUG("nullfs_root(mp = %p, vp = %p)\n", mp,
283357508Skib	    mntdata->nullm_lowerrootvp);
2841541Srgrimes
285357508Skib	error = vget(mntdata->nullm_lowerrootvp, (flags & ~LK_TYPE_MASK) |
286357508Skib	    LK_EXCLUSIVE, curthread);
287357508Skib	if (error == 0) {
288357508Skib		error = null_nodeget(mp, mntdata->nullm_lowerrootvp, &vp);
289357508Skib		if (error == 0) {
290357508Skib			if ((flags & LK_TYPE_MASK) == LK_SHARED)
291357508Skib				vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
292357508Skib			*vpp = vp;
293357508Skib		}
294357508Skib	}
295357508Skib	return (error);
2961541Srgrimes}
2971541Srgrimes
29812769Sphkstatic int
299191990Sattilionullfs_quotactl(mp, cmd, uid, arg)
3001541Srgrimes	struct mount *mp;
3011541Srgrimes	int cmd;
3021541Srgrimes	uid_t uid;
303153400Sdes	void *arg;
3041541Srgrimes{
305191990Sattilio	return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg);
3061541Srgrimes}
3071541Srgrimes
30812769Sphkstatic int
309191990Sattilionullfs_statfs(mp, sbp)
3101541Srgrimes	struct mount *mp;
3111541Srgrimes	struct statfs *sbp;
3121541Srgrimes{
3131541Srgrimes	int error;
314311957Skib	struct statfs *mstat;
3151541Srgrimes
31665467Sbp	NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p->%p)\n", (void *)mp,
31737977Sbde	    (void *)MOUNTTONULLMOUNT(mp)->nullm_rootvp,
31837977Sbde	    (void *)NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp));
3191541Srgrimes
320311957Skib	mstat = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK | M_ZERO);
3211541Srgrimes
322311957Skib	error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, mstat);
323311957Skib	if (error) {
324311957Skib		free(mstat, M_STATFS);
3251541Srgrimes		return (error);
326311957Skib	}
3271541Srgrimes
3281541Srgrimes	/* now copy across the "interesting" information and fake the rest */
329311957Skib	sbp->f_type = mstat->f_type;
330247619Sjilles	sbp->f_flags = (sbp->f_flags & (MNT_RDONLY | MNT_NOEXEC | MNT_NOSUID |
331332613Strasz	    MNT_UNION | MNT_NOSYMFOLLOW | MNT_AUTOMOUNTED)) |
332332613Strasz	    (mstat->f_flags & ~(MNT_ROOTFS | MNT_AUTOMOUNTED));
333311957Skib	sbp->f_bsize = mstat->f_bsize;
334311957Skib	sbp->f_iosize = mstat->f_iosize;
335311957Skib	sbp->f_blocks = mstat->f_blocks;
336311957Skib	sbp->f_bfree = mstat->f_bfree;
337311957Skib	sbp->f_bavail = mstat->f_bavail;
338311957Skib	sbp->f_files = mstat->f_files;
339311957Skib	sbp->f_ffree = mstat->f_ffree;
340311957Skib
341311957Skib	free(mstat, M_STATFS);
3421541Srgrimes	return (0);
3431541Srgrimes}
3441541Srgrimes
34512769Sphkstatic int
346191990Sattilionullfs_sync(mp, waitfor)
3471541Srgrimes	struct mount *mp;
3481541Srgrimes	int waitfor;
3491541Srgrimes{
3501541Srgrimes	/*
3511541Srgrimes	 * XXX - Assumes no data cached at null layer.
3521541Srgrimes	 */
3531541Srgrimes	return (0);
3541541Srgrimes}
3551541Srgrimes
35612769Sphkstatic int
35792462Smckusicknullfs_vget(mp, ino, flags, vpp)
3581541Srgrimes	struct mount *mp;
3591541Srgrimes	ino_t ino;
36092462Smckusick	int flags;
3611541Srgrimes	struct vnode **vpp;
3621541Srgrimes{
36366356Sbp	int error;
364232301Skib
365232301Skib	KASSERT((flags & LK_TYPE_MASK) != 0,
366232301Skib	    ("nullfs_vget: no lock requested"));
367232301Skib
36892462Smckusick	error = VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, flags, vpp);
369240285Skib	if (error != 0)
37066356Sbp		return (error);
37198183Ssemenu	return (null_nodeget(mp, *vpp, vpp));
3721541Srgrimes}
3731541Srgrimes
37412769Sphkstatic int
375222167Srmacklemnullfs_fhtovp(mp, fidp, flags, vpp)
3761541Srgrimes	struct mount *mp;
3771541Srgrimes	struct fid *fidp;
378222167Srmacklem	int flags;
3791541Srgrimes	struct vnode **vpp;
3801541Srgrimes{
38166356Sbp	int error;
382240285Skib
383240285Skib	error = VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, flags,
384222167Srmacklem	    vpp);
385240285Skib	if (error != 0)
38666356Sbp		return (error);
38798183Ssemenu	return (null_nodeget(mp, *vpp, vpp));
3881541Srgrimes}
3891541Srgrimes
39054803Srwatsonstatic int
391191990Sattilionullfs_extattrctl(mp, cmd, filename_vp, namespace, attrname)
39254803Srwatson	struct mount *mp;
39354803Srwatson	int cmd;
39474273Srwatson	struct vnode *filename_vp;
39574273Srwatson	int namespace;
39656272Srwatson	const char *attrname;
39754803Srwatson{
398240285Skib
399240285Skib	return (VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd,
400240285Skib	    filename_vp, namespace, attrname));
40154803Srwatson}
40254803Srwatson
403240285Skibstatic void
404240285Skibnullfs_reclaim_lowervp(struct mount *mp, struct vnode *lowervp)
405240285Skib{
406240285Skib	struct vnode *vp;
40754803Srwatson
408240285Skib	vp = null_hashget(mp, lowervp);
409240285Skib	if (vp == NULL)
410240285Skib		return;
411250505Skib	VTONULL(vp)->null_flags |= NULLV_NOUNLOCK;
412240285Skib	vgone(vp);
413250505Skib	vput(vp);
414240285Skib}
415240285Skib
416250505Skibstatic void
417250505Skibnullfs_unlink_lowervp(struct mount *mp, struct vnode *lowervp)
418250505Skib{
419250505Skib	struct vnode *vp;
420250505Skib	struct null_node *xp;
421250505Skib
422250505Skib	vp = null_hashget(mp, lowervp);
423250505Skib	if (vp == NULL)
424250505Skib		return;
425250505Skib	xp = VTONULL(vp);
426250505Skib	xp->null_flags |= NULLV_DROP | NULLV_NOUNLOCK;
427250505Skib	vhold(vp);
428250505Skib	vunref(vp);
429250505Skib
430250505Skib	if (vp->v_usecount == 0) {
431250852Skib		/*
432250852Skib		 * If vunref() dropped the last use reference on the
433250852Skib		 * nullfs vnode, it must be reclaimed, and its lock
434250852Skib		 * was split from the lower vnode lock.  Need to do
435250852Skib		 * extra unlock before allowing the final vdrop() to
436250852Skib		 * free the vnode.
437250852Skib		 */
438250505Skib		KASSERT((vp->v_iflag & VI_DOOMED) != 0,
439250852Skib		    ("not reclaimed nullfs vnode %p", vp));
440250505Skib		VOP_UNLOCK(vp, 0);
441250852Skib	} else {
442250852Skib		/*
443250852Skib		 * Otherwise, the nullfs vnode still shares the lock
444250852Skib		 * with the lower vnode, and must not be unlocked.
445250852Skib		 * Also clear the NULLV_NOUNLOCK, the flag is not
446250852Skib		 * relevant for future reclamations.
447250852Skib		 */
448250852Skib		ASSERT_VOP_ELOCKED(vp, "unlink_lowervp");
449250852Skib		KASSERT((vp->v_iflag & VI_DOOMED) == 0,
450250852Skib		    ("reclaimed nullfs vnode %p", vp));
451250852Skib		xp->null_flags &= ~NULLV_NOUNLOCK;
452250505Skib	}
453250505Skib	vdrop(vp);
454250505Skib}
455250505Skib
45612769Sphkstatic struct vfsops null_vfsops = {
457116271Sphk	.vfs_extattrctl =	nullfs_extattrctl,
458116271Sphk	.vfs_fhtovp =		nullfs_fhtovp,
459116271Sphk	.vfs_init =		nullfs_init,
460132902Sphk	.vfs_mount =		nullfs_mount,
461116271Sphk	.vfs_quotactl =		nullfs_quotactl,
462116271Sphk	.vfs_root =		nullfs_root,
463116271Sphk	.vfs_statfs =		nullfs_statfs,
464116271Sphk	.vfs_sync =		nullfs_sync,
465116271Sphk	.vfs_uninit =		nullfs_uninit,
466116271Sphk	.vfs_unmount =		nullfs_unmount,
467116271Sphk	.vfs_vget =		nullfs_vget,
468240285Skib	.vfs_reclaim_lowervp =	nullfs_reclaim_lowervp,
469250505Skib	.vfs_unlink_lowervp =	nullfs_unlink_lowervp,
4701541Srgrimes};
4712946Swollman
472231269SmmVFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL);
473