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