Commit | Line | Data |
---|---|---|
461c058b | 1 | /* |
ad787160 C |
2 | * Copyright (c) 1992, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
461c058b JH |
4 | * |
5 | * This code is derived from software donated to Berkeley by | |
e0851395 | 6 | * the UCLA Ficus project. |
461c058b | 7 | * |
ad787160 C |
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. | |
461c058b | 23 | * |
ad787160 C |
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 | * | |
ed554bc5 | 36 | * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94 |
461c058b | 37 | * |
e0851395 | 38 | * @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92 |
461c058b JH |
39 | */ |
40 | ||
41 | /* | |
e0851395 | 42 | * Umap Layer |
ddcb8262 | 43 | * (See mount_umap(8) for a description of this layer.) |
461c058b JH |
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> | |
ddcb8262 | 54 | #include <miscfs/umapfs/umap.h> |
461c058b JH |
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 | { | |
461c058b JH |
67 | struct umap_args args; |
68 | struct vnode *lowerrootvp, *vp; | |
69 | struct vnode *umapm_rootvp; | |
70 | struct umap_mount *amp; | |
71 | u_int size; | |
33e96e24 | 72 | int error; |
461c058b JH |
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); | |
33e96e24 | 83 | /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ |
461c058b JH |
84 | } |
85 | ||
86 | /* | |
87 | * Get argument | |
88 | */ | |
89 | if (error = copyin(data, (caddr_t)&args, sizeof(struct umap_args))) | |
90 | return (error); | |
91 | ||
92 | /* | |
e0851395 | 93 | * Find lower node |
461c058b JH |
94 | */ |
95 | NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, | |
96 | UIO_USERSPACE, args.target, p); | |
97 | if (error = namei(ndp)) | |
98 | return (error); | |
99 | ||
100 | /* | |
e0851395 | 101 | * Sanity check on lower vnode |
461c058b JH |
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 | ||
461c058b JH |
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 | /* | |
e0851395 | 123 | * Save reference to underlying FS |
461c058b JH |
124 | */ |
125 | amp->umapm_vfs = lowerrootvp->v_mount; | |
126 | ||
127 | /* | |
128 | * Now copy in the number of entries and maps for umap mapping. | |
129 | */ | |
461c058b JH |
130 | amp->info_nentries = args.nentries; |
131 | amp->info_gnentries = args.gnentries; | |
132 | error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, | |
33e96e24 KB |
133 | 2*sizeof(u_long)*args.nentries); |
134 | if (error) | |
135 | return (error); | |
e0851395 JH |
136 | |
137 | #ifdef UMAP_DIAGNOSTIC | |
461c058b | 138 | printf("umap_mount:nentries %d\n",args.nentries); |
e0851395 | 139 | for (i = 0; i < args.nentries; i++) |
461c058b JH |
140 | printf(" %d maps to %d\n", amp->info_mapdata[i][0], |
141 | amp->info_mapdata[i][1]); | |
e0851395 | 142 | #endif |
461c058b JH |
143 | |
144 | error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, | |
33e96e24 KB |
145 | 2*sizeof(u_long)*args.nentries); |
146 | if (error) | |
147 | return (error); | |
e0851395 JH |
148 | |
149 | #ifdef UMAP_DIAGNOSTIC | |
461c058b | 150 | printf("umap_mount:gnentries %d\n",args.gnentries); |
e0851395 | 151 | for (i = 0; i < args.gnentries; i++) |
461c058b JH |
152 | printf(" group %d maps to %d\n", |
153 | amp->info_gmapdata[i][0], | |
154 | amp->info_gmapdata[i][1]); | |
e0851395 | 155 | #endif |
461c058b JH |
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 | /* | |
e0851395 | 164 | * Unlock the node (either the lower or the alias) |
461c058b JH |
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 | |
e0851395 | 194 | printf("umapfs_mount: lower %s, alias at %s\n", |
461c058b JH |
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); | |
33e96e24 | 212 | /* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */ |
461c058b JH |
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 | */ | |
fb250c6b | 245 | #ifdef notyet |
461c058b JH |
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 | |
e0851395 | 256 | vprint("alias root of lower", umapm_rootvp); |
461c058b JH |
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; | |
33e96e24 | 271 | return (0); |
461c058b JH |
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; | |
33e96e24 | 295 | return (0); |
461c058b JH |
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 | { | |
33e96e24 | 306 | return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p)); |
461c058b JH |
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 | ||
33e96e24 | 369 | return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp)); |
461c058b JH |
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 | ||
33e96e24 | 382 | return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, nam, vpp, exflagsp,credanonp)); |
461c058b JH |
383 | } |
384 | ||
385 | int | |
386 | umapfs_vptofh(vp, fhp) | |
387 | struct vnode *vp; | |
388 | struct fid *fhp; | |
389 | { | |
33e96e24 | 390 | return (VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp)); |
461c058b JH |
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 | }; |