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