umap_vfsops.c revision 1.1 1 /*
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software donated to Berkeley by
6 * the UCLA Ficus project.
7 *
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.
23 *
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 *
36 * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
37 * from: @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
38 * $Id: umap_vfsops.c,v 1.1 1994/06/08 11:33:53 mycroft Exp $
39 */
40
41 /*
42 * Umap Layer
43 * (See mount_umap(8) for a description of this layer.)
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>
54 #include <miscfs/umapfs/umap.h>
55
56 /*
57 * Mount umap layer
58 */
59 int
60 umapfs_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 {
67 struct umap_args args;
68 struct vnode *lowerrootvp, *vp;
69 struct vnode *umapm_rootvp;
70 struct umap_mount *amp;
71 u_int size;
72 int error;
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);
83 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
84 }
85
86 /*
87 * Get argument
88 */
89 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
90 return (error);
91
92 /*
93 * Find lower node
94 */
95 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
96 UIO_USERSPACE, args.target, p);
97 if (error = namei(ndp))
98 return (error);
99
100 /*
101 * Sanity check on lower vnode
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
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 /*
123 * Save reference to underlying FS
124 */
125 amp->umapm_vfs = lowerrootvp->v_mount;
126
127 /*
128 * Now copy in the number of entries and maps for umap mapping.
129 */
130 amp->info_nentries = args.nentries;
131 amp->info_gnentries = args.gnentries;
132 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
133 2*sizeof(u_long)*args.nentries);
134 if (error)
135 return (error);
136
137 #ifdef UMAP_DIAGNOSTIC
138 printf("umap_mount:nentries %d\n",args.nentries);
139 for (i = 0; i < args.nentries; i++)
140 printf(" %d maps to %d\n", amp->info_mapdata[i][0],
141 amp->info_mapdata[i][1]);
142 #endif
143
144 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
145 2*sizeof(u_long)*args.nentries);
146 if (error)
147 return (error);
148
149 #ifdef UMAP_DIAGNOSTIC
150 printf("umap_mount:gnentries %d\n",args.gnentries);
151 for (i = 0; i < args.gnentries; i++)
152 printf(" group %d maps to %d\n",
153 amp->info_gmapdata[i][0],
154 amp->info_gmapdata[i][1]);
155 #endif
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 /*
164 * Unlock the node (either the lower or the alias)
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, makefstype(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
194 printf("umapfs_mount: lower %s, alias at %s\n",
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 */
205 int
206 umapfs_start(mp, flags, p)
207 struct mount *mp;
208 int flags;
209 struct proc *p;
210 {
211
212 return (0);
213 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
214 }
215
216 /*
217 * Free reference to umap layer
218 */
219 int
220 umapfs_unmount(mp, mntflags, p)
221 struct mount *mp;
222 int mntflags;
223 struct proc *p;
224 {
225 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
226 int error;
227 int flags = 0;
228 extern int doforce;
229
230 #ifdef UMAPFS_DIAGNOSTIC
231 printf("umapfs_unmount(mp = %x)\n", mp);
232 #endif
233
234 if (mntflags & MNT_FORCE) {
235 /* lofs can never be rootfs so don't check for it */
236 if (!doforce)
237 return (EINVAL);
238 flags |= FORCECLOSE;
239 }
240
241 /*
242 * Clear out buffer cache. I don't think we
243 * ever get anything cached at this level at the
244 * moment, but who knows...
245 */
246 #ifdef notyet
247 mntflushbuf(mp, 0);
248 if (mntinvalbuf(mp, 1))
249 return (EBUSY);
250 #endif
251 if (umapm_rootvp->v_usecount > 1)
252 return (EBUSY);
253 if (error = vflush(mp, umapm_rootvp, flags))
254 return (error);
255
256 #ifdef UMAPFS_DIAGNOSTIC
257 vprint("alias root of lower", umapm_rootvp);
258 #endif
259 /*
260 * Release reference on underlying root vnode
261 */
262 vrele(umapm_rootvp);
263 /*
264 * And blow it away for future re-use
265 */
266 vgone(umapm_rootvp);
267 /*
268 * Finally, throw away the umap_mount structure
269 */
270 free(mp->mnt_data, M_UFSMNT); /* XXX */
271 mp->mnt_data = 0;
272 return (0);
273 }
274
275 int
276 umapfs_root(mp, vpp)
277 struct mount *mp;
278 struct vnode **vpp;
279 {
280 struct vnode *vp;
281
282 #ifdef UMAPFS_DIAGNOSTIC
283 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
284 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
285 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
286 );
287 #endif
288
289 /*
290 * Return locked reference to root.
291 */
292 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
293 VREF(vp);
294 VOP_LOCK(vp);
295 *vpp = vp;
296 return (0);
297 }
298
299 int
300 umapfs_quotactl(mp, cmd, uid, arg, p)
301 struct mount *mp;
302 int cmd;
303 uid_t uid;
304 caddr_t arg;
305 struct proc *p;
306 {
307
308 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
309 }
310
311 int
312 umapfs_statfs(mp, sbp, p)
313 struct mount *mp;
314 struct statfs *sbp;
315 struct proc *p;
316 {
317 int error;
318 struct statfs mstat;
319
320 #ifdef UMAPFS_DIAGNOSTIC
321 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
322 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
323 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
324 );
325 #endif
326
327 bzero(&mstat, sizeof(mstat));
328
329 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
330 if (error)
331 return (error);
332
333 /* now copy across the "interesting" information and fake the rest */
334 sbp->f_type = mstat.f_type;
335 sbp->f_flags = mstat.f_flags;
336 sbp->f_bsize = mstat.f_bsize;
337 sbp->f_iosize = mstat.f_iosize;
338 sbp->f_blocks = mstat.f_blocks;
339 sbp->f_bfree = mstat.f_bfree;
340 sbp->f_bavail = mstat.f_bavail;
341 sbp->f_files = mstat.f_files;
342 sbp->f_ffree = mstat.f_ffree;
343 if (sbp != &mp->mnt_stat) {
344 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
345 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
346 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
347 }
348 strncpy(&sbp->f_fstypename[0], &mstat.f_fstypename[0], MFSNAMELEN);
349 sbp->f_fstypename[MFSNAMELEN] = '\0';
350 return (0);
351 }
352
353 int
354 umapfs_sync(mp, waitfor, cred, p)
355 struct mount *mp;
356 int waitfor;
357 struct ucred *cred;
358 struct proc *p;
359 {
360
361 /*
362 * XXX - Assumes no data cached at umap layer.
363 */
364 return (0);
365 }
366
367 int
368 umapfs_vget(mp, ino, vpp)
369 struct mount *mp;
370 ino_t ino;
371 struct vnode **vpp;
372 {
373
374 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
375 }
376
377 int
378 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
379 struct mount *mp;
380 struct fid *fidp;
381 struct mbuf *nam;
382 struct vnode **vpp;
383 int *exflagsp;
384 struct ucred**credanonp;
385 {
386
387 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
388 }
389
390 int
391 umapfs_vptofh(vp, fhp)
392 struct vnode *vp;
393 struct fid *fhp;
394 {
395
396 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
397 }
398
399 int umapfs_init __P((void));
400
401 struct vfsops umap_vfsops = {
402 MOUNT_UMAP,
403 umapfs_mount,
404 umapfs_start,
405 umapfs_unmount,
406 umapfs_root,
407 umapfs_quotactl,
408 umapfs_statfs,
409 umapfs_sync,
410 umapfs_vget,
411 umapfs_fhtovp,
412 umapfs_vptofh,
413 umapfs_init,
414 };
415