2 * Copyright (c) 1992, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software donated to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94
38 * @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
39 * $FreeBSD: src/sys/miscfs/nullfs/null_vfsops.c,v 1.35.2.3 2001/07/26 20:37:11 iedowse Exp $
40 * $DragonFly: src/sys/vfs/nullfs/null_vfsops.c,v 1.29 2006/10/27 04:56:34 dillon Exp $
45 * (See null_vnops.c for a description of what this does.)
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
52 #include <sys/malloc.h>
53 #include <sys/vnode.h>
54 #include <sys/mount.h>
55 #include <sys/nlookup.h>
58 extern struct vop_ops null_vnode_vops
;
60 static MALLOC_DEFINE(M_NULLFSMNT
, "NULLFS mount", "NULLFS mount structure");
62 static int nullfs_root(struct mount
*mp
, struct vnode
**vpp
);
63 static int nullfs_statfs(struct mount
*mp
, struct statfs
*sbp
,
70 nullfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
73 struct null_args args
;
75 struct null_mount
*xmp
;
77 struct nlookupdata nd
;
79 NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp
);
84 if (mp
->mnt_flag
& MNT_UPDATE
) {
91 error
= copyin(data
, (caddr_t
)&args
, sizeof(struct null_args
));
99 error
= nlookup_init(&nd
, args
.target
, UIO_USERSPACE
, NLC_FOLLOW
);
102 error
= nlookup(&nd
);
105 error
= cache_vget(&nd
.nl_nch
, nd
.nl_cred
, LK_EXCLUSIVE
, &rootvp
);
109 xmp
= (struct null_mount
*) kmalloc(sizeof(struct null_mount
),
110 M_NULLFSMNT
, M_WAITOK
); /* XXX */
113 * Save reference to underlying FS
115 * As lite stacking enters the scene, the old way of doing this
116 * -- via the vnode -- is not good enough anymore. Use the
117 * underlying filesystem's namecache handle as our mount point
118 * root, adjusting the mount to point to us.
120 * NCF_ISMOUNTPT is normally set on the mount point, but we also
121 * want to set it on the base directory being mounted to prevent
122 * that directory from being destroyed out from under the nullfs
125 xmp
->nullm_vfs
= nd
.nl_nch
.mount
;
126 mp
->mnt_ncmountpt
= nd
.nl_nch
;
127 cache_changemount(&mp
->mnt_ncmountpt
, mp
);
128 mp
->mnt_ncmountpt
.ncp
->nc_flag
|= NCF_ISMOUNTPT
;
129 cache_unlock(&mp
->mnt_ncmountpt
);
130 cache_zero(&nd
.nl_nch
);
133 vfs_add_vnodeops(mp
, &null_vnode_vops
, &mp
->mnt_vn_norm_ops
);
135 vn_unlock(rootvp
); /* leave reference intact */
138 * Keep a held reference to the root vnode.
139 * It is vrele'd in nullfs_unmount.
141 xmp
->nullm_rootvp
= rootvp
;
143 * XXX What's the proper safety condition for querying
144 * the underlying mount? Is this flag tuning necessary
147 if (xmp
->nullm_vfs
->mnt_flag
& MNT_LOCAL
)
148 mp
->mnt_flag
|= MNT_LOCAL
;
149 mp
->mnt_data
= (qaddr_t
) xmp
;
152 (void) copyinstr(args
.target
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1,
154 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
155 (void)nullfs_statfs(mp
, &mp
->mnt_stat
, cred
);
156 NULLFSDEBUG("nullfs_mount: lower %s, alias at %s\n",
157 mp
->mnt_stat
.f_mntfromname
, mp
->mnt_stat
.f_mntfromname
);
160 * So unmount won't complain about namecache refs still existing
162 mp
->mnt_kern_flag
|= MNTK_NCALIASED
;
171 * Free reference to null layer
174 nullfs_unmount(struct mount
*mp
, int mntflags
)
176 struct null_mount
*xmp
;
179 NULLFSDEBUG("nullfs_unmount: mp = %p\n", (void *)mp
);
181 if (mntflags
& MNT_FORCE
)
185 * Finally, throw away the null_mount structure
187 xmp
= (void *)mp
->mnt_data
;
189 if (xmp
->nullm_rootvp
) {
190 vrele(xmp
->nullm_rootvp
);
191 xmp
->nullm_rootvp
= NULL
;
193 kfree(xmp
, M_NULLFSMNT
);
198 nullfs_root(struct mount
*mp
, struct vnode
**vpp
)
203 NULLFSDEBUG("nullfs_root(mp = %p, vp = %p)\n", (void *)mp
,
204 (void *)MOUNTTONULLMOUNT(mp
)->nullm_rootvp
);
207 * Return locked reference to root.
209 vp
= MOUNTTONULLMOUNT(mp
)->nullm_rootvp
;
210 error
= vget(vp
, LK_EXCLUSIVE
| LK_RETRY
);
217 nullfs_quotactl(struct mount
*mp
, int cmd
, uid_t uid
, caddr_t arg
,
220 return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, cmd
, uid
, arg
, cred
);
224 nullfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
229 NULLFSDEBUG("nullfs_statfs(mp = %p, vp = %p)\n", (void *)mp
,
230 (void *)MOUNTTONULLMOUNT(mp
)->nullm_rootvp
);
232 bzero(&mstat
, sizeof(mstat
));
234 error
= VFS_STATFS(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, &mstat
, cred
);
238 /* now copy across the "interesting" information and fake the rest */
239 sbp
->f_type
= mstat
.f_type
;
240 sbp
->f_flags
= mstat
.f_flags
;
241 sbp
->f_bsize
= mstat
.f_bsize
;
242 sbp
->f_iosize
= mstat
.f_iosize
;
243 sbp
->f_blocks
= mstat
.f_blocks
;
244 sbp
->f_bfree
= mstat
.f_bfree
;
245 sbp
->f_bavail
= mstat
.f_bavail
;
246 sbp
->f_files
= mstat
.f_files
;
247 sbp
->f_ffree
= mstat
.f_ffree
;
248 if (sbp
!= &mp
->mnt_stat
) {
249 bcopy(&mp
->mnt_stat
.f_fsid
, &sbp
->f_fsid
, sizeof(sbp
->f_fsid
));
250 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
256 nullfs_checkexp(struct mount
*mp
, struct sockaddr
*nam
, int *extflagsp
,
257 struct ucred
**credanonp
)
260 return VFS_CHECKEXP(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, nam
,
261 extflagsp
, credanonp
);
265 nullfs_extattrctl(struct mount
*mp
, int cmd
, const char *attrname
, caddr_t arg
,
268 return VFS_EXTATTRCTL(MOUNTTONULLMOUNT(mp
)->nullm_vfs
, cmd
, attrname
,
273 static struct vfsops null_vfsops
= {
274 .vfs_mount
= nullfs_mount
,
275 .vfs_unmount
= nullfs_unmount
,
276 .vfs_root
= nullfs_root
,
277 .vfs_quotactl
= nullfs_quotactl
,
278 .vfs_statfs
= nullfs_statfs
,
279 .vfs_sync
= vfs_stdsync
,
280 .vfs_checkexp
= nullfs_checkexp
,
281 .vfs_extattrctl
= nullfs_extattrctl
284 VFS_SET(null_vfsops
, null
, VFCF_LOOPBACK
);