]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/umapfs/umap_vfsops.c
This commit was generated by cvs2svn to compensate for changes in r157043,
[FreeBSD/FreeBSD.git] / sys / fs / umapfs / umap_vfsops.c
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                 mp->mnt_flag |= MNT_LOCAL;
221         mp->mnt_data = (qaddr_t) amp;
222         vfs_getnewfsid(mp);
223
224         (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
225             &size);
226         bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
227         (void)umapfs_statfs(mp, &mp->mnt_stat, td);
228 #ifdef DEBUG
229         printf("umapfs_mount: lower %s, alias at %s\n",
230                 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
231 #endif
232         return (0);
233 }
234
235 /*
236  * Free reference to umap layer
237  */
238 static int
239 umapfs_unmount(mp, mntflags, td)
240         struct mount *mp;
241         int mntflags;
242         struct thread *td;
243 {
244         int error;
245         int flags = 0;
246
247 #ifdef DEBUG
248         printf("umapfs_unmount(mp = %p)\n", (void *)mp);
249 #endif
250
251         if (mntflags & MNT_FORCE)
252                 flags |= FORCECLOSE;
253
254         /*
255          * Clear out buffer cache.  I don't think we
256          * ever get anything cached at this level at the
257          * moment, but who knows...
258          */
259 #ifdef notyet
260         mntflushbuf(mp, 0);
261         if (mntinvalbuf(mp, 1))
262                 return (EBUSY);
263 #endif
264         /* There is 1 extra root vnode reference (umapm_rootvp). */
265         error = vflush(mp, 1, flags, td);
266         if (error)
267                 return (error);
268
269         /*
270          * Finally, throw away the umap_mount structure
271          */
272         free(mp->mnt_data, M_UMAPFSMNT);        /* XXX */
273         mp->mnt_data = 0;
274         return (0);
275 }
276
277 static int
278 umapfs_root(mp, flags, vpp, td)
279         struct mount *mp;
280         int flags;
281         struct vnode **vpp;
282         struct thread *td;
283 {
284         struct thread *td = curthread;  /* XXX */
285         struct vnode *vp;
286
287 #ifdef DEBUG
288         printf("umapfs_root(mp = %p, vp = %p->%p)\n",
289             (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
290             (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
291 #endif
292
293         /*
294          * Return locked reference to root.
295          */
296         vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
297         VREF(vp);
298         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
299         *vpp = vp;
300         return (0);
301 }
302
303 static int
304 umapfs_quotactl(mp, cmd, uid, arg, td)
305         struct mount *mp;
306         int cmd;
307         uid_t uid;
308         caddr_t arg;
309         struct thread *td;
310 {
311
312         return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, td));
313 }
314
315 static int
316 umapfs_statfs(mp, sbp, td)
317         struct mount *mp;
318         struct statfs *sbp;
319         struct thread *td;
320 {
321         int error;
322         struct statfs mstat;
323
324 #ifdef DEBUG
325         printf("umapfs_statfs(mp = %p, vp = %p->%p)\n",
326             (void *)mp, (void *)MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
327             (void *)UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
328 #endif
329
330         bzero(&mstat, sizeof(mstat));
331
332         error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, td);
333         if (error)
334                 return (error);
335
336         /* now copy across the "interesting" information and fake the rest */
337         sbp->f_type = mstat.f_type;
338         sbp->f_flags = mstat.f_flags;
339         sbp->f_bsize = mstat.f_bsize;
340         sbp->f_iosize = mstat.f_iosize;
341         sbp->f_blocks = mstat.f_blocks;
342         sbp->f_bfree = mstat.f_bfree;
343         sbp->f_bavail = mstat.f_bavail;
344         sbp->f_files = mstat.f_files;
345         sbp->f_ffree = mstat.f_ffree;
346         return (0);
347 }
348
349 static int
350 umapfs_vget(mp, ino, flags, vpp)
351         struct mount *mp;
352         ino_t ino;
353         int flags;
354         struct vnode **vpp;
355 {
356
357         return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, flags, vpp));
358 }
359
360 static int
361 umapfs_fhtovp(mp, fidp, vpp)
362         struct mount *mp;
363         struct fid *fidp;
364         struct vnode **vpp;
365 {
366
367         return (VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp));
368 }
369
370 static int
371 umapfs_checkexp(mp, nam, exflagsp, credanonp)
372         struct mount *mp;
373         struct sockaddr *nam;
374         int *exflagsp;
375         struct ucred **credanonp;
376 {
377
378         return (VFS_CHECKEXP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, nam,
379                 exflagsp, credanonp));
380 }
381
382 static int
383 umapfs_vptofh(vp, fhp)
384         struct vnode *vp;
385         struct fid *fhp;
386 {
387         struct vnode *lvp;
388
389         lvp = UMAPVPTOLOWERVP(vp);
390         return (VFS_VPTOFH(lvp, fhp));
391 }
392
393 static int
394 umapfs_extattrctl(mp, cmd, filename_vp, namespace, attrname, td)
395         struct mount *mp;
396         int cmd;
397         struct vnode *filename_vp;
398         int namespace;
399         const char *attrname;
400         struct thread *td;
401 {
402
403         return (VFS_EXTATTRCTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd,
404             filename_vp, namespace, attrname, td));
405 }
406
407 static struct vfsops umap_vfsops = {
408         .vfs_checkexp =                 umapfs_checkexp,
409         .vfs_extattrctl =               umapfs_extattrctl,
410         .vfs_fhtovp =                   umapfs_fhtovp,
411         .vfs_init =                     umapfs_init,
412         .vfs_omount =                   umapfs_omount,
413         .vfs_quotactl =                 umapfs_quotactl,
414         .vfs_root =                     umapfs_root,
415         .vfs_statfs =                   umapfs_statfs,
416         .vfs_unmount =                  umapfs_unmount,
417         .vfs_vget =                     umapfs_vget,
418         .vfs_vptofh =                   umapfs_vptofh,
419 };
420
421 VFS_SET(umap_vfsops, umapfs, VFCF_LOOPBACK);