mfs_vfsops.c revision 1.13
1/*	$NetBSD: mfs_vfsops.c,v 1.13 1997/06/12 17:15:00 mrg 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.4 (Berkeley) 4/16/94
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/time.h>
41#include <sys/kernel.h>
42#include <sys/proc.h>
43#include <sys/buf.h>
44#include <sys/mount.h>
45#include <sys/signalvar.h>
46#include <sys/vnode.h>
47#include <sys/malloc.h>
48
49#include <ufs/ufs/quota.h>
50#include <ufs/ufs/inode.h>
51#include <ufs/ufs/ufsmount.h>
52#include <ufs/ufs/ufs_extern.h>
53
54#include <ufs/ffs/fs.h>
55#include <ufs/ffs/ffs_extern.h>
56
57#include <ufs/mfs/mfsnode.h>
58#include <ufs/mfs/mfs_extern.h>
59
60caddr_t	mfs_rootbase;	/* address of mini-root in kernel virtual memory */
61u_long	mfs_rootsize;	/* size of mini-root in bytes */
62
63static	int mfs_minor;	/* used for building internal dev_t */
64
65extern int (**mfs_vnodeop_p) __P((void *));
66
67/*
68 * mfs vfs operations.
69 */
70struct vfsops mfs_vfsops = {
71	MOUNT_MFS,
72	mfs_mount,
73	mfs_start,
74	ffs_unmount,
75	ufs_root,
76	ufs_quotactl,
77	mfs_statfs,
78	ffs_sync,
79	ffs_vget,
80	ffs_fhtovp,
81	ffs_vptofh,
82	mfs_init,
83};
84
85/*
86 * Called by main() when mfs is going to be mounted as root.
87 *
88 * Name is updated by mount(8) after booting.
89 */
90#define ROOTNAME	"mfs_root"
91
92int
93mfs_mountroot()
94{
95	extern struct vnode *rootvp;
96	register struct fs *fs;
97	register struct mount *mp;
98	struct proc *p = curproc;	/* XXX */
99	struct ufsmount *ump;
100	struct mfsnode *mfsp;
101	size_t size;
102	int error;
103
104	/*
105	 * Get vnodes for rootdev.
106	 */
107	if (bdevvp(rootdev, &rootvp))
108		panic("mfs_mountroot: can't setup bdevvp's");
109
110	mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
111	bzero((char *)mp, (u_long)sizeof(struct mount));
112	mp->mnt_op = &mfs_vfsops;
113	mp->mnt_flag = MNT_RDONLY;
114	mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
115	rootvp->v_data = mfsp;
116	rootvp->v_op = mfs_vnodeop_p;
117	rootvp->v_tag = VT_MFS;
118	mfsp->mfs_baseoff = mfs_rootbase;
119	mfsp->mfs_size = mfs_rootsize;
120	mfsp->mfs_vnode = rootvp;
121	mfsp->mfs_pid = p->p_pid;
122	mfsp->mfs_buflist = (struct buf *)0;
123	if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
124		free(mp, M_MOUNT);
125		free(mfsp, M_MFSNODE);
126		return (error);
127	}
128	if ((error = vfs_lock(mp)) != 0) {
129		(void)ffs_unmount(mp, 0, p);
130		free(mp, M_MOUNT);
131		free(mfsp, M_MFSNODE);
132		return (error);
133	}
134	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
135	mp->mnt_vnodecovered = NULLVP;
136	ump = VFSTOUFS(mp);
137	fs = ump->um_fs;
138	bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
139	fs->fs_fsmnt[0] = '/';
140	bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
141	(void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
142	    &size);
143	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
144	(void)ffs_statfs(mp, &mp->mnt_stat, p);
145	vfs_unlock(mp);
146	inittodr((time_t)0);
147	return (0);
148}
149
150/*
151 * This is called early in boot to set the base address and size
152 * of the mini-root.
153 */
154int
155mfs_initminiroot(base)
156	caddr_t base;
157{
158	struct fs *fs = (struct fs *)(base + SBOFF);
159	extern int (*mountroot) __P((void));
160
161	/* check for valid super block */
162	if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
163	    fs->fs_bsize < sizeof(struct fs))
164		return (0);
165	mountroot = mfs_mountroot;
166	mfs_rootbase = base;
167	mfs_rootsize = fs->fs_fsize * fs->fs_size;
168	rootdev = makedev(255, mfs_minor++);
169	return (mfs_rootsize);
170}
171
172/*
173 * VFS Operations.
174 *
175 * mount system call
176 */
177/* ARGSUSED */
178int
179mfs_mount(mp, path, data, ndp, p)
180	register struct mount *mp;
181	const char *path;
182	void *data;
183	struct nameidata *ndp;
184	struct proc *p;
185{
186	struct vnode *devvp;
187	struct mfs_args args;
188	struct ufsmount *ump;
189	register struct fs *fs;
190	register struct mfsnode *mfsp;
191	size_t size;
192	int flags, error;
193
194	error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args));
195	if (error)
196		return (error);
197
198	/*
199	 * If updating, check whether changing from read-only to
200	 * read/write; if there is no device name, that's all we do.
201	 */
202	if (mp->mnt_flag & MNT_UPDATE) {
203		ump = VFSTOUFS(mp);
204		fs = ump->um_fs;
205		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
206			flags = WRITECLOSE;
207			if (mp->mnt_flag & MNT_FORCE)
208				flags |= FORCECLOSE;
209			if (vfs_busy(mp))
210				return (EBUSY);
211			error = ffs_flushfiles(mp, flags, p);
212			vfs_unbusy(mp);
213			if (error)
214				return (error);
215		}
216		if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
217			fs->fs_ronly = 0;
218#ifdef EXPORTMFS
219		if (args.fspec == 0)
220			return (vfs_export(mp, &ump->um_export, &args.export));
221#endif
222		return (0);
223	}
224	error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
225	if (error)
226		return (error);
227	devvp->v_type = VBLK;
228	if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0))
229		panic("mfs_mount: dup dev");
230	mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
231	devvp->v_data = mfsp;
232	mfsp->mfs_baseoff = args.base;
233	mfsp->mfs_size = args.size;
234	mfsp->mfs_vnode = devvp;
235	mfsp->mfs_pid = p->p_pid;
236	mfsp->mfs_buflist = (struct buf *)0;
237	if ((error = ffs_mountfs(devvp, mp, p)) != 0) {
238		mfsp->mfs_buflist = (struct buf *)-1;
239		vrele(devvp);
240		return (error);
241	}
242	ump = VFSTOUFS(mp);
243	fs = ump->um_fs;
244	(void) copyinstr(path, fs->fs_fsmnt, sizeof(fs->fs_fsmnt) - 1, &size);
245	bzero(fs->fs_fsmnt + size, sizeof(fs->fs_fsmnt) - size);
246	bcopy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname, MNAMELEN);
247	(void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
248	    &size);
249	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
250	return (0);
251}
252
253int	mfs_pri = PWAIT | PCATCH;		/* XXX prob. temp */
254
255/*
256 * Used to grab the process and keep it in the kernel to service
257 * memory filesystem I/O requests.
258 *
259 * Loop servicing I/O requests.
260 * Copy the requested data into or out of the memory filesystem
261 * address space.
262 */
263/* ARGSUSED */
264int
265mfs_start(mp, flags, p)
266	struct mount *mp;
267	int flags;
268	struct proc *p;
269{
270	register struct vnode *vp = VFSTOUFS(mp)->um_devvp;
271	register struct mfsnode *mfsp = VTOMFS(vp);
272	register struct buf *bp;
273	register caddr_t base;
274	int error = 0;
275
276	base = mfsp->mfs_baseoff;
277	while (mfsp->mfs_buflist != (struct buf *)-1) {
278		while ((bp = mfsp->mfs_buflist) != NULL) {
279			mfsp->mfs_buflist = bp->b_actf;
280			mfs_doio(bp, base);
281			wakeup((caddr_t)bp);
282		}
283		/*
284		 * If a non-ignored signal is received, try to unmount.
285		 * If that fails, clear the signal (it has been "processed"),
286		 * otherwise we will loop here, as tsleep will always return
287		 * EINTR/ERESTART.
288		 */
289		if (error == EINTR || error == ERESTART) {
290			if (vfs_busy(mp) == 0 && dounmount(mp, 0, p) != 0)
291				CLRSIG(p, CURSIG(p));
292			error = 0;
293			continue;
294		}
295		error = tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0);
296	}
297	return (error);
298}
299
300/*
301 * Get file system statistics.
302 */
303int
304mfs_statfs(mp, sbp, p)
305	struct mount *mp;
306	struct statfs *sbp;
307	struct proc *p;
308{
309	int error;
310
311	error = ffs_statfs(mp, sbp, p);
312#ifdef COMPAT_09
313	sbp->f_type = 3;
314#else
315	sbp->f_type = 0;
316#endif
317	strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN);
318	return (error);
319}
320