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
58int	umapfs_mount __P((struct mount *, const char *, void *,
59			  struct nameidata *, struct proc *));
60int	umapfs_start __P((struct mount *, int, struct proc *));
61int	umapfs_unmount __P((struct mount *, int, struct proc *));
62int	umapfs_root __P((struct mount *, struct vnode **));
63int	umapfs_quotactl __P((struct mount *, int, uid_t, caddr_t,
64			     struct proc *));
65int	umapfs_statfs __P((struct mount *, struct statfs *, struct proc *));
66int	umapfs_sync __P((struct mount *, int, struct ucred *, struct proc *));
67int	umapfs_vget __P((struct mount *, ino_t, struct vnode **));
68int	umapfs_fhtovp __P((struct mount *, struct fid *, struct mbuf *,
69			   struct vnode **, int *, struct ucred **));
70int	umapfs_vptofh __P((struct vnode *, struct fid *));
71int	umapfs_sysctl __P((int *, u_int, void *, size_t *, void *, size_t,
72			   struct proc *));
73
74/*
75 * Mount umap layer
76 */
77int
78umapfs_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 */
224int
225umapfs_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 */
238int
239umapfs_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
289int
290umapfs_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
312int
313umapfs_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
324int
325umapfs_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
364int
365umapfs_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
378int
379umapfs_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
388int
389umapfs_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
401int
402umapfs_vptofh(vp, fhp)
403	struct vnode *vp;
404	struct fid *fhp;
405{
406
407	return (EOPNOTSUPP);
408}
409
410int
411umapfs_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
423extern struct vnodeopv_desc umapfs_vnodeop_opv_desc;
424
425struct vnodeopv_desc *umapfs_vnodeopv_descs[] = {
426	&umapfs_vnodeop_opv_desc,
427	NULL,
428};
429
430struct 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