null_vfsops.c revision 1.1 1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software donated to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
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.
23 *
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
34 * SUCH DAMAGE.
35 *
36 * from: Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp
37 * from: @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
38 * from: @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94
39 * $Id: null_vfsops.c,v 1.1 1994/06/08 11:33:25 mycroft Exp $
40 */
41
42 /*
43 * Null Layer
44 * (See null_vnops.c for a description of what this does.)
45 */
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/vnode.h>
52 #include <sys/mount.h>
53 #include <sys/namei.h>
54 #include <sys/malloc.h>
55 #include <miscfs/nullfs/null.h>
56
57 /*
58 * Mount null layer
59 */
60 int
61 nullfs_mount(mp, path, data, ndp, p)
62 struct mount *mp;
63 char *path;
64 caddr_t data;
65 struct nameidata *ndp;
66 struct proc *p;
67 {
68 int error = 0;
69 struct null_args args;
70 struct vnode *lowerrootvp, *vp;
71 struct vnode *nullm_rootvp;
72 struct null_mount *xmp;
73 u_int size;
74
75 #ifdef NULLFS_DIAGNOSTIC
76 printf("nullfs_mount(mp = %x)\n", mp);
77 #endif
78
79 /*
80 * Update is a no-op
81 */
82 if (mp->mnt_flag & MNT_UPDATE) {
83 return (EOPNOTSUPP);
84 /* return VFS_MOUNT(MOUNTTONULLMOUNT(mp)->nullm_vfs, path, data, ndp, p);*/
85 }
86
87 /*
88 * Get argument
89 */
90 if (error = copyin(data, (caddr_t)&args, sizeof(struct null_args)))
91 return (error);
92
93 /*
94 * Find lower node
95 */
96 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
97 UIO_USERSPACE, args.target, p);
98 if (error = namei(ndp))
99 return (error);
100
101 /*
102 * Sanity check on lower vnode
103 */
104 lowerrootvp = ndp->ni_vp;
105
106 vrele(ndp->ni_dvp);
107 ndp->ni_dvp = NULL;
108
109 xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
110 M_UFSMNT, M_WAITOK); /* XXX */
111
112 /*
113 * Save reference to underlying FS
114 */
115 xmp->nullm_vfs = lowerrootvp->v_mount;
116
117 /*
118 * Save reference. Each mount also holds
119 * a reference on the root vnode.
120 */
121 error = null_node_create(mp, lowerrootvp, &vp);
122 /*
123 * Unlock the node (either the lower or the alias)
124 */
125 VOP_UNLOCK(vp);
126 /*
127 * Make sure the node alias worked
128 */
129 if (error) {
130 vrele(lowerrootvp);
131 free(xmp, M_UFSMNT); /* XXX */
132 return (error);
133 }
134
135 /*
136 * Keep a held reference to the root vnode.
137 * It is vrele'd in nullfs_unmount.
138 */
139 nullm_rootvp = vp;
140 nullm_rootvp->v_flag |= VROOT;
141 xmp->nullm_rootvp = nullm_rootvp;
142 if (NULLVPTOLOWERVP(nullm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
143 mp->mnt_flag |= MNT_LOCAL;
144 mp->mnt_data = (qaddr_t) xmp;
145 getnewfsid(mp, makefstype(MOUNT_LOFS));
146
147 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
148 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
149 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
150 &size);
151 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
152 #ifdef NULLFS_DIAGNOSTIC
153 printf("nullfs_mount: lower %s, alias at %s\n",
154 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
155 #endif
156 return (0);
157 }
158
159 /*
160 * VFS start. Nothing needed here - the start routine
161 * on the underlying filesystem will have been called
162 * when that filesystem was mounted.
163 */
164 int
165 nullfs_start(mp, flags, p)
166 struct mount *mp;
167 int flags;
168 struct proc *p;
169 {
170
171 return (0);
172 /* return VFS_START(MOUNTTONULLMOUNT(mp)->nullm_vfs, flags, p); */
173 }
174
175 /*
176 * Free reference to null layer
177 */
178 int
179 nullfs_unmount(mp, mntflags, p)
180 struct mount *mp;
181 int mntflags;
182 struct proc *p;
183 {
184 struct vnode *nullm_rootvp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
185 int error;
186 int flags = 0;
187 extern int doforce;
188
189 #ifdef NULLFS_DIAGNOSTIC
190 printf("nullfs_unmount(mp = %x)\n", mp);
191 #endif
192
193 if (mntflags & MNT_FORCE) {
194 /* lofs can never be rootfs so don't check for it */
195 if (!doforce)
196 return (EINVAL);
197 flags |= FORCECLOSE;
198 }
199
200 /*
201 * Clear out buffer cache. I don't think we
202 * ever get anything cached at this level at the
203 * moment, but who knows...
204 */
205 #if 0
206 mntflushbuf(mp, 0);
207 if (mntinvalbuf(mp, 1))
208 return (EBUSY);
209 #endif
210 if (nullm_rootvp->v_usecount > 1)
211 return (EBUSY);
212 if (error = vflush(mp, nullm_rootvp, flags))
213 return (error);
214
215 #ifdef NULLFS_DIAGNOSTIC
216 vprint("alias root of lower", nullm_rootvp);
217 #endif
218 /*
219 * Release reference on underlying root vnode
220 */
221 vrele(nullm_rootvp);
222 /*
223 * And blow it away for future re-use
224 */
225 vgone(nullm_rootvp);
226 /*
227 * Finally, throw away the null_mount structure
228 */
229 free(mp->mnt_data, M_UFSMNT); /* XXX */
230 mp->mnt_data = 0;
231 return 0;
232 }
233
234 int
235 nullfs_root(mp, vpp)
236 struct mount *mp;
237 struct vnode **vpp;
238 {
239 struct vnode *vp;
240
241 #ifdef NULLFS_DIAGNOSTIC
242 printf("nullfs_root(mp = %x, vp = %x->%x)\n", mp,
243 MOUNTTONULLMOUNT(mp)->nullm_rootvp,
244 NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
245 );
246 #endif
247
248 /*
249 * Return locked reference to root.
250 */
251 vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp;
252 VREF(vp);
253 VOP_LOCK(vp);
254 *vpp = vp;
255 return 0;
256 }
257
258 int
259 nullfs_quotactl(mp, cmd, uid, arg, p)
260 struct mount *mp;
261 int cmd;
262 uid_t uid;
263 caddr_t arg;
264 struct proc *p;
265 {
266
267 return VFS_QUOTACTL(MOUNTTONULLMOUNT(mp)->nullm_vfs, cmd, uid, arg, p);
268 }
269
270 int
271 nullfs_statfs(mp, sbp, p)
272 struct mount *mp;
273 struct statfs *sbp;
274 struct proc *p;
275 {
276 int error;
277 struct statfs mstat;
278
279 #ifdef NULLFS_DIAGNOSTIC
280 printf("nullfs_statfs(mp = %x, vp = %x->%x)\n", mp,
281 MOUNTTONULLMOUNT(mp)->nullm_rootvp,
282 NULLVPTOLOWERVP(MOUNTTONULLMOUNT(mp)->nullm_rootvp)
283 );
284 #endif
285
286 bzero(&mstat, sizeof(mstat));
287
288 error = VFS_STATFS(MOUNTTONULLMOUNT(mp)->nullm_vfs, &mstat, p);
289 if (error)
290 return (error);
291
292 /* now copy across the "interesting" information and fake the rest */
293 sbp->f_type = mstat.f_type;
294 sbp->f_flags = mstat.f_flags;
295 sbp->f_bsize = mstat.f_bsize;
296 sbp->f_iosize = mstat.f_iosize;
297 sbp->f_blocks = mstat.f_blocks;
298 sbp->f_bfree = mstat.f_bfree;
299 sbp->f_bavail = mstat.f_bavail;
300 sbp->f_files = mstat.f_files;
301 sbp->f_ffree = mstat.f_ffree;
302 if (sbp != &mp->mnt_stat) {
303 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
304 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
305 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
306 }
307 strncpy(&sbp->f_fstypename[0], &mstat.f_fstypename[0], MFSNAMELEN);
308 sbp->f_fstypename[MFSNAMELEN] = '\0';
309 return (0);
310 }
311
312 int
313 nullfs_sync(mp, waitfor, cred, p)
314 struct mount *mp;
315 int waitfor;
316 struct ucred *cred;
317 struct proc *p;
318 {
319
320 /*
321 * XXX - Assumes no data cached at null layer.
322 */
323 return (0);
324 }
325
326 int
327 nullfs_vget(mp, ino, vpp)
328 struct mount *mp;
329 ino_t ino;
330 struct vnode **vpp;
331 {
332
333 return VFS_VGET(MOUNTTONULLMOUNT(mp)->nullm_vfs, ino, vpp);
334 }
335
336 int
337 nullfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
338 struct mount *mp;
339 struct fid *fidp;
340 struct mbuf *nam;
341 struct vnode **vpp;
342 int *exflagsp;
343 struct ucred**credanonp;
344 {
345
346 return VFS_FHTOVP(MOUNTTONULLMOUNT(mp)->nullm_vfs, fidp, nam, vpp, exflagsp,credanonp);
347 }
348
349 int
350 nullfs_vptofh(vp, fhp)
351 struct vnode *vp;
352 struct fid *fhp;
353 {
354
355 return VFS_VPTOFH(NULLVPTOLOWERVP(vp), fhp);
356 }
357
358 int nullfs_init __P((void));
359
360 struct vfsops null_vfsops = {
361 MOUNT_NULL,
362 nullfs_mount,
363 nullfs_start,
364 nullfs_unmount,
365 nullfs_root,
366 nullfs_quotactl,
367 nullfs_statfs,
368 nullfs_sync,
369 nullfs_vget,
370 nullfs_fhtovp,
371 nullfs_vptofh,
372 nullfs_init,
373 };
374