umap_vfsops.c revision 1.16 1 /* $NetBSD: umap_vfsops.c,v 1.16 1997/10/06 09:32:37 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 * 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 *, const char *, void *,
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 const char *path;
78 void *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 = %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(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 = %p, 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 = %p\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.gnentries);
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("\tgroup %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_UMAP));
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 = %p)\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 = %p, vp = %p->%p)\n", mp,
300 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
301 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
302 #endif
303
304 /*
305 * Return locked reference to root.
306 */
307 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
308 VREF(vp);
309 VOP_LOCK(vp);
310 *vpp = vp;
311 return (0);
312 }
313
314 int
315 umapfs_quotactl(mp, cmd, uid, arg, p)
316 struct mount *mp;
317 int cmd;
318 uid_t uid;
319 caddr_t arg;
320 struct proc *p;
321 {
322
323 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
324 }
325
326 int
327 umapfs_statfs(mp, sbp, p)
328 struct mount *mp;
329 struct statfs *sbp;
330 struct proc *p;
331 {
332 int error;
333 struct statfs mstat;
334
335 #ifdef UMAPFS_DIAGNOSTIC
336 printf("umapfs_statfs(mp = %p, vp = %p->%p)\n", mp,
337 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
338 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
339 #endif
340
341 bzero(&mstat, sizeof(mstat));
342
343 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
344 if (error)
345 return (error);
346
347 /* now copy across the "interesting" information and fake the rest */
348 sbp->f_type = mstat.f_type;
349 sbp->f_flags = mstat.f_flags;
350 sbp->f_bsize = mstat.f_bsize;
351 sbp->f_iosize = mstat.f_iosize;
352 sbp->f_blocks = mstat.f_blocks;
353 sbp->f_bfree = mstat.f_bfree;
354 sbp->f_bavail = mstat.f_bavail;
355 sbp->f_files = mstat.f_files;
356 sbp->f_ffree = mstat.f_ffree;
357 if (sbp != &mp->mnt_stat) {
358 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
359 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
360 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
361 }
362 strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
363 return (0);
364 }
365
366 int
367 umapfs_sync(mp, waitfor, cred, p)
368 struct mount *mp;
369 int waitfor;
370 struct ucred *cred;
371 struct proc *p;
372 {
373
374 /*
375 * XXX - Assumes no data cached at umap layer.
376 */
377 return (0);
378 }
379
380 int
381 umapfs_vget(mp, ino, vpp)
382 struct mount *mp;
383 ino_t ino;
384 struct vnode **vpp;
385 {
386
387 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
388 }
389
390 int
391 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
392 struct mount *mp;
393 struct fid *fidp;
394 struct mbuf *nam;
395 struct vnode **vpp;
396 int *exflagsp;
397 struct ucred**credanonp;
398 {
399
400 return (EOPNOTSUPP);
401 }
402
403 int
404 umapfs_vptofh(vp, fhp)
405 struct vnode *vp;
406 struct fid *fhp;
407 {
408
409 return (EOPNOTSUPP);
410 }
411
412 struct vfsops umapfs_vfsops = {
413 MOUNT_UMAP,
414 umapfs_mount,
415 umapfs_start,
416 umapfs_unmount,
417 umapfs_root,
418 umapfs_quotactl,
419 umapfs_statfs,
420 umapfs_sync,
421 umapfs_vget,
422 umapfs_fhtovp,
423 umapfs_vptofh,
424 umapfs_init,
425 };
426