umap_vfsops.c revision 1.39.2.2 1 /* $NetBSD: umap_vfsops.c,v 1.39.2.2 2003/07/03 01:23:44 wrstuden Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software donated to Berkeley by
8 * the UCLA Ficus project.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
39 * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
40 */
41
42 /*
43 * Umap Layer
44 * (See mount_umap(8) for a description of this layer.)
45 */
46
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.39.2.2 2003/07/03 01:23:44 wrstuden Exp $");
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/proc.h>
53 #include <sys/time.h>
54 #include <sys/vnode.h>
55 #include <sys/mount.h>
56 #include <sys/namei.h>
57 #include <sys/malloc.h>
58 #include <miscfs/umapfs/umap.h>
59 #include <miscfs/genfs/layer_extern.h>
60
61 int umapfs_mount __P((struct mount *, const char *, void *,
62 struct nameidata *, struct lwp *));
63 int umapfs_unmount __P((struct mount *, int, struct lwp *));
64
65 /*
66 * Mount umap layer
67 */
68 int
69 umapfs_mount(mp, path, data, ndp, l)
70 struct mount *mp;
71 const char *path;
72 void *data;
73 struct nameidata *ndp;
74 struct lwp *l;
75 {
76 struct umap_args args;
77 struct vnode *lowerrootvp, *vp;
78 struct umap_mount *amp;
79 struct proc *p;
80 int error;
81 #ifdef UMAPFS_DIAGNOSTIC
82 int i;
83 #endif
84
85 if (mp->mnt_flag & MNT_GETARGS) {
86 amp = MOUNTTOUMAPMOUNT(mp);
87 if (amp == NULL)
88 return EIO;
89 args.la.target = NULL;
90 vfs_showexport(mp, &args.la.export, &->umapm_export);
91 args.nentries = amp->info_nentries;
92 args.gnentries = amp->info_gnentries;
93 return copyout(&args, data, sizeof(args));
94 }
95
96 /* only for root */
97 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
98 return error;
99
100 #ifdef UMAPFS_DIAGNOSTIC
101 printf("umapfs_mount(mp = %p)\n", mp);
102 #endif
103
104 /*
105 * Get argument
106 */
107 error = copyin(data, (caddr_t)&args, sizeof(struct umap_args));
108 if (error)
109 return (error);
110
111 /*
112 * Update only does export updating.
113 */
114 if (mp->mnt_flag & MNT_UPDATE) {
115 amp = MOUNTTOUMAPMOUNT(mp);
116 if (args.umap_target == 0)
117 return (vfs_export(mp, &->umapm_export,
118 &args.umap_export));
119 else
120 return (EOPNOTSUPP);
121 }
122
123 /*
124 * Find lower node
125 */
126 NDINIT(ndp, LOOKUP, FOLLOW|LOCKLEAF,
127 UIO_USERSPACE, args.umap_target, l);
128 if ((error = namei(ndp)) != 0)
129 return (error);
130
131 /*
132 * Sanity check on lower vnode
133 */
134 lowerrootvp = ndp->ni_vp;
135 #ifdef UMAPFS_DIAGNOSTIC
136 printf("vp = %p, check for VDIR...\n", lowerrootvp);
137 #endif
138
139 if (lowerrootvp->v_type != VDIR) {
140 vput(lowerrootvp);
141 return (EINVAL);
142 }
143
144 #ifdef UMAPFS_DIAGNOSTIC
145 printf("mp = %p\n", mp);
146 #endif
147
148 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
149 M_UFSMNT, M_WAITOK); /* XXX */
150 memset((caddr_t)amp, 0, sizeof(struct umap_mount));
151
152 mp->mnt_data = amp;
153 amp->umapm_vfs = lowerrootvp->v_mount;
154 if (amp->umapm_vfs->mnt_flag & MNT_LOCAL)
155 mp->mnt_flag |= MNT_LOCAL;
156
157 /*
158 * Now copy in the number of entries and maps for umap mapping.
159 */
160 if (args.nentries > MAPFILEENTRIES || args.gnentries > GMAPFILEENTRIES) {
161 vput(lowerrootvp);
162 return (error);
163 }
164
165 amp->info_nentries = args.nentries;
166 amp->info_gnentries = args.gnentries;
167 error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
168 2*sizeof(u_long)*args.nentries);
169 if (error) {
170 vput(lowerrootvp);
171 return (error);
172 }
173
174 #ifdef UMAPFS_DIAGNOSTIC
175 printf("umap_mount:nentries %d\n",args.nentries);
176 for (i = 0; i < args.nentries; i++)
177 printf(" %ld maps to %ld\n", amp->info_mapdata[i][0],
178 amp->info_mapdata[i][1]);
179 #endif
180
181 error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
182 2*sizeof(u_long)*args.gnentries);
183 if (error) {
184 vput(lowerrootvp);
185 return (error);
186 }
187
188 #ifdef UMAPFS_DIAGNOSTIC
189 printf("umap_mount:gnentries %d\n",args.gnentries);
190 for (i = 0; i < args.gnentries; i++)
191 printf("\tgroup %ld maps to %ld\n",
192 amp->info_gmapdata[i][0],
193 amp->info_gmapdata[i][1]);
194 #endif
195
196 /*
197 * Make sure the mount point's sufficiently initialized
198 * that the node create call will work.
199 */
200 vfs_getnewfsid(mp);
201 amp->umapm_size = sizeof(struct umap_node);
202 amp->umapm_tag = VT_UMAP;
203 amp->umapm_bypass = umap_bypass;
204 amp->umapm_alloc = layer_node_alloc; /* the default alloc is fine */
205 amp->umapm_vnodeop_p = umap_vnodeop_p;
206 simple_lock_init(&->umapm_hashlock);
207 amp->umapm_node_hashtbl = hashinit(NUMAPNODECACHE, HASH_LIST, M_CACHE,
208 M_WAITOK, &->umapm_node_hash);
209
210
211 /*
212 * fix up umap node for root vnode.
213 */
214 error = layer_node_create(mp, lowerrootvp, &vp);
215 /*
216 * Make sure the node alias worked
217 */
218 if (error) {
219 vput(lowerrootvp);
220 free(amp, M_UFSMNT); /* XXX */
221 return (error);
222 }
223 /*
224 * Unlock the node (either the lower or the alias)
225 */
226 VOP_UNLOCK(vp, 0);
227
228 /*
229 * Keep a held reference to the root vnode.
230 * It is vrele'd in umapfs_unmount.
231 */
232 vp->v_flag |= VROOT;
233 amp->umapm_rootvp = vp;
234
235 error = set_statfs_info(path, UIO_USERSPACE, args.umap_target,
236 UIO_USERSPACE, mp, l);
237 #ifdef UMAPFS_DIAGNOSTIC
238 printf("umapfs_mount: lower %s, alias at %s\n",
239 mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
240 #endif
241 return error;
242 }
243
244 /*
245 * Free reference to umap layer
246 */
247 int
248 umapfs_unmount(mp, mntflags, l)
249 struct mount *mp;
250 int mntflags;
251 struct lwp *l;
252 {
253 struct vnode *rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
254 int error;
255 int flags = 0;
256
257 #ifdef UMAPFS_DIAGNOSTIC
258 printf("umapfs_unmount(mp = %p)\n", mp);
259 #endif
260
261 if (mntflags & MNT_FORCE)
262 flags |= FORCECLOSE;
263
264 /*
265 * Clear out buffer cache. I don't think we
266 * ever get anything cached at this level at the
267 * moment, but who knows...
268 */
269 #ifdef notyet
270 mntflushbuf(mp, 0);
271 if (mntinvalbuf(mp, 1))
272 return (EBUSY);
273 #endif
274 if (rootvp->v_usecount > 1)
275 return (EBUSY);
276 if ((error = vflush(mp, rootvp, flags)) != 0)
277 return (error);
278
279 #ifdef UMAPFS_DIAGNOSTIC
280 vprint("alias root of lower", rootvp);
281 #endif
282 /*
283 * Release reference on underlying root vnode
284 */
285 vrele(rootvp);
286 /*
287 * And blow it away for future re-use
288 */
289 vgone(rootvp);
290 /*
291 * Finally, throw away the umap_mount structure
292 */
293 free(mp->mnt_data, M_UFSMNT); /* XXX */
294 mp->mnt_data = 0;
295 return (0);
296 }
297
298 extern const struct vnodeopv_desc umapfs_vnodeop_opv_desc;
299
300 const struct vnodeopv_desc * const umapfs_vnodeopv_descs[] = {
301 &umapfs_vnodeop_opv_desc,
302 NULL,
303 };
304
305 struct vfsops umapfs_vfsops = {
306 MOUNT_UMAP,
307 umapfs_mount,
308 layerfs_start,
309 umapfs_unmount,
310 layerfs_root,
311 layerfs_quotactl,
312 layerfs_statfs,
313 layerfs_sync,
314 layerfs_vget,
315 layerfs_fhtovp,
316 layerfs_vptofh,
317 layerfs_init,
318 NULL,
319 layerfs_done,
320 layerfs_sysctl,
321 NULL, /* vfs_mountroot */
322 layerfs_checkexp,
323 umapfs_vnodeopv_descs,
324 };
325