BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / miscfs / umapfs / umap_vfsops.c
CommitLineData
461c058b 1/*
ad787160
C
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
461c058b
JH
4 *
5 * This code is derived from software donated to Berkeley by
e0851395 6 * the UCLA Ficus project.
461c058b 7 *
ad787160
C
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.
461c058b 23 *
ad787160
C
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 *
ed554bc5 36 * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
461c058b 37 *
e0851395 38 * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
461c058b
JH
39 */
40
41/*
e0851395 42 * Umap Layer
ddcb8262 43 * (See mount_umap(8) for a description of this layer.)
461c058b
JH
44 */
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/time.h>
49#include <sys/types.h>
50#include <sys/vnode.h>
51#include <sys/mount.h>
52#include <sys/namei.h>
53#include <sys/malloc.h>
ddcb8262 54#include <miscfs/umapfs/umap.h>
461c058b
JH
55
56/*
57 * Mount umap layer
58 */
59int
60umapfs_mount(mp, path, data, ndp, p)
61 struct mount *mp;
62 char *path;
63 caddr_t data;
64 struct nameidata *ndp;
65 struct proc *p;
66{
461c058b
JH
67 struct umap_args args;
68 struct vnode *lowerrootvp, *vp;
69 struct vnode *umapm_rootvp;
70 struct umap_mount *amp;
71 u_int size;
33e96e24 72 int error;
461c058b
JH
73
74#ifdef UMAPFS_DIAGNOSTIC
75 printf("umapfs_mount(mp = %x)\n", mp);
76#endif
77
78 /*
79 * Update is a no-op
80 */
81 if (mp->mnt_flag & MNT_UPDATE) {
82 return (EOPNOTSUPP);
33e96e24 83 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
461c058b
JH
84 }
85
86 /*
87 * Get argument
88 */
89 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
90 return (error);
91
92 /*
e0851395 93 * Find lower node
461c058b
JH
94 */
95 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
96 UIO_USERSPACE, args.target, p);
97 if (error = namei(ndp))
98 return (error);
99
100 /*
e0851395 101 * Sanity check on lower vnode
461c058b
JH
102 */
103 lowerrootvp = ndp->ni_vp;
104#ifdef UMAPFS_DIAGNOSTIC
105 printf("vp = %x, check for VDIR...\n", lowerrootvp);
106#endif
107 vrele(ndp->ni_dvp);
108 ndp->ni_dvp = 0;
109
461c058b
JH
110 if (lowerrootvp->v_type != VDIR) {
111 vput(lowerrootvp);
112 return (EINVAL);
113 }
114
115#ifdef UMAPFS_DIAGNOSTIC
116 printf("mp = %x\n", mp);
117#endif
118
119 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
120 M_UFSMNT, M_WAITOK); /* XXX */
121
122 /*
e0851395 123 * Save reference to underlying FS
461c058b
JH
124 */
125 amp->umapm_vfs = lowerrootvp->v_mount;
126
127 /*
128 * Now copy in the number of entries and maps for umap mapping.
129 */
461c058b
JH
130 amp->info_nentries = args.nentries;
131 amp->info_gnentries = args.gnentries;
132 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
33e96e24
KB
133 2*sizeof(u_long)*args.nentries);
134 if (error)
135 return (error);
e0851395
JH
136
137#ifdef UMAP_DIAGNOSTIC
461c058b 138 printf("umap_mount:nentries %d\n",args.nentries);
e0851395 139 for (i = 0; i < args.nentries; i++)
461c058b
JH
140 printf(" %d maps to %d\n", amp->info_mapdata[i][0],
141 amp->info_mapdata[i][1]);
e0851395 142#endif
461c058b
JH
143
144 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
33e96e24
KB
145 2*sizeof(u_long)*args.nentries);
146 if (error)
147 return (error);
e0851395
JH
148
149#ifdef UMAP_DIAGNOSTIC
461c058b 150 printf("umap_mount:gnentries %d\n",args.gnentries);
e0851395 151 for (i = 0; i < args.gnentries; i++)
461c058b
JH
152 printf(" group %d maps to %d\n",
153 amp->info_gmapdata[i][0],
154 amp->info_gmapdata[i][1]);
e0851395 155#endif
461c058b
JH
156
157
158 /*
159 * Save reference. Each mount also holds
160 * a reference on the root vnode.
161 */
162 error = umap_node_create(mp, lowerrootvp, &vp);
163 /*
e0851395 164 * Unlock the node (either the lower or the alias)
461c058b
JH
165 */
166 VOP_UNLOCK(vp);
167 /*
168 * Make sure the node alias worked
169 */
170 if (error) {
171 vrele(lowerrootvp);
172 free(amp, M_UFSMNT); /* XXX */
173 return (error);
174 }
175
176 /*
177 * Keep a held reference to the root vnode.
178 * It is vrele'd in umapfs_unmount.
179 */
180 umapm_rootvp = vp;
181 umapm_rootvp->v_flag |= VROOT;
182 amp->umapm_rootvp = umapm_rootvp;
183 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
184 mp->mnt_flag |= MNT_LOCAL;
185 mp->mnt_data = (qaddr_t) amp;
186 getnewfsid(mp, MOUNT_LOFS);
187
188 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
189 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
190 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
191 &size);
192 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
193#ifdef UMAPFS_DIAGNOSTIC
e0851395 194 printf("umapfs_mount: lower %s, alias at %s\n",
461c058b
JH
195 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
196#endif
197 return (0);
198}
199
200/*
201 * VFS start. Nothing needed here - the start routine
202 * on the underlying filesystem will have been called
203 * when that filesystem was mounted.
204 */
205int
206umapfs_start(mp, flags, p)
207 struct mount *mp;
208 int flags;
209 struct proc *p;
210{
211 return (0);
33e96e24 212 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
461c058b
JH
213}
214
215/*
216 * Free reference to umap layer
217 */
218int
219umapfs_unmount(mp, mntflags, p)
220 struct mount *mp;
221 int mntflags;
222 struct proc *p;
223{
224 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
225 int error;
226 int flags = 0;
227 extern int doforce;
228
229#ifdef UMAPFS_DIAGNOSTIC
230 printf("umapfs_unmount(mp = %x)\n", mp);
231#endif
232
233 if (mntflags & MNT_FORCE) {
234 /* lofs can never be rootfs so don't check for it */
235 if (!doforce)
236 return (EINVAL);
237 flags |= FORCECLOSE;
238 }
239
240 /*
241 * Clear out buffer cache. I don't think we
242 * ever get anything cached at this level at the
243 * moment, but who knows...
244 */
fb250c6b 245#ifdef notyet
461c058b
JH
246 mntflushbuf(mp, 0);
247 if (mntinvalbuf(mp, 1))
248 return (EBUSY);
249#endif
250 if (umapm_rootvp->v_usecount > 1)
251 return (EBUSY);
252 if (error = vflush(mp, umapm_rootvp, flags))
253 return (error);
254
255#ifdef UMAPFS_DIAGNOSTIC
e0851395 256 vprint("alias root of lower", umapm_rootvp);
461c058b
JH
257#endif
258 /*
259 * Release reference on underlying root vnode
260 */
261 vrele(umapm_rootvp);
262 /*
263 * And blow it away for future re-use
264 */
265 vgone(umapm_rootvp);
266 /*
267 * Finally, throw away the umap_mount structure
268 */
269 free(mp->mnt_data, M_UFSMNT); /* XXX */
270 mp->mnt_data = 0;
33e96e24 271 return (0);
461c058b
JH
272}
273
274int
275umapfs_root(mp, vpp)
276 struct mount *mp;
277 struct vnode **vpp;
278{
279 struct vnode *vp;
280
281#ifdef UMAPFS_DIAGNOSTIC
282 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
283 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
284 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
285 );
286#endif
287
288 /*
289 * Return locked reference to root.
290 */
291 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
292 VREF(vp);
293 VOP_LOCK(vp);
294 *vpp = vp;
33e96e24 295 return (0);
461c058b
JH
296}
297
298int
299umapfs_quotactl(mp, cmd, uid, arg, p)
300 struct mount *mp;
301 int cmd;
302 uid_t uid;
303 caddr_t arg;
304 struct proc *p;
305{
33e96e24 306 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
461c058b
JH
307}
308
309int
310umapfs_statfs(mp, sbp, p)
311 struct mount *mp;
312 struct statfs *sbp;
313 struct proc *p;
314{
315 int error;
316 struct statfs mstat;
317
318#ifdef UMAPFS_DIAGNOSTIC
319 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
320 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
321 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
322 );
323#endif
324
325 bzero(&mstat, sizeof(mstat));
326
327 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
328 if (error)
329 return (error);
330
331 /* now copy across the "interesting" information and fake the rest */
332 sbp->f_type = mstat.f_type;
333 sbp->f_flags = mstat.f_flags;
334 sbp->f_bsize = mstat.f_bsize;
335 sbp->f_iosize = mstat.f_iosize;
336 sbp->f_blocks = mstat.f_blocks;
337 sbp->f_bfree = mstat.f_bfree;
338 sbp->f_bavail = mstat.f_bavail;
339 sbp->f_files = mstat.f_files;
340 sbp->f_ffree = mstat.f_ffree;
341 if (sbp != &mp->mnt_stat) {
342 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
343 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
344 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
345 }
346 return (0);
347}
348
349int
350umapfs_sync(mp, waitfor, cred, p)
351 struct mount *mp;
352 int waitfor;
353 struct ucred *cred;
354 struct proc *p;
355{
356 /*
357 * XXX - Assumes no data cached at umap layer.
358 */
359 return (0);
360}
361
362int
363umapfs_vget(mp, ino, vpp)
364 struct mount *mp;
365 ino_t ino;
366 struct vnode **vpp;
367{
368
33e96e24 369 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
461c058b
JH
370}
371
372int
373umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
374 struct mount *mp;
375 struct fid *fidp;
376 struct mbuf *nam;
377 struct vnode **vpp;
378 int *exflagsp;
379 struct ucred**credanonp;
380{
381
33e96e24 382 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
461c058b
JH
383}
384
385int
386umapfs_vptofh(vp, fhp)
387 struct vnode *vp;
388 struct fid *fhp;
389{
33e96e24 390 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
461c058b
JH
391}
392
393int umapfs_init __P((void));
394
395struct vfsops umap_vfsops = {
396 umapfs_mount,
397 umapfs_start,
398 umapfs_unmount,
399 umapfs_root,
400 umapfs_quotactl,
401 umapfs_statfs,
402 umapfs_sync,
403 umapfs_vget,
404 umapfs_fhtovp,
405 umapfs_vptofh,
406 umapfs_init,
407};