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