mfs_vfsops.c revision 1.22
1/*	$NetBSD: mfs_vfsops.c,v 1.22 2000/01/21 23:43:10 thorpej Exp $	*/
2
3/*
4 * Copyright (c) 1989, 1990, 1993, 1994
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *	@(#)mfs_vfsops.c	8.11 (Berkeley) 6/19/95
36 */
37
38#if defined(_KERNEL) && !defined(_LKM)
39#include "opt_compat_netbsd.h"
40#endif
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/time.h>
45#include <sys/kernel.h>
46#include <sys/proc.h>
47#include <sys/buf.h>
48#include <sys/mount.h>
49#include <sys/signalvar.h>
50#include <sys/vnode.h>
51#include <sys/malloc.h>
52
53#include <ufs/ufs/quota.h>
54#include <ufs/ufs/inode.h>
55#include <ufs/ufs/ufsmount.h>
56#include <ufs/ufs/ufs_extern.h>
57
58#include <ufs/ffs/fs.h>
59#include <ufs/ffs/ffs_extern.h>
60
61#include <ufs/mfs/mfsnode.h>
62#include <ufs/mfs/mfs_extern.h>
63
64caddr_t	mfs_rootbase;	/* address of mini-root in kernel virtual memory */
65u_long	mfs_rootsize;	/* size of mini-root in bytes */
66
67static	int mfs_minor;	/* used for building internal dev_t */
68
69extern int (**mfs_vnodeop_p) __P((void *));
70
71/*
72 * mfs vfs operations.
73 */
74
75extern struct vnodeopv_desc mfs_vnodeop_opv_desc;
76
77struct vnodeopv_desc *mfs_vnodeopv_descs[] = {
78	&mfs_vnodeop_opv_desc,
79	NULL,
80};
81
82struct vfsops mfs_vfsops = {
83	MOUNT_MFS,
84	mfs_mount,
85	mfs_start,
86	ffs_unmount,
87	ufs_root,
88	ufs_quotactl,
89	mfs_statfs,
90	ffs_sync,
91	ffs_vget,
92	ffs_fhtovp,
93	ffs_vptofh,
94	mfs_init,
95	ffs_sysctl,
96	NULL,
97	ufs_check_export,
98	mfs_vnodeopv_descs,
99};
100
101/*
102 * Memory based filesystem initialization.
103 */
104void
105mfs_init()
106{
107}
108
109
110/*
111 * Called by main() when mfs is going to be mounted as root.
112 */
113
114int
115mfs_mountroot()
116{
117	extern struct vnode *rootvp;
118	struct fs *fs;
119	struct mount *mp;
120	struct proc *p = curproc;	/* XXX */
121	struct ufsmount *ump;
122	struct mfsnode *mfsp;
123	int error = 0;
124
125	/*
126	 * Get vnodes for rootdev.
127	 */
128	if (bdevvp(rootdev, &rootvp)) {
129		printf("mfs_mountroot: can't setup bdevvp's");
130		return (error);
131	}
132
133	if ((error = vfs_rootmountalloc(MOUNT_MFS, "mfs_root", &mp))) {
134		vrele(rootvp);
135		return (error);
136	}
137
138	mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
139	rootvp->v_data = mfsp;
140	rootvp->v_op = mfs_vnodeop_p;
141	rootvp->v_tag = VT_MFS;
142	mfsp->mfs_baseoff = mfs_rootbase;
143	mfsp->mfs_size = mfs_rootsize;
144	mfsp->mfs_vnode = rootvp;
145	mfsp->mfs_pid = p->p_pid;
146	BUFQ_INIT(&mfsp->mfs_buflist);
147	if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
148		mp->mnt_op->vfs_refcount--;
149		vfs_unbusy(mp);
150		free(mp, M_MOUNT);
151		free(mfsp, M_MFSNODE);
152		vrele(rootvp);
153		return (error);
154	}
155	simple_lock(&mountlist_slock);
156	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
157	simple_unlock(&mountlist_slock);
158	mp->mnt_vnodecovered = NULLVP;
159	ump = VFSTOUFS(mp);
160	fs = ump->um_fs;
161	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
162	(void)ffs_statfs(mp, &mp->mnt_stat, p);
163	vfs_unbusy(mp);
164	inittodr((time_t)0);
165	return (0);
166}
167
168/*
169 * This is called early in boot to set the base address and size
170 * of the mini-root.
171 */
172int
173mfs_initminiroot(base)
174	caddr_t base;
175{
176	struct fs *fs = (struct fs *)(base + SBOFF);
177	extern int (*mountroot) __P((void));
178
179	/* check for valid super block */
180	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
181	    fs->fs_bsize < sizeof(struct fs))
182		return (0);
183	mountroot = mfs_mountroot;
184	mfs_rootbase = base;
185	mfs_rootsize = fs->fs_fsize * fs->fs_size;
186	rootdev = makedev(255, mfs_minor++);
187	return (mfs_rootsize);
188}
189
190/*
191 * VFS Operations.
192 *
193 * mount system call
194 */
195/* ARGSUSED */
196int
197mfs_mount(mp, path, data, ndp, p)
198	register struct mount *mp;
199	const char *path;
200	void *data;
201	struct nameidata *ndp;
202	struct proc *p;
203{
204	struct vnode *devvp;
205	struct mfs_args args;
206	struct ufsmount *ump;
207	register struct fs *fs;
208	register struct mfsnode *mfsp;
209	size_t size;
210	int flags, error;
211
212	error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args));
213	if (error)
214		return (error);
215
216	/*
217	 * If updating, check whether changing from read-only to
218	 * read/write; if there is no device name, that's all we do.
219	 */
220	if (mp->mnt_flag & MNT_UPDATE) {
221		ump = VFSTOUFS(mp);
222		fs = ump->um_fs;
223		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
224			flags = WRITECLOSE;
225			if (mp->mnt_flag & MNT_FORCE)
226				flags |= FORCECLOSE;
227			error = ffs_flushfiles(mp, flags, p);
228			if (error)
229				return (error);
230		}
231		if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
232			fs->fs_ronly = 0;
233		if (args.fspec == 0)
234			return (vfs_export(mp, &ump->um_export, &args.export));
235		return (0);
236	}
237	error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
238	if (error)
239		return (error);
240	devvp->v_type = VBLK;
241	if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0))
242		panic("mfs_mount: dup dev");
243	mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
244	devvp->v_data = mfsp;
245	mfsp->mfs_baseoff = args.base;
246	mfsp->mfs_size = args.size;
247	mfsp->mfs_vnode = devvp;
248	mfsp->mfs_pid = p->p_pid;
249	BUFQ_INIT(&mfsp->mfs_buflist);
250	if ((error = ffs_mountfs(devvp, mp, p)) != 0) {
251		BUFQ_FIRST(&mfsp->mfs_buflist) = (struct buf *) -1;
252		vrele(devvp);
253		return (error);
254	}
255	ump = VFSTOUFS(mp);
256	fs = ump->um_fs;
257	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
258	memset(fs->fs_fsmnt + size, 0, sizeof(fs->fs_fsmnt) - size);
259	memcpy(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN);
260	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
261	    &size);
262	memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size);
263	return (0);
264}
265
266int	mfs_pri = PWAIT | PCATCH;		/* XXX prob. temp */
267
268/*
269 * Used to grab the process and keep it in the kernel to service
270 * memory filesystem I/O requests.
271 *
272 * Loop servicing I/O requests.
273 * Copy the requested data into or out of the memory filesystem
274 * address space.
275 */
276/* ARGSUSED */
277int
278mfs_start(mp, flags, p)
279	struct mount *mp;
280	int flags;
281	struct proc *p;
282{
283	register struct vnode *vp = VFSTOUFS(mp)->um_devvp;
284	register struct mfsnode *mfsp = VTOMFS(vp);
285	register struct buf *bp;
286	register caddr_t base;
287	int sleepreturn = 0;
288
289	base = mfsp->mfs_baseoff;
290	while (BUFQ_FIRST(&mfsp->mfs_buflist) != (struct buf *) -1) {
291		/*
292		 * If a non-ignored signal is received, try to unmount.
293		 * If that fails, or the filesystem is already in the
294		 * process of being unmounted, clear the signal (it has been
295		 * "processed"), otherwise we will loop here, as tsleep
296		 * will always return EINTR/ERESTART.
297		 */
298		if (sleepreturn != 0) {
299			if (vfs_busy(mp, LK_NOWAIT, 0) ||
300			    dounmount(mp, 0, p) != 0)
301				CLRSIG(p, CURSIG(p));
302			sleepreturn = 0;
303			continue;
304		}
305
306		while ((bp = BUFQ_FIRST(&mfsp->mfs_buflist)) != NULL) {
307			BUFQ_REMOVE(&mfsp->mfs_buflist, bp);
308			mfs_doio(bp, base);
309			wakeup((caddr_t)bp);
310		}
311		sleepreturn = tsleep(vp, mfs_pri, "mfsidl", 0);
312	}
313	return (sleepreturn);
314}
315
316/*
317 * Get file system statistics.
318 */
319int
320mfs_statfs(mp, sbp, p)
321	struct mount *mp;
322	struct statfs *sbp;
323	struct proc *p;
324{
325	int error;
326
327	error = ffs_statfs(mp, sbp, p);
328#ifdef COMPAT_09
329	sbp->f_type = 3;
330#else
331	sbp->f_type = 0;
332#endif
333	strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN);
334	return (error);
335}
336