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