null_vfsops.c revision 2946
1227825Stheraven/*
2227825Stheraven * Copyright (c) 1992, 1993
3227825Stheraven *	The Regents of the University of California.  All rights reserved.
4227825Stheraven *
5227825Stheraven * This code is derived from software donated to Berkeley by
6227825Stheraven * Jan-Simon Pendry.
7227825Stheraven *
8227825Stheraven * Redistribution and use in source and binary forms, with or without
9227825Stheraven * modification, are permitted provided that the following conditions
10227825Stheraven * are met:
11227825Stheraven * 1. Redistributions of source code must retain the above copyright
12227825Stheraven *    notice, this list of conditions and the following disclaimer.
13227825Stheraven * 2. Redistributions in binary form must reproduce the above copyright
14227825Stheraven *    notice, this list of conditions and the following disclaimer in the
15227825Stheraven *    documentation and/or other materials provided with the distribution.
16227825Stheraven * 3. All advertising materials mentioning features or use of this software
17227825Stheraven *    must display the following acknowledgement:
18227825Stheraven *	This product includes software developed by the University of
19227825Stheraven *	California, Berkeley and its contributors.
20227825Stheraven * 4. Neither the name of the University nor the names of its contributors
21227825Stheraven *    may be used to endorse or promote products derived from this software
22227825Stheraven *    without specific prior written permission.
23227825Stheraven *
24234976Stheraven * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25234976Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26234976Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27234976Stheraven * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28227825Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29234976Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30234976Stheraven * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31234976Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32234976Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33234976Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34234976Stheraven * SUCH DAMAGE.
35234976Stheraven *
36234976Stheraven *	@(#)null_vfsops.c	8.2 (Berkeley) 1/21/94
37234976Stheraven *
38227825Stheraven * @(#)lofs_vfsops.c	1.2 (Berkeley) 6/18/92
39234976Stheraven * $Id: null_vfsops.c,v 1.1.1.1 1994/05/24 10:05:03 rgrimes Exp $
40234976Stheraven */
41234976Stheraven
42234976Stheraven/*
43227825Stheraven * Null Layer
44234976Stheraven * (See null_vnops.c for a description of what this does.)
45234976Stheraven */
46234976Stheraven
47234976Stheraven#include <sys/param.h>
48234976Stheraven#include <sys/systm.h>
49234976Stheraven#include <sys/time.h>
50234976Stheraven#include <sys/types.h>
51234976Stheraven#include <sys/vnode.h>
52234976Stheraven#include <sys/mount.h>
53227825Stheraven#include <sys/namei.h>
54234976Stheraven#include <sys/malloc.h>
55234976Stheraven#include <miscfs/nullfs/null.h>
56234976Stheraven
57227825Stheraven/*
58234976Stheraven * Mount null layer
59234976Stheraven */
60234976Stheravenint
61227825Stheravennullfs_mount(mp, path, data, ndp, p)
62227825Stheraven	struct mount *mp;
63227825Stheraven	char *path;
64227825Stheraven	caddr_t data;
65227825Stheraven	struct nameidata *ndp;
66227825Stheraven	struct proc *p;
67227825Stheraven{
68227825Stheraven	int error = 0;
69227825Stheraven	struct null_args args;
70227825Stheraven	struct vnode *lowerrootvp, *vp;
71227825Stheraven	struct vnode *nullm_rootvp;
72227825Stheraven	struct null_mount *xmp;
73227825Stheraven	u_int size;
74227825Stheraven
75227825Stheraven#ifdef NULLFS_DIAGNOSTIC
76227825Stheraven	printf("nullfs_mount(mp = %x)\n", mp);
77227825Stheraven#endif
78227825Stheraven
79227825Stheraven	/*
80227825Stheraven	 * Update is a no-op
81227825Stheraven	 */
82227825Stheraven	if (mp->mnt_flag & MNT_UPDATE) {
83227825Stheraven		return (EOPNOTSUPP);
84227825Stheraven		/* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/
85227825Stheraven	}
86227825Stheraven
87227825Stheraven	/*
88227825Stheraven	 * Get argument
89227825Stheraven	 */
90227825Stheraven	if (error = copyin(data, (caddr_t)&args, sizeof(struct null_args)))
91227825Stheraven		return (error);
92227825Stheraven
93227825Stheraven	/*
94227825Stheraven	 * Find lower node
95227825Stheraven	 */
96227825Stheraven	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
97227825Stheraven		UIO_USERSPACE, args.target, p);
98227825Stheraven	if (error = namei(ndp))
99227825Stheraven		return (error);
100227825Stheraven
101227825Stheraven	/*
102227825Stheraven	 * Sanity check on lower vnode
103227825Stheraven	 */
104227825Stheraven	lowerrootvp = ndp->ni_vp;
105227825Stheraven
106227825Stheraven	vrele(ndp->ni_dvp);
107227825Stheraven	ndp->ni_dvp = NULL;
108227825Stheraven
109227825Stheraven	xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
110227825Stheraven				M_UFSMNT, M_WAITOK);	/* XXX */
111227825Stheraven
112232950Stheraven	/*
113232950Stheraven	 * Save reference to underlying FS
114262801Sdim	 */
115227825Stheraven	xmp->nullm_vfs = lowerrootvp->v_mount;
116262801Sdim
117227825Stheraven	/*
118262801Sdim	 * Save reference.  Each mount also holds
119262801Sdim	 * a reference on the root vnode.
120262801Sdim	 */
121262801Sdim	error = null_node_create(mp, lowerrootvp, &vp);
122227825Stheraven	/*
123227825Stheraven	 * Unlock the node (either the lower or the alias)
124227825Stheraven	 */
125227825Stheraven	VOP_UNLOCK(vp);
126227825Stheraven	/*
127227825Stheraven	 * Make sure the node alias worked
128227825Stheraven	 */
129227825Stheraven	if (error) {
130227825Stheraven		vrele(lowerrootvp);
131227825Stheraven		free(xmp, M_UFSMNT);	/* XXX */
132227825Stheraven		return (error);
133227825Stheraven	}
134227825Stheraven
135227825Stheraven	/*
136227825Stheraven	 * Keep a held reference to the root vnode.
137227825Stheraven	 * It is vrele'd in nullfs_unmount.
138227825Stheraven	 */
139227825Stheraven	nullm_rootvp = vp;
140227825Stheraven	nullm_rootvp->v_flag |= VROOT;
141227825Stheraven	xmp->nullm_rootvp = nullm_rootvp;
142227825Stheraven	if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
143227825Stheraven		mp->mnt_flag |= MNT_LOCAL;
144227825Stheraven	mp->mnt_data = (qaddr_t) xmp;
145227825Stheraven	getnewfsid(mp, MOUNT_LOFS);
146234976Stheraven
147234976Stheraven	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
148234976Stheraven	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
149234976Stheraven	(void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
150227825Stheraven	    &size);
151234976Stheraven	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
152234976Stheraven#ifdef NULLFS_DIAGNOSTIC
153234976Stheraven	printf("nullfs_mount: lower %s, alias at %s\n",
154234976Stheraven		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
155234976Stheraven#endif
156234976Stheraven	return (0);
157234976Stheraven}
158234976Stheraven
159234976Stheraven/*
160227825Stheraven * VFS start.  Nothing needed here - the start routine
161234976Stheraven * on the underlying filesystem will have been called
162234976Stheraven * when that filesystem was mounted.
163234976Stheraven */
164234976Stheravenint
165227825Stheravennullfs_start(mp, flags, p)
166234976Stheraven	struct mount *mp;
167234976Stheraven	int flags;
168234976Stheraven	struct proc *p;
169234976Stheraven{
170234976Stheraven	return (0);
171234976Stheraven	/* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, p); */
172234976Stheraven}
173234976Stheraven
174234976Stheraven/*
175227825Stheraven * Free reference to null layer
176234976Stheraven */
177234976Stheravenint
178234976Stheravennullfs_unmount(mp, mntflags, p)
179227825Stheraven	struct mount *mp;
180234976Stheraven	int mntflags;
181234976Stheraven	struct proc *p;
182234976Stheraven{
183227825Stheraven	struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
184227825Stheraven	int error;
185227825Stheraven	int flags = 0;
186227825Stheraven	extern int doforce;
187227825Stheraven
188234976Stheraven#ifdef NULLFS_DIAGNOSTIC
189227825Stheraven	printf("nullfs_unmount(mp = %x)\n", mp);
190227825Stheraven#endif
191227825Stheraven
192227825Stheraven	if (mntflags & MNT_FORCE) {
193227825Stheraven		/* lofs can never be rootfs so don't check for it */
194234976Stheraven		if (!doforce)
195227825Stheraven			return (EINVAL);
196227825Stheraven		flags |= FORCECLOSE;
197227825Stheraven	}
198227825Stheraven
199227825Stheraven	/*
200227825Stheraven	 * Clear out buffer cache.  I don't think we
201227825Stheraven	 * ever get anything cached at this level at the
202227825Stheraven	 * moment, but who knows...
203234976Stheraven	 */
204227825Stheraven#if 0
205234976Stheraven	mntflushbuf(mp, 0);
206234976Stheraven	if (mntinvalbuf(mp, 1))
207234976Stheraven		return (EBUSY);
208234976Stheraven#endif
209234976Stheraven	if (nullm_rootvp->v_usecount > 1)
210234976Stheraven		return (EBUSY);
211234976Stheraven	if (error = vflush(mp, nullm_rootvp, flags))
212234976Stheraven		return (error);
213234976Stheraven
214227825Stheraven#ifdef NULLFS_DIAGNOSTIC
215234976Stheraven	vprint("alias root of lower", nullm_rootvp);
216234976Stheraven#endif
217234976Stheraven	/*
218234976Stheraven	 * Release reference on underlying root vnode
219234976Stheraven	 */
220227825Stheraven	vrele(nullm_rootvp);
221234976Stheraven	/*
222234976Stheraven	 * And blow it away for future re-use
223234976Stheraven	 */
224234976Stheraven	vgone(nullm_rootvp);
225227825Stheraven	/*
226234976Stheraven	 * Finally, throw away the null_mount structure
227234976Stheraven	 */
228234976Stheraven	free(mp->mnt_data, M_UFSMNT);	/* XXX */
229234976Stheraven	mp->mnt_data = 0;
230234976Stheraven	return 0;
231234976Stheraven}
232234976Stheraven
233234976Stheravenint
234234976Stheravennullfs_root(mp, vpp)
235227825Stheraven	struct mount *mp;
236234976Stheraven	struct vnode **vpp;
237234976Stheraven{
238278724Sdim	struct vnode *vp;
239227825Stheraven
240278724Sdim#ifdef NULLFS_DIAGNOSTIC
241234976Stheraven	printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp,
242227825Stheraven			MOUNTTONULLMOUNT(mp)->nullm_rootvp,
243234976Stheraven			NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
244227825Stheraven			);
245234976Stheraven#endif
246234976Stheraven
247227825Stheraven	/*
248227825Stheraven	 * Return locked reference to root.
249227825Stheraven	 */
250227825Stheraven	vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
251227825Stheraven	VREF(vp);
252227825Stheraven	VOP_LOCK(vp);
253227825Stheraven	*vpp = vp;
254227825Stheraven	return 0;
255234976Stheraven}
256227825Stheraven
257234976Stheravenint
258234976Stheravennullfs_quotactl(mp, cmd, uid, arg, p)
259234976Stheraven	struct mount *mp;
260234976Stheraven	int cmd;
261234976Stheraven	uid_t uid;
262234976Stheraven	caddr_t arg;
263234976Stheraven	struct proc *p;
264234976Stheraven{
265234976Stheraven	return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg, p);
266227825Stheraven}
267234976Stheraven
268234976Stheravenint
269234976Stheravennullfs_statfs(mp, sbp, p)
270234976Stheraven	struct mount *mp;
271234976Stheraven	struct statfs *sbp;
272227825Stheraven	struct proc *p;
273234976Stheraven{
274234976Stheraven	int error;
275234976Stheraven	struct statfs mstat;
276234976Stheraven
277227825Stheraven#ifdef NULLFS_DIAGNOSTIC
278234976Stheraven	printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp,
279234976Stheraven			MOUNTTONULLMOUNT(mp)->nullm_rootvp,
280234976Stheraven			NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
281234976Stheraven			);
282234976Stheraven#endif
283234976Stheraven
284234976Stheraven	bzero(&mstat, sizeof(mstat));
285234976Stheraven
286234976Stheraven	error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, p);
287227825Stheraven	if (error)
288234976Stheraven		return (error);
289234976Stheraven
290234976Stheraven	/* now copy across the "interesting" information and fake the rest */
291227825Stheraven	sbp->f_type = mstat.f_type;
292234976Stheraven	sbp->f_flags = mstat.f_flags;
293234976Stheraven	sbp->f_bsize = mstat.f_bsize;
294234976Stheraven	sbp->f_iosize = mstat.f_iosize;
295227825Stheraven	sbp->f_blocks = mstat.f_blocks;
296227825Stheraven	sbp->f_bfree = mstat.f_bfree;
297227825Stheraven	sbp->f_bavail = mstat.f_bavail;
298227825Stheraven	sbp->f_files = mstat.f_files;
299227825Stheraven	sbp->f_ffree = mstat.f_ffree;
300227825Stheraven	if (sbp != &mp->mnt_stat) {
301227825Stheraven		bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
302227825Stheraven		bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
303234976Stheraven		bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
304227825Stheraven	}
305234976Stheraven	return (0);
306234976Stheraven}
307234976Stheraven
308234976Stheravenint
309234976Stheravennullfs_sync(mp, waitfor, cred, p)
310234976Stheraven	struct mount *mp;
311234976Stheraven	int waitfor;
312227825Stheraven	struct ucred *cred;
313234976Stheraven	struct proc *p;
314234976Stheraven{
315234976Stheraven	/*
316234976Stheraven	 * XXX - Assumes no data cached at null layer.
317234976Stheraven	 */
318227825Stheraven	return (0);
319234976Stheraven}
320234976Stheraven
321234976Stheravenint
322234976Stheravennullfs_vget(mp, ino, vpp)
323227825Stheraven	struct mount *mp;
324234976Stheraven	ino_t ino;
325234976Stheraven	struct vnode **vpp;
326234976Stheraven{
327234976Stheraven
328234976Stheraven	return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp);
329234976Stheraven}
330234976Stheraven
331234976Stheravenint
332234976Stheravennullfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
333227825Stheraven	struct mount *mp;
334234976Stheraven	struct fid *fidp;
335234976Stheraven	struct mbuf *nam;
336234976Stheraven	struct vnode **vpp;
337227825Stheraven	int *exflagsp;
338234976Stheraven	struct ucred**credanonp;
339234976Stheraven{
340234976Stheraven
341227825Stheraven	return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, nam, vpp, exflagsp,credanonp);
342227825Stheraven}
343227825Stheraven
344227825Stheravenint
345227825Stheravennullfs_vptofh(vp, fhp)
346227825Stheraven	struct vnode *vp;
347227825Stheraven	struct fid *fhp;
348227825Stheraven{
349234976Stheraven	return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp);
350227825Stheraven}
351234976Stheraven
352234976Stheravenint nullfs_init __P((void));
353234976Stheraven
354234976Stheravenstruct vfsops null_vfsops = {
355234976Stheraven	nullfs_mount,
356234976Stheraven	nullfs_start,
357234976Stheraven	nullfs_unmount,
358227825Stheraven	nullfs_root,
359234976Stheraven	nullfs_quotactl,
360234976Stheraven	nullfs_statfs,
361234976Stheraven	nullfs_sync,
362234976Stheraven	nullfs_vget,
363234976Stheraven	nullfs_fhtovp,
364227825Stheraven	nullfs_vptofh,
365234976Stheraven	nullfs_init,
366234976Stheraven};
367234976Stheraven
368234976StheravenVFS_SET(null_vfsops, null, MOUNT_NULL, 0);
369227825Stheraven