Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / miscfs / umapfs / umap_vfsops.c
blobb40e24f4394a0940a7577957b69c6abfedbda6b6
1 /* $NetBSD: umap_vfsops.c,v 1.81 2008/12/05 13:05:38 ad Exp $ */
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software donated to Berkeley by
8 * the UCLA Ficus project.
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
34 * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
35 * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
39 * Umap Layer
40 * (See mount_umap(8) for a description of this layer.)
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: umap_vfsops.c,v 1.81 2008/12/05 13:05:38 ad Exp $");
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/sysctl.h>
49 #include <sys/proc.h>
50 #include <sys/time.h>
51 #include <sys/vnode.h>
52 #include <sys/mount.h>
53 #include <sys/namei.h>
54 #include <sys/malloc.h>
55 #include <sys/kauth.h>
56 #include <sys/module.h>
58 #include <miscfs/umapfs/umap.h>
59 #include <miscfs/genfs/layer_extern.h>
61 MODULE(MODULE_CLASS_VFS, umapfs, "layerfs");
63 VFS_PROTOS(umapfs);
65 static struct sysctllog *umapfs_sysctl_log;
68 * Mount umap layer
70 int
71 umapfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
73 struct lwp *l = curlwp;
74 struct nameidata nd;
75 struct umap_args *args = data;
76 struct vnode *lowerrootvp, *vp;
77 struct umap_mount *amp;
78 int error;
79 #ifdef UMAPFS_DIAGNOSTIC
80 int i;
81 #endif
83 if (*data_len < sizeof *args)
84 return EINVAL;
86 if (mp->mnt_flag & MNT_GETARGS) {
87 amp = MOUNTTOUMAPMOUNT(mp);
88 if (amp == NULL)
89 return EIO;
90 args->la.target = NULL;
91 args->nentries = amp->info_nentries;
92 args->gnentries = amp->info_gnentries;
93 *data_len = sizeof *args;
94 return 0;
97 /* only for root */
98 if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
99 NULL)) != 0)
100 return error;
102 #ifdef UMAPFS_DIAGNOSTIC
103 printf("umapfs_mount(mp = %p)\n", mp);
104 #endif
107 * Update is not supported
109 if (mp->mnt_flag & MNT_UPDATE)
110 return EOPNOTSUPP;
113 * Find lower node
115 NDINIT(&nd, LOOKUP, FOLLOW|LOCKLEAF,
116 UIO_USERSPACE, args->umap_target);
117 if ((error = namei(&nd)) != 0)
118 return (error);
121 * Sanity check on lower vnode
123 lowerrootvp = nd.ni_vp;
124 #ifdef UMAPFS_DIAGNOSTIC
125 printf("vp = %p, check for VDIR...\n", lowerrootvp);
126 #endif
128 if (lowerrootvp->v_type != VDIR) {
129 vput(lowerrootvp);
130 return (EINVAL);
133 #ifdef UMAPFS_DIAGNOSTIC
134 printf("mp = %p\n", mp);
135 #endif
137 amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
138 M_UFSMNT, M_WAITOK); /* XXX */
139 memset(amp, 0, sizeof(struct umap_mount));
141 mp->mnt_data = amp;
142 amp->umapm_vfs = lowerrootvp->v_mount;
143 if (amp->umapm_vfs->mnt_flag & MNT_LOCAL)
144 mp->mnt_flag |= MNT_LOCAL;
147 * Now copy in the number of entries and maps for umap mapping.
149 if (args->nentries > MAPFILEENTRIES || args->gnentries > GMAPFILEENTRIES) {
150 vput(lowerrootvp);
151 return (error);
154 amp->info_nentries = args->nentries;
155 amp->info_gnentries = args->gnentries;
156 error = copyin(args->mapdata, amp->info_mapdata,
157 2*sizeof(u_long)*args->nentries);
158 if (error) {
159 vput(lowerrootvp);
160 return (error);
163 #ifdef UMAPFS_DIAGNOSTIC
164 printf("umap_mount:nentries %d\n",args->nentries);
165 for (i = 0; i < args->nentries; i++)
166 printf(" %ld maps to %ld\n", amp->info_mapdata[i][0],
167 amp->info_mapdata[i][1]);
168 #endif
170 error = copyin(args->gmapdata, amp->info_gmapdata,
171 2*sizeof(u_long)*args->gnentries);
172 if (error) {
173 vput(lowerrootvp);
174 return (error);
177 #ifdef UMAPFS_DIAGNOSTIC
178 printf("umap_mount:gnentries %d\n",args->gnentries);
179 for (i = 0; i < args->gnentries; i++)
180 printf("\tgroup %ld maps to %ld\n",
181 amp->info_gmapdata[i][0],
182 amp->info_gmapdata[i][1]);
183 #endif
186 * Make sure the mount point's sufficiently initialized
187 * that the node create call will work.
189 vfs_getnewfsid(mp);
190 amp->umapm_size = sizeof(struct umap_node);
191 amp->umapm_tag = VT_UMAP;
192 amp->umapm_bypass = umap_bypass;
193 amp->umapm_alloc = layer_node_alloc; /* the default alloc is fine */
194 amp->umapm_vnodeop_p = umap_vnodeop_p;
195 mutex_init(&amp->umapm_hashlock, MUTEX_DEFAULT, IPL_NONE);
196 amp->umapm_node_hashtbl = hashinit(NUMAPNODECACHE, HASH_LIST, true,
197 &amp->umapm_node_hash);
201 * fix up umap node for root vnode.
203 error = layer_node_create(mp, lowerrootvp, &vp);
205 * Make sure the node alias worked
207 if (error) {
208 vput(lowerrootvp);
209 hashdone(amp->umapm_node_hashtbl, HASH_LIST,
210 amp->umapm_node_hash);
211 free(amp, M_UFSMNT); /* XXX */
212 return (error);
215 * Unlock the node (either the lower or the alias)
217 vp->v_vflag |= VV_ROOT;
218 VOP_UNLOCK(vp, 0);
221 * Keep a held reference to the root vnode.
222 * It is vrele'd in umapfs_unmount.
224 amp->umapm_rootvp = vp;
226 error = set_statvfs_info(path, UIO_USERSPACE, args->umap_target,
227 UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
228 #ifdef UMAPFS_DIAGNOSTIC
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 error;
236 * Free reference to umap layer
239 umapfs_unmount(struct mount *mp, int mntflags)
241 struct umap_mount *amp = MOUNTTOUMAPMOUNT(mp);
242 struct vnode *rtvp = amp->umapm_rootvp;
243 int error;
244 int flags = 0;
246 #ifdef UMAPFS_DIAGNOSTIC
247 printf("umapfs_unmount(mp = %p)\n", mp);
248 #endif
250 if (mntflags & MNT_FORCE)
251 flags |= FORCECLOSE;
253 if (rtvp->v_usecount > 1 && (mntflags & MNT_FORCE) == 0)
254 return (EBUSY);
255 if ((error = vflush(mp, rtvp, flags)) != 0)
256 return (error);
258 #ifdef UMAPFS_DIAGNOSTIC
259 vprint("alias root of lower", rtvp);
260 #endif
262 * Blow it away for future re-use
264 vgone(rtvp);
266 * Finally, throw away the umap_mount structure
268 mutex_destroy(&amp->umapm_hashlock);
269 hashdone(amp->umapm_node_hashtbl, HASH_LIST, amp->umapm_node_hash);
270 free(amp, M_UFSMNT); /* XXX */
271 mp->mnt_data = NULL;
272 return (0);
275 extern const struct vnodeopv_desc umapfs_vnodeop_opv_desc;
277 const struct vnodeopv_desc * const umapfs_vnodeopv_descs[] = {
278 &umapfs_vnodeop_opv_desc,
279 NULL,
282 struct vfsops umapfs_vfsops = {
283 MOUNT_UMAP,
284 sizeof (struct umap_args),
285 umapfs_mount,
286 layerfs_start,
287 umapfs_unmount,
288 layerfs_root,
289 layerfs_quotactl,
290 layerfs_statvfs,
291 layerfs_sync,
292 layerfs_vget,
293 layerfs_fhtovp,
294 layerfs_vptofh,
295 layerfs_init,
296 NULL,
297 layerfs_done,
298 NULL, /* vfs_mountroot */
299 layerfs_snapshot,
300 vfs_stdextattrctl,
301 (void *)eopnotsupp, /* vfs_suspendctl */
302 layerfs_renamelock_enter,
303 layerfs_renamelock_exit,
304 (void *)eopnotsupp,
305 umapfs_vnodeopv_descs,
306 0, /* vfs_refcount */
307 { NULL, NULL },
310 static int
311 umapfs_modcmd(modcmd_t cmd, void *arg)
313 int error;
315 switch (cmd) {
316 case MODULE_CMD_INIT:
317 error = vfs_attach(&umapfs_vfsops);
318 if (error != 0)
319 break;
320 sysctl_createv(&umapfs_sysctl_log, 0, NULL, NULL,
321 CTLFLAG_PERMANENT,
322 CTLTYPE_NODE, "vfs", NULL,
323 NULL, 0, NULL, 0,
324 CTL_VFS, CTL_EOL);
325 sysctl_createv(&umapfs_sysctl_log, 0, NULL, NULL,
326 CTLFLAG_PERMANENT,
327 CTLTYPE_NODE, "umap",
328 SYSCTL_DESCR("UID/GID remapping file system"),
329 NULL, 0, NULL, 0,
330 CTL_VFS, 10, CTL_EOL);
332 * XXX the "10" above could be dynamic, thereby eliminating
333 * one more instance of the "number to vfs" mapping problem,
334 * but "10" is the order as taken from sys/mount.h
336 break;
337 case MODULE_CMD_FINI:
338 error = vfs_detach(&umapfs_vfsops);
339 if (error != 0)
340 break;
341 sysctl_teardown(&umapfs_sysctl_log);
342 break;
343 default:
344 error = ENOTTY;
345 break;
348 return (error);