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 * 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 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
33 *
34 * $FreeBSD$
35 */
36
37 /*
38 * Umap Layer
39 * (See mount_umapfs(8) for a description of this layer.)
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mount.h>
48 #include <sys/mutex.h>
49 #include <sys/namei.h>
50 #include <sys/vnode.h>
51
52 #include <fs/umapfs/umap.h>
53
54 static MALLOC_DEFINE(M_UMAPFSMNT, "UMAP mount", "UMAP mount structure");
55
56 static vfs_omount_t umapfs_omount;
57 static vfs_root_t umapfs_root;
58 static vfs_quotactl_t umapfs_quotactl;
59 static vfs_statfs_t umapfs_statfs;
60 static vfs_unmount_t umapfs_unmount;
61 static vfs_fhtovp_t umapfs_fhtovp;
62 static vfs_vptofh_t umapfs_vptofh;
63 static vfs_checkexp_t umapfs_checkexp;
64 static vfs_vget_t umapfs_vget;
65 static vfs_extattrctl_t umapfs_extattrctl;
66
67 /*
68 * Mount umap layer
69 */
70 static int
71 umapfs_omount(mp, path, data, ndp, td)
72 struct mount *mp;
73 char *path;
74 caddr_t data;
75 struct nameidata *ndp;
76 struct thread *td;
77 {
78 struct umap_args args;
79 struct vnode *lowerrootvp, *vp;
80 struct vnode *umapm_rootvp;
81 struct umap_mount *amp;
82 size_t size;
83 int error;
84 #ifdef DEBUG
85 int i;
86 #endif
87
88 /*
89 * Only for root
90 */
91 if ((error = suser(td)) != 0)
92 return (error);
93
94 #ifdef DEBUG
95 printf("umapfs_mount(mp = %p)\n", (void *)mp);
96 #endif
97
98 /*
99 * Update is a no-op
100 */
101 if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) {
102 return (EOPNOTSUPP);
103 /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, td));*/
104 }
105
106 /*
107 * Get argument
108 */
109 error = copyin(data, (caddr_t)&args, sizeof(struct umap_args));
110 if (error)
111 return (error);
112
113 /*
114 * Find lower node
115 */
116 NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
117 UIO_USERSPACE, args.target, td);
118 error = namei(ndp);
119 if (error)
120 return (error);
121 NDFREE(ndp, NDF_ONLY_PNBUF);
122
123 /*
124 * Sanity check on lower vnode
125 */
126 lowerrootvp = ndp->ni_vp;
127 #ifdef DEBUG
128 printf("vp = %p, check for VDIR...\n", (void *)lowerrootvp);
129 #endif
130 vrele(ndp->ni_dvp);
131 ndp->ni_dvp = 0;
132
133 if (lowerrootvp->v_type != VDIR) {
134 vput(lowerrootvp);
135 return (EINVAL);
136 }
137
138 #ifdef DEBUG
139 printf("mp = %p\n", (void *)mp);
140 #endif
141
142 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
143 M_UMAPFSMNT, M_WAITOK); /* XXX */
144
145 /*
146 * Save reference to underlying FS
147 */
148 amp->umapm_vfs = lowerrootvp->v_mount;
149
150 /*
151 * Now copy in the number of entries and maps for umap mapping.
152 */
153 if (args.nentries > MAPFILEENTRIES || args.gnentries >
154 GMAPFILEENTRIES) {
155 vput(lowerrootvp);
156 free(amp, M_UMAPFSMNT);
157 /* XXX missing error = EINVAL ? */
158 return (error);
159 }
160
161 amp->info_nentries = args.nentries;
162 amp->info_gnentries = args.gnentries;
163 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
164 2*sizeof(u_long)*args.nentries);
165 if (error) {
166 free(amp, M_UMAPFSMNT);
167 return (error);
168 }
169
170 #ifdef DEBUG
171 printf("umap_mount:nentries %d\n",args.nentries);
172 for (i = 0; i < args.nentries; i++)
173 printf(" %lu maps to %lu\n", amp->info_mapdata[i][0],
174 amp->info_mapdata[i][1]);
175 #endif
176
177 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
178 2*sizeof(u_long)*args.gnentries);
179 if (error) {
180 free(amp, M_UMAPFSMNT);
181 return (error);
182 }
183
184 #ifdef DEBUG
185 printf("umap_mount:gnentries %d\n",args.gnentries);
186 for (i = 0; i < args.gnentries; i++)
187 printf(" group %lu maps to %lu\n",
188 amp->info_gmapdata[i][0],
189 amp->info_gmapdata[i][1]);
190 #endif
191
192
193 /*
194 * Save reference. Each mount also holds
195 * a reference on the root vnode.
196 */
197 error = umap_node_create(mp, lowerrootvp, &vp);
198 /*
199 * Unlock the node (either the lower or the alias)
200 */
201 VOP_UNLOCK(vp, 0, td);
202 /*
203 * Make sure the node alias worked
204 */
205 if (error) {
206 vrele(lowerrootvp);
207 free(amp, M_UMAPFSMNT); /* XXX */
208 return (error);
209 }
210
211 /*
212 * Keep a held reference to the root vnode.
213 * It is vrele'd in umapfs_unmount.
214 */
215 ASSERT_VOP_LOCKED(vp, "umapfs_mount");
216 umapm_rootvp = vp;
217 umapm_rootvp->v_vflag |= VV_ROOT;
218 amp->umapm_rootvp = umapm_rootvp;
219 if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) {
220 MNT_ILOCK(mp);
221 mp->mnt_flag |= MNT_LOCAL;
222 MNT_IUNLOCK(mp);
223 }
224 mp->mnt_data = (qaddr_t) amp;
225 vfs_getnewfsid(mp);
226
227 (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
228 &size);
229 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
230 (void)umapfs_statfs(mp, &mp->mnt_stat, td);
231 #ifdef DEBUG
232 printf("umapfs_mount: lower %s, alias at %s\n",
233 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
234 #endif
235 return (0);
236 }
237
238 /*
239 * Free reference to umap layer
240 */
241 static int
242 umapfs_unmount(mp, mntflags, td)
243 struct mount *mp;
244 int mntflags;
245 struct thread *td;
246 {
247 int error;
248 int flags = 0;
249
250 #ifdef DEBUG
251 printf("umapfs_unmount(mp = %p)\n", (void *)mp);
252 #endif
253
254 if (mntflags & MNT_FORCE)
255 flags |= FORCECLOSE;
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 /* There is 1 extra root vnode reference (umapm_rootvp). */
268 error = vflush(mp, 1, flags, td);
269 if (error)
270 return (error);
271
272 /*
273 * Finally, throw away the umap_mount structure
274 */
275 free(mp->mnt_data, M_UMAPFSMNT); /* XXX */
276 mp->mnt_data = 0;
277 return (0);
278 }
279
280 static int
281 umapfs_root(mp, flags, vpp, td)
282 struct mount *mp;
283 int flags;
284 struct vnode **vpp;
285 struct thread *td;
286 {
287 struct thread *td = curthread; /* XXX */
288 struct vnode *vp;
289
290 #ifdef DEBUG
291 printf("umapfs_root(mp = %p, vp = %p->%p)\n",
292 (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
293 (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
294 #endif
295
296 /*
297 * Return locked reference to root.
298 */
299 vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
300 VREF(vp);
301 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
302 *vpp = vp;
303 return (0);
304 }
305
306 static int
307 umapfs_quotactl(mp, cmd, uid, arg, td)
308 struct mount *mp;
309 int cmd;
310 uid_t uid;
311 caddr_t arg;
312 struct thread *td;
313 {
314
315 return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, td));
316 }
317
318 static int
319 umapfs_statfs(mp, sbp, td)
320 struct mount *mp;
321 struct statfs *sbp;
322 struct thread *td;
323 {
324 int error;
325 struct statfs mstat;
326
327 #ifdef DEBUG
328 printf("umapfs_statfs(mp = %p, vp = %p->%p)\n",
329 (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
330 (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
331 #endif
332
333 bzero(&mstat, sizeof(mstat));
334
335 error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, td);
336 if (error)
337 return (error);
338
339 /* now copy across the "interesting" information and fake the rest */
340 sbp->f_type = mstat.f_type;
341 sbp->f_flags = mstat.f_flags;
342 sbp->f_bsize = mstat.f_bsize;
343 sbp->f_iosize = mstat.f_iosize;
344 sbp->f_blocks = mstat.f_blocks;
345 sbp->f_bfree = mstat.f_bfree;
346 sbp->f_bavail = mstat.f_bavail;
347 sbp->f_files = mstat.f_files;
348 sbp->f_ffree = mstat.f_ffree;
349 return (0);
350 }
351
352 static int
353 umapfs_vget(mp, ino, flags, vpp)
354 struct mount *mp;
355 ino_t ino;
356 int flags;
357 struct vnode **vpp;
358 {
359
360 return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, flags, vpp));
361 }
362
363 static int
364 umapfs_fhtovp(mp, fidp, vpp)
365 struct mount *mp;
366 struct fid *fidp;
367 struct vnode **vpp;
368 {
369
370 return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp));
371 }
372
373 static int
374 umapfs_checkexp(mp, nam, exflagsp, credanonp)
375 struct mount *mp;
376 struct sockaddr *nam;
377 int *exflagsp;
378 struct ucred **credanonp;
379 {
380
381 return (VFS_CHECKEXP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, nam,
382 exflagsp, credanonp));
383 }
384
385 static int
386 umapfs_vptofh(vp, fhp)
387 struct vnode *vp;
388 struct fid *fhp;
389 {
390 struct vnode *lvp;
391
392 lvp = UMAPVPTOLOWERVP(vp);
393 return (VFS_VPTOFH(lvp, fhp));
394 }
395
396 static int
397 umapfs_extattrctl(mp, cmd, filename_vp, namespace, attrname, td)
398 struct mount *mp;
399 int cmd;
400 struct vnode *filename_vp;
401 int namespace;
402 const char *attrname;
403 struct thread *td;
404 {
405
406 return (VFS_EXTATTRCTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd,
407 filename_vp, namespace, attrname, td));
408 }
409
410 static struct vfsops umap_vfsops = {
411 .vfs_checkexp = umapfs_checkexp,
412 .vfs_extattrctl = umapfs_extattrctl,
413 .vfs_fhtovp = umapfs_fhtovp,
414 .vfs_init = umapfs_init,
415 .vfs_omount = umapfs_omount,
416 .vfs_quotactl = umapfs_quotactl,
417 .vfs_root = umapfs_root,
418 .vfs_statfs = umapfs_statfs,
419 .vfs_unmount = umapfs_unmount,
420 .vfs_vget = umapfs_vget,
421 .vfs_vptofh = umapfs_vptofh,
422 };
423
424 VFS_SET(umap_vfsops, umapfs, VFCF_LOOPBACK);
Cache object: 8650f1fb8134d36fd38a38cee531e3d2
|