1 /* $NetBSD: umap_vfsops.c,v 1.81 2008/12/05 13:05:38 ad Exp $ */
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
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
34 * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92
35 * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95
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>
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");
65 static struct sysctllog
*umapfs_sysctl_log
;
71 umapfs_mount(struct mount
*mp
, const char *path
, void *data
, size_t *data_len
)
73 struct lwp
*l
= curlwp
;
75 struct umap_args
*args
= data
;
76 struct vnode
*lowerrootvp
, *vp
;
77 struct umap_mount
*amp
;
79 #ifdef UMAPFS_DIAGNOSTIC
83 if (*data_len
< sizeof *args
)
86 if (mp
->mnt_flag
& MNT_GETARGS
) {
87 amp
= MOUNTTOUMAPMOUNT(mp
);
90 args
->la
.target
= NULL
;
91 args
->nentries
= amp
->info_nentries
;
92 args
->gnentries
= amp
->info_gnentries
;
93 *data_len
= sizeof *args
;
98 if ((error
= kauth_authorize_generic(l
->l_cred
, KAUTH_GENERIC_ISSUSER
,
102 #ifdef UMAPFS_DIAGNOSTIC
103 printf("umapfs_mount(mp = %p)\n", mp
);
107 * Update is not supported
109 if (mp
->mnt_flag
& MNT_UPDATE
)
115 NDINIT(&nd
, LOOKUP
, FOLLOW
|LOCKLEAF
,
116 UIO_USERSPACE
, args
->umap_target
);
117 if ((error
= namei(&nd
)) != 0)
121 * Sanity check on lower vnode
123 lowerrootvp
= nd
.ni_vp
;
124 #ifdef UMAPFS_DIAGNOSTIC
125 printf("vp = %p, check for VDIR...\n", lowerrootvp
);
128 if (lowerrootvp
->v_type
!= VDIR
) {
133 #ifdef UMAPFS_DIAGNOSTIC
134 printf("mp = %p\n", mp
);
137 amp
= (struct umap_mount
*) malloc(sizeof(struct umap_mount
),
138 M_UFSMNT
, M_WAITOK
); /* XXX */
139 memset(amp
, 0, sizeof(struct umap_mount
));
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
) {
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
);
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]);
170 error
= copyin(args
->gmapdata
, amp
->info_gmapdata
,
171 2*sizeof(u_long
)*args
->gnentries
);
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]);
186 * Make sure the mount point's sufficiently initialized
187 * that the node create call will work.
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(&
->umapm_hashlock
, MUTEX_DEFAULT
, IPL_NONE
);
196 amp
->umapm_node_hashtbl
= hashinit(NUMAPNODECACHE
, HASH_LIST
, true,
197 &
->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
209 hashdone(amp
->umapm_node_hashtbl
, HASH_LIST
,
210 amp
->umapm_node_hash
);
211 free(amp
, M_UFSMNT
); /* XXX */
215 * Unlock the node (either the lower or the alias)
217 vp
->v_vflag
|= VV_ROOT
;
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
);
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
;
246 #ifdef UMAPFS_DIAGNOSTIC
247 printf("umapfs_unmount(mp = %p)\n", mp
);
250 if (mntflags
& MNT_FORCE
)
253 if (rtvp
->v_usecount
> 1 && (mntflags
& MNT_FORCE
) == 0)
255 if ((error
= vflush(mp
, rtvp
, flags
)) != 0)
258 #ifdef UMAPFS_DIAGNOSTIC
259 vprint("alias root of lower", rtvp
);
262 * Blow it away for future re-use
266 * Finally, throw away the umap_mount structure
268 mutex_destroy(&
->umapm_hashlock
);
269 hashdone(amp
->umapm_node_hashtbl
, HASH_LIST
, amp
->umapm_node_hash
);
270 free(amp
, M_UFSMNT
); /* XXX */
275 extern const struct vnodeopv_desc umapfs_vnodeop_opv_desc
;
277 const struct vnodeopv_desc
* const umapfs_vnodeopv_descs
[] = {
278 &umapfs_vnodeop_opv_desc
,
282 struct vfsops umapfs_vfsops
= {
284 sizeof (struct umap_args
),
298 NULL
, /* vfs_mountroot */
301 (void *)eopnotsupp
, /* vfs_suspendctl */
302 layerfs_renamelock_enter
,
303 layerfs_renamelock_exit
,
305 umapfs_vnodeopv_descs
,
306 0, /* vfs_refcount */
311 umapfs_modcmd(modcmd_t cmd
, void *arg
)
316 case MODULE_CMD_INIT
:
317 error
= vfs_attach(&umapfs_vfsops
);
320 sysctl_createv(&umapfs_sysctl_log
, 0, NULL
, NULL
,
322 CTLTYPE_NODE
, "vfs", NULL
,
325 sysctl_createv(&umapfs_sysctl_log
, 0, NULL
, NULL
,
327 CTLTYPE_NODE
, "umap",
328 SYSCTL_DESCR("UID/GID remapping file system"),
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
337 case MODULE_CMD_FINI
:
338 error
= vfs_detach(&umapfs_vfsops
);
341 sysctl_teardown(&umapfs_sysctl_log
);