1 /*
2 * Copyright (c) 1992, 1993, 1995
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 * %sccs.include.redist.c%
9 *
10 * @(#)umap_vfsops.c 8.8 (Berkeley) 05/14/95
11 *
12 * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
13 */
14
15 /*
16 * Umap Layer
17 * (See mount_umap(8) for a description of this layer.)
18 */
19
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/proc.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #include <sys/vnode.h>
26 #include <sys/mount.h>
27 #include <sys/namei.h>
28 #include <sys/malloc.h>
29 #include <miscfs/umapfs/umap.h>
30
31 /*
32 * Mount umap layer
33 */
34 int
umapfs_mount(mp,path,data,ndp,p)35 umapfs_mount(mp, path, data, ndp, p)
36 struct mount *mp;
37 char *path;
38 caddr_t data;
39 struct nameidata *ndp;
40 struct proc *p;
41 {
42 struct umap_args args;
43 struct vnode *lowerrootvp, *vp;
44 struct vnode *umapm_rootvp;
45 struct umap_mount *amp;
46 u_int size;
47 int error;
48
49 #ifdef UMAPFS_DIAGNOSTIC
50 printf("umapfs_mount(mp = %x)\n", mp);
51 #endif
52
53 /*
54 * Update is a no-op
55 */
56 if (mp->mnt_flag & MNT_UPDATE) {
57 return (EOPNOTSUPP);
58 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
59 }
60
61 /*
62 * Get argument
63 */
64 if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)))
65 return (error);
66
67 /*
68 * Find lower node
69 */
70 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
71 UIO_USERSPACE, args.target, p);
72 if (error = namei(ndp))
73 return (error);
74
75 /*
76 * Sanity check on lower vnode
77 */
78 lowerrootvp = ndp->ni_vp;
79 #ifdef UMAPFS_DIAGNOSTIC
80 printf("vp = %x, check for VDIR...\n", lowerrootvp);
81 #endif
82 vrele(ndp->ni_dvp);
83 ndp->ni_dvp = 0;
84
85 if (lowerrootvp->v_type != VDIR) {
86 vput(lowerrootvp);
87 return (EINVAL);
88 }
89
90 #ifdef UMAPFS_DIAGNOSTIC
91 printf("mp = %x\n", mp);
92 #endif
93
94 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
95 M_UFSMNT, M_WAITOK); /* XXX */
96
97 /*
98 * Save reference to underlying FS
99 */
100 amp->umapm_vfs = lowerrootvp->v_mount;
101
102 /*
103 * Now copy in the number of entries and maps for umap mapping.
104 */
105 amp->info_nentries = args.nentries;
106 amp->info_gnentries = args.gnentries;
107 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
108 2*sizeof(u_long)*args.nentries);
109 if (error)
110 return (error);
111
112 #ifdef UMAP_DIAGNOSTIC
113 printf("umap_mount:nentries %d\n",args.nentries);
114 for (i = 0; i < args.nentries; i++)
115 printf(" %d maps to %d\n", amp->info_mapdata[i][0],
116 amp->info_mapdata[i][1]);
117 #endif
118
119 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
120 2*sizeof(u_long)*args.nentries);
121 if (error)
122 return (error);
123
124 #ifdef UMAP_DIAGNOSTIC
125 printf("umap_mount:gnentries %d\n",args.gnentries);
126 for (i = 0; i < args.gnentries; i++)
127 printf(" group %d maps to %d\n",
128 amp->info_gmapdata[i][0],
129 amp->info_gmapdata[i][1]);
130 #endif
131
132
133 /*
134 * Save reference. Each mount also holds
135 * a reference on the root vnode.
136 */
137 error = umap_node_create(mp, lowerrootvp, &vp);
138 /*
139 * Unlock the node (either the lower or the alias)
140 */
141 VOP_UNLOCK(vp, 0, p);
142 /*
143 * Make sure the node alias worked
144 */
145 if (error) {
146 vrele(lowerrootvp);
147 free(amp, M_UFSMNT); /* XXX */
148 return (error);
149 }
150
151 /*
152 * Keep a held reference to the root vnode.
153 * It is vrele'd in umapfs_unmount.
154 */
155 umapm_rootvp = vp;
156 umapm_rootvp->v_flag |= VROOT;
157 amp->umapm_rootvp = umapm_rootvp;
158 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
159 mp->mnt_flag |= MNT_LOCAL;
160 mp->mnt_data = (qaddr_t) amp;
161 vfs_getnewfsid(mp);
162
163 (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
164 bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
165 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
166 &size);
167 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
168 #ifdef UMAPFS_DIAGNOSTIC
169 printf("umapfs_mount: lower %s, alias at %s\n",
170 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
171 #endif
172 return (0);
173 }
174
175 /*
176 * VFS start. Nothing needed here - the start routine
177 * on the underlying filesystem will have been called
178 * when that filesystem was mounted.
179 */
180 int
umapfs_start(mp,flags,p)181 umapfs_start(mp, flags, p)
182 struct mount *mp;
183 int flags;
184 struct proc *p;
185 {
186 return (0);
187 /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
188 }
189
190 /*
191 * Free reference to umap layer
192 */
193 int
umapfs_unmount(mp,mntflags,p)194 umapfs_unmount(mp, mntflags, p)
195 struct mount *mp;
196 int mntflags;
197 struct proc *p;
198 {
199 struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
200 int error;
201 int flags = 0;
202
203 #ifdef UMAPFS_DIAGNOSTIC
204 printf("umapfs_unmount(mp = %x)\n", mp);
205 #endif
206
207 if (mntflags & MNT_FORCE)
208 flags |= FORCECLOSE;
209
210 /*
211 * Clear out buffer cache. I don't think we
212 * ever get anything cached at this level at the
213 * moment, but who knows...
214 */
215 #ifdef notyet
216 mntflushbuf(mp, 0);
217 if (mntinvalbuf(mp, 1))
218 return (EBUSY);
219 #endif
220 if (umapm_rootvp->v_usecount > 1)
221 return (EBUSY);
222 if (error = vflush(mp, umapm_rootvp, flags))
223 return (error);
224
225 #ifdef UMAPFS_DIAGNOSTIC
226 vprint("alias root of lower", umapm_rootvp);
227 #endif
228 /*
229 * Release reference on underlying root vnode
230 */
231 vrele(umapm_rootvp);
232 /*
233 * And blow it away for future re-use
234 */
235 vgone(umapm_rootvp);
236 /*
237 * Finally, throw away the umap_mount structure
238 */
239 free(mp->mnt_data, M_UFSMNT); /* XXX */
240 mp->mnt_data = 0;
241 return (0);
242 }
243
244 int
umapfs_root(mp,vpp)245 umapfs_root(mp, vpp)
246 struct mount *mp;
247 struct vnode **vpp;
248 {
249 struct proc *p = curproc; /* XXX */
250 struct vnode *vp;
251
252 #ifdef UMAPFS_DIAGNOSTIC
253 printf("umapfs_root(mp = %x, vp = %x->%x)\n", mp,
254 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
255 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
256 );
257 #endif
258
259 /*
260 * Return locked reference to root.
261 */
262 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
263 VREF(vp);
264 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
265 *vpp = vp;
266 return (0);
267 }
268
269 int
umapfs_quotactl(mp,cmd,uid,arg,p)270 umapfs_quotactl(mp, cmd, uid, arg, p)
271 struct mount *mp;
272 int cmd;
273 uid_t uid;
274 caddr_t arg;
275 struct proc *p;
276 {
277 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
278 }
279
280 int
umapfs_statfs(mp,sbp,p)281 umapfs_statfs(mp, sbp, p)
282 struct mount *mp;
283 struct statfs *sbp;
284 struct proc *p;
285 {
286 int error;
287 struct statfs mstat;
288
289 #ifdef UMAPFS_DIAGNOSTIC
290 printf("umapfs_statfs(mp = %x, vp = %x->%x)\n", mp,
291 MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
292 UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp)
293 );
294 #endif
295
296 bzero(&mstat, sizeof(mstat));
297
298 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
299 if (error)
300 return (error);
301
302 /* now copy across the "interesting" information and fake the rest */
303 sbp->f_type = mstat.f_type;
304 sbp->f_flags = mstat.f_flags;
305 sbp->f_bsize = mstat.f_bsize;
306 sbp->f_iosize = mstat.f_iosize;
307 sbp->f_blocks = mstat.f_blocks;
308 sbp->f_bfree = mstat.f_bfree;
309 sbp->f_bavail = mstat.f_bavail;
310 sbp->f_files = mstat.f_files;
311 sbp->f_ffree = mstat.f_ffree;
312 if (sbp != &mp->mnt_stat) {
313 bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid));
314 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
315 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
316 }
317 return (0);
318 }
319
320 int
umapfs_sync(mp,waitfor,cred,p)321 umapfs_sync(mp, waitfor, cred, p)
322 struct mount *mp;
323 int waitfor;
324 struct ucred *cred;
325 struct proc *p;
326 {
327 /*
328 * XXX - Assumes no data cached at umap layer.
329 */
330 return (0);
331 }
332
333 int
umapfs_vget(mp,ino,vpp)334 umapfs_vget(mp, ino, vpp)
335 struct mount *mp;
336 ino_t ino;
337 struct vnode **vpp;
338 {
339
340 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
341 }
342
343 int
umapfs_fhtovp(mp,fidp,nam,vpp,exflagsp,credanonp)344 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
345 struct mount *mp;
346 struct fid *fidp;
347 struct mbuf *nam;
348 struct vnode **vpp;
349 int *exflagsp;
350 struct ucred**credanonp;
351 {
352
353 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp));
354 }
355
356 int
umapfs_vptofh(vp,fhp)357 umapfs_vptofh(vp, fhp)
358 struct vnode *vp;
359 struct fid *fhp;
360 {
361 return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp));
362 }
363
364 int umapfs_init __P((struct vfsconf *));
365 #define umapfs_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
366 size_t, struct proc *)))eopnotsupp)
367
368 struct vfsops umap_vfsops = {
369 umapfs_mount,
370 umapfs_start,
371 umapfs_unmount,
372 umapfs_root,
373 umapfs_quotactl,
374 umapfs_statfs,
375 umapfs_sync,
376 umapfs_vget,
377 umapfs_fhtovp,
378 umapfs_vptofh,
379 umapfs_init,
380 umapfs_sysctl,
381 };
382