Home | History | Annotate | Line # | Download | only in umapfs
umap_vfsops.c revision 1.19
      1 /*	$NetBSD: umap_vfsops.c,v 1.19 1998/08/09 20:51:10 perry 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/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/proc.h>
     50 #include <sys/time.h>
     51 #include <sys/types.h>
     52 #include <sys/vnode.h>
     53 #include <sys/mount.h>
     54 #include <sys/namei.h>
     55 #include <sys/malloc.h>
     56 #include <miscfs/umapfs/umap.h>
     57 
     58 int	umapfs_mount __P((struct mount *, const char *, void *,
     59 			  struct nameidata *, struct proc *));
     60 int	umapfs_start __P((struct mount *, int, struct proc *));
     61 int	umapfs_unmount __P((struct mount *, int, struct proc *));
     62 int	umapfs_root __P((struct mount *, struct vnode **));
     63 int	umapfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
     64 			     struct proc *));
     65 int	umapfs_statfs __P((struct mount *, struct statfs *, struct proc *));
     66 int	umapfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
     67 int	umapfs_vget __P((struct mount *, ino_t, struct vnode **));
     68 int	umapfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
     69 			   struct vnode **, int *, struct ucred **));
     70 int	umapfs_vptofh __P((struct vnode *, struct fid *));
     71 int	umapfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
     72 			   struct proc *));
     73 
     74 /*
     75  * Mount umap layer
     76  */
     77 int
     78 umapfs_mount(mp, path, data, ndp, p)
     79 	struct mount *mp;
     80 	const char *path;
     81 	void *data;
     82 	struct nameidata *ndp;
     83 	struct proc *p;
     84 {
     85 	struct umap_args args;
     86 	struct vnode *lowerrootvp, *vp;
     87 	struct vnode *umapm_rootvp;
     88 	struct umap_mount *amp;
     89 	size_t size;
     90 	int error;
     91 
     92 #ifdef UMAPFS_DIAGNOSTIC
     93 	printf("umapfs_mount(mp = %p)\n", mp);
     94 #endif
     95 
     96 	/*
     97 	 * Update is a no-op
     98 	 */
     99 	if (mp->mnt_flag & MNT_UPDATE) {
    100 		return (EOPNOTSUPP);
    101 		/* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/
    102 	}
    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 	 * Find lower node
    113 	 */
    114 	NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
    115 		UIO_USERSPACE, args.target, p);
    116 	if ((error = namei(ndp)) != 0)
    117 		return (error);
    118 
    119 	/*
    120 	 * Sanity check on lower vnode
    121 	 */
    122 	lowerrootvp = ndp->ni_vp;
    123 #ifdef UMAPFS_DIAGNOSTIC
    124 	printf("vp = %p, check for VDIR...\n", lowerrootvp);
    125 #endif
    126 	vrele(ndp->ni_dvp);
    127 	ndp->ni_dvp = 0;
    128 
    129 	if (lowerrootvp->v_type != VDIR) {
    130 		vput(lowerrootvp);
    131 		return (EINVAL);
    132 	}
    133 
    134 #ifdef UMAPFS_DIAGNOSTIC
    135 	printf("mp = %p\n", mp);
    136 #endif
    137 
    138 	amp = (struct umap_mount *) malloc(sizeof(struct umap_mount),
    139 				M_UFSMNT, M_WAITOK);	/* XXX */
    140 
    141 	/*
    142 	 * Save reference to underlying FS
    143 	 */
    144 	amp->umapm_vfs = lowerrootvp->v_mount;
    145 
    146 	/*
    147 	 * Now copy in the number of entries and maps for umap mapping.
    148 	 */
    149 	amp->info_nentries = args.nentries;
    150 	amp->info_gnentries = args.gnentries;
    151 	error = copyin(args.mapdata, (caddr_t)amp->info_mapdata,
    152 	    2*sizeof(u_long)*args.nentries);
    153 	if (error)
    154 		return (error);
    155 
    156 #ifdef UMAP_DIAGNOSTIC
    157 	printf("umap_mount:nentries %d\n",args.nentries);
    158 	for (i = 0; i < args.nentries; i++)
    159 		printf("   %d maps to %d\n", amp->info_mapdata[i][0],
    160 	 	    amp->info_mapdata[i][1]);
    161 #endif
    162 
    163 	error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata,
    164 	    2*sizeof(u_long)*args.gnentries);
    165 	if (error)
    166 		return (error);
    167 
    168 #ifdef UMAP_DIAGNOSTIC
    169 	printf("umap_mount:gnentries %d\n",args.gnentries);
    170 	for (i = 0; i < args.gnentries; i++)
    171 		printf("\tgroup %d maps to %d\n",
    172 		    amp->info_gmapdata[i][0],
    173 	 	    amp->info_gmapdata[i][1]);
    174 #endif
    175 
    176 
    177 	/*
    178 	 * Save reference.  Each mount also holds
    179 	 * a reference on the root vnode.
    180 	 */
    181 	error = umap_node_create(mp, lowerrootvp, &vp);
    182 	/*
    183 	 * Unlock the node (either the lower or the alias)
    184 	 */
    185 	VOP_UNLOCK(vp, 0);
    186 	/*
    187 	 * Make sure the node alias worked
    188 	 */
    189 	if (error) {
    190 		vrele(lowerrootvp);
    191 		free(amp, M_UFSMNT);	/* XXX */
    192 		return (error);
    193 	}
    194 
    195 	/*
    196 	 * Keep a held reference to the root vnode.
    197 	 * It is vrele'd in umapfs_unmount.
    198 	 */
    199 	umapm_rootvp = vp;
    200 	umapm_rootvp->v_flag |= VROOT;
    201 	amp->umapm_rootvp = umapm_rootvp;
    202 	if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL)
    203 		mp->mnt_flag |= MNT_LOCAL;
    204 	mp->mnt_data = (qaddr_t) amp;
    205 	vfs_getnewfsid(mp, MOUNT_UMAP);
    206 
    207 	(void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
    208 	memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
    209 	(void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
    210 	    &size);
    211 	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
    212 #ifdef UMAPFS_DIAGNOSTIC
    213 	printf("umapfs_mount: lower %s, alias at %s\n",
    214 		mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
    215 #endif
    216 	return (0);
    217 }
    218 
    219 /*
    220  * VFS start.  Nothing needed here - the start routine
    221  * on the underlying filesystem will have been called
    222  * when that filesystem was mounted.
    223  */
    224 int
    225 umapfs_start(mp, flags, p)
    226 	struct mount *mp;
    227 	int flags;
    228 	struct proc *p;
    229 {
    230 
    231 	return (0);
    232 	/* return (VFS_START(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, flags, p)); */
    233 }
    234 
    235 /*
    236  * Free reference to umap layer
    237  */
    238 int
    239 umapfs_unmount(mp, mntflags, p)
    240 	struct mount *mp;
    241 	int mntflags;
    242 	struct proc *p;
    243 {
    244 	struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
    245 	int error;
    246 	int flags = 0;
    247 
    248 #ifdef UMAPFS_DIAGNOSTIC
    249 	printf("umapfs_unmount(mp = %p)\n", mp);
    250 #endif
    251 
    252 	if (mntflags & MNT_FORCE)
    253 		flags |= FORCECLOSE;
    254 
    255 	/*
    256 	 * Clear out buffer cache.  I don't think we
    257 	 * ever get anything cached at this level at the
    258 	 * moment, but who knows...
    259 	 */
    260 #ifdef notyet
    261 	mntflushbuf(mp, 0);
    262 	if (mntinvalbuf(mp, 1))
    263 		return (EBUSY);
    264 #endif
    265 	if (umapm_rootvp->v_usecount > 1)
    266 		return (EBUSY);
    267 	if ((error = vflush(mp, umapm_rootvp, flags)) != 0)
    268 		return (error);
    269 
    270 #ifdef UMAPFS_DIAGNOSTIC
    271 	vprint("alias root of lower", umapm_rootvp);
    272 #endif
    273 	/*
    274 	 * Release reference on underlying root vnode
    275 	 */
    276 	vrele(umapm_rootvp);
    277 	/*
    278 	 * And blow it away for future re-use
    279 	 */
    280 	vgone(umapm_rootvp);
    281 	/*
    282 	 * Finally, throw away the umap_mount structure
    283 	 */
    284 	free(mp->mnt_data, M_UFSMNT);	/* XXX */
    285 	mp->mnt_data = 0;
    286 	return (0);
    287 }
    288 
    289 int
    290 umapfs_root(mp, vpp)
    291 	struct mount *mp;
    292 	struct vnode **vpp;
    293 {
    294 	struct vnode *vp;
    295 
    296 #ifdef UMAPFS_DIAGNOSTIC
    297 	printf("umapfs_root(mp = %p, vp = %p->%p)\n", mp,
    298 	    MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
    299 	    UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
    300 #endif
    301 
    302 	/*
    303 	 * Return locked reference to root.
    304 	 */
    305 	vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp;
    306 	VREF(vp);
    307 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
    308 	*vpp = vp;
    309 	return (0);
    310 }
    311 
    312 int
    313 umapfs_quotactl(mp, cmd, uid, arg, p)
    314 	struct mount *mp;
    315 	int cmd;
    316 	uid_t uid;
    317 	caddr_t arg;
    318 	struct proc *p;
    319 {
    320 
    321 	return (VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p));
    322 }
    323 
    324 int
    325 umapfs_statfs(mp, sbp, p)
    326 	struct mount *mp;
    327 	struct statfs *sbp;
    328 	struct proc *p;
    329 {
    330 	int error;
    331 	struct statfs mstat;
    332 
    333 #ifdef UMAPFS_DIAGNOSTIC
    334 	printf("umapfs_statfs(mp = %p, vp = %p->%p)\n", mp,
    335 	    MOUNTTOUMAPMOUNT(mp)->umapm_rootvp,
    336 	    UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp));
    337 #endif
    338 
    339 	memset(&mstat, 0, sizeof(mstat));
    340 
    341 	error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p);
    342 	if (error)
    343 		return (error);
    344 
    345 	/* now copy across the "interesting" information and fake the rest */
    346 	sbp->f_type = mstat.f_type;
    347 	sbp->f_flags = mstat.f_flags;
    348 	sbp->f_bsize = mstat.f_bsize;
    349 	sbp->f_iosize = mstat.f_iosize;
    350 	sbp->f_blocks = mstat.f_blocks;
    351 	sbp->f_bfree = mstat.f_bfree;
    352 	sbp->f_bavail = mstat.f_bavail;
    353 	sbp->f_files = mstat.f_files;
    354 	sbp->f_ffree = mstat.f_ffree;
    355 	if (sbp != &mp->mnt_stat) {
    356 		memcpy(&sbp->f_fsid, &mp->mnt_stat.f_fsid, sizeof(sbp->f_fsid));
    357 		memcpy(sbp->f_mntonname, mp->mnt_stat.f_mntonname, MNAMELEN);
    358 		memcpy(sbp->f_mntfromname, mp->mnt_stat.f_mntfromname, MNAMELEN);
    359 	}
    360 	strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name, MFSNAMELEN);
    361 	return (0);
    362 }
    363 
    364 int
    365 umapfs_sync(mp, waitfor, cred, p)
    366 	struct mount *mp;
    367 	int waitfor;
    368 	struct ucred *cred;
    369 	struct proc *p;
    370 {
    371 
    372 	/*
    373 	 * XXX - Assumes no data cached at umap layer.
    374 	 */
    375 	return (0);
    376 }
    377 
    378 int
    379 umapfs_vget(mp, ino, vpp)
    380 	struct mount *mp;
    381 	ino_t ino;
    382 	struct vnode **vpp;
    383 {
    384 
    385 	return (VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp));
    386 }
    387 
    388 int
    389 umapfs_fhtovp(mp, fidp, nam, vpp, exflagsp, credanonp)
    390 	struct mount *mp;
    391 	struct fid *fidp;
    392 	struct mbuf *nam;
    393 	struct vnode **vpp;
    394 	int *exflagsp;
    395 	struct ucred**credanonp;
    396 {
    397 
    398 	return (EOPNOTSUPP);
    399 }
    400 
    401 int
    402 umapfs_vptofh(vp, fhp)
    403 	struct vnode *vp;
    404 	struct fid *fhp;
    405 {
    406 
    407 	return (EOPNOTSUPP);
    408 }
    409 
    410 int
    411 umapfs_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
    412 	int *name;
    413 	u_int namelen;
    414 	void *oldp;
    415 	size_t *oldlenp;
    416 	void *newp;
    417 	size_t newlen;
    418 	struct proc *p;
    419 {
    420 	return (EOPNOTSUPP);
    421 }
    422 
    423 extern struct vnodeopv_desc umapfs_vnodeop_opv_desc;
    424 
    425 struct vnodeopv_desc *umapfs_vnodeopv_descs[] = {
    426 	&umapfs_vnodeop_opv_desc,
    427 	NULL,
    428 };
    429 
    430 struct vfsops umapfs_vfsops = {
    431 	MOUNT_UMAP,
    432 	umapfs_mount,
    433 	umapfs_start,
    434 	umapfs_unmount,
    435 	umapfs_root,
    436 	umapfs_quotactl,
    437 	umapfs_statfs,
    438 	umapfs_sync,
    439 	umapfs_vget,
    440 	umapfs_fhtovp,
    441 	umapfs_vptofh,
    442 	umapfs_init,
    443 	umapfs_sysctl,
    444 	NULL,				/* vfs_mountroot */
    445 	umapfs_vnodeopv_descs,
    446 };
    447