umap_vfsops.c revision 1.1.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 * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94
37 *
38 * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
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, 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 return (0);
212 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
213 }
214
215 /*
216 * Free reference to umap layer
217 */
218 int
219 umapfs_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 */
245 #ifdef notyet
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
256 vprint("alias root of lower", umapm_rootvp);
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;
271 return (0);
272 }
273
274 int
275 umapfs_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;
295 return (0);
296 }
297
298 int
299 umapfs_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 {
306 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
307 }
308
309 int
310 umapfs_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
349 int
350 umapfs_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
362 int
363 umapfs_vget(mp, ino, vpp)
364 struct mount *mp;
365 ino_t ino;
366 struct vnode **vpp;
367 {
368
369 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
370 }
371
372 int
373 umapfs_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
382 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
383 }
384
385 int
386 umapfs_vptofh(vp, fhp)
387 struct vnode *vp;
388 struct fid *fhp;
389 {
390 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
391 }
392
393 int umapfs_init __P((void));
394
395 struct 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 };
408