xref: /netbsd-src/sys/ufs/mfs/mfs_vfsops.c (revision 9ea3b23dafd978027b28369eda07bf00fb169b23)
1*9ea3b23dShannken /*	$NetBSD: mfs_vfsops.c,v 1.116 2022/03/19 13:53:33 hannken Exp $	*/
2fccfa11aScgd 
3264b874cSmycroft /*
4264b874cSmycroft  * Copyright (c) 1989, 1990, 1993, 1994
5264b874cSmycroft  *	The Regents of the University of California.  All rights reserved.
6264b874cSmycroft  *
7264b874cSmycroft  * Redistribution and use in source and binary forms, with or without
8264b874cSmycroft  * modification, are permitted provided that the following conditions
9264b874cSmycroft  * are met:
10264b874cSmycroft  * 1. Redistributions of source code must retain the above copyright
11264b874cSmycroft  *    notice, this list of conditions and the following disclaimer.
12264b874cSmycroft  * 2. Redistributions in binary form must reproduce the above copyright
13264b874cSmycroft  *    notice, this list of conditions and the following disclaimer in the
14264b874cSmycroft  *    documentation and/or other materials provided with the distribution.
15aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
16264b874cSmycroft  *    may be used to endorse or promote products derived from this software
17264b874cSmycroft  *    without specific prior written permission.
18264b874cSmycroft  *
19264b874cSmycroft  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20264b874cSmycroft  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21264b874cSmycroft  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22264b874cSmycroft  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23264b874cSmycroft  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24264b874cSmycroft  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25264b874cSmycroft  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26264b874cSmycroft  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27264b874cSmycroft  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28264b874cSmycroft  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29264b874cSmycroft  * SUCH DAMAGE.
30264b874cSmycroft  *
31e5bc90f4Sfvdl  *	@(#)mfs_vfsops.c	8.11 (Berkeley) 6/19/95
32264b874cSmycroft  */
33264b874cSmycroft 
34ec624546Slukem #include <sys/cdefs.h>
35*9ea3b23dShannken __KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.116 2022/03/19 13:53:33 hannken Exp $");
36ec624546Slukem 
3767afbd62Smrg #if defined(_KERNEL_OPT)
38d275e56dSjonathan #include "opt_compat_netbsd.h"
39d275e56dSjonathan #endif
40d275e56dSjonathan 
41264b874cSmycroft #include <sys/param.h>
42264b874cSmycroft #include <sys/systm.h>
4313f8d2ceSatatat #include <sys/sysctl.h>
44264b874cSmycroft #include <sys/time.h>
45264b874cSmycroft #include <sys/kernel.h>
46264b874cSmycroft #include <sys/proc.h>
47264b874cSmycroft #include <sys/buf.h>
4805f25dccSyamt #include <sys/bufq.h>
49264b874cSmycroft #include <sys/mount.h>
50264b874cSmycroft #include <sys/signalvar.h>
51264b874cSmycroft #include <sys/vnode.h>
52021b86ddSad #include <sys/kmem.h>
53a1221b6dSrumble #include <sys/module.h>
54264b874cSmycroft 
55717e1785Sdholland #include <miscfs/genfs/genfs.h>
5604177824Spooka #include <miscfs/specfs/specdev.h>
575b35dc81Sthorpej 
58264b874cSmycroft #include <ufs/ufs/quota.h>
59264b874cSmycroft #include <ufs/ufs/inode.h>
60264b874cSmycroft #include <ufs/ufs/ufsmount.h>
61264b874cSmycroft #include <ufs/ufs/ufs_extern.h>
62264b874cSmycroft 
63264b874cSmycroft #include <ufs/ffs/fs.h>
64264b874cSmycroft #include <ufs/ffs/ffs_extern.h>
65264b874cSmycroft 
66264b874cSmycroft #include <ufs/mfs/mfsnode.h>
67264b874cSmycroft #include <ufs/mfs/mfs_extern.h>
68264b874cSmycroft 
692f839a22Sad MODULE(MODULE_CLASS_VFS, mfs, "ffs");
70a1221b6dSrumble 
71021b86ddSad kmutex_t mfs_lock;	/* global lock */
72264b874cSmycroft 
73d6f18673Spooka /* used for building internal dev_t, minor == 0 reserved for miniroot */
742547f842Shannken static devminor_t mfs_minor = 1;
75021b86ddSad static int mfs_initcnt;
76264b874cSmycroft 
7723ebf62dSxtraeme extern int (**mfs_vnodeop_p)(void *);
78264b874cSmycroft 
79264b874cSmycroft /*
80264b874cSmycroft  * mfs vfs operations.
81264b874cSmycroft  */
82b5bf2ed6Sthorpej 
83d9466585Sjdolecek extern const struct vnodeopv_desc mfs_vnodeop_opv_desc;
84b5bf2ed6Sthorpej 
85d9466585Sjdolecek const struct vnodeopv_desc * const mfs_vnodeopv_descs[] = {
86b5bf2ed6Sthorpej 	&mfs_vnodeop_opv_desc,
87b5bf2ed6Sthorpej 	NULL,
88b5bf2ed6Sthorpej };
89b5bf2ed6Sthorpej 
90264b874cSmycroft struct vfsops mfs_vfsops = {
916d285189Shannken 	.vfs_name = MOUNT_MFS,
926d285189Shannken 	.vfs_min_mount_data = sizeof (struct mfs_args),
936d285189Shannken 	.vfs_mount = mfs_mount,
946d285189Shannken 	.vfs_start = mfs_start,
956d285189Shannken 	.vfs_unmount = ffs_unmount,
966d285189Shannken 	.vfs_root = ufs_root,
976d285189Shannken 	.vfs_quotactl = ufs_quotactl,
986d285189Shannken 	.vfs_statvfs = mfs_statvfs,
996d285189Shannken 	.vfs_sync = ffs_sync,
10042c8d67cShannken 	.vfs_vget = ufs_vget,
10142c8d67cShannken 	.vfs_loadvnode = ffs_loadvnode,
10254fa474eShannken 	.vfs_newvnode = ffs_newvnode,
1036d285189Shannken 	.vfs_fhtovp = ffs_fhtovp,
1046d285189Shannken 	.vfs_vptofh = ffs_vptofh,
1056d285189Shannken 	.vfs_init = mfs_init,
1066d285189Shannken 	.vfs_reinit = mfs_reinit,
1076d285189Shannken 	.vfs_done = mfs_done,
1086d285189Shannken 	.vfs_snapshot = (void *)eopnotsupp,
1096d285189Shannken 	.vfs_extattrctl = vfs_stdextattrctl,
110326db3aaShannken 	.vfs_suspendctl = genfs_suspendctl,
1116d285189Shannken 	.vfs_renamelock_enter = genfs_renamelock_enter,
1126d285189Shannken 	.vfs_renamelock_exit = genfs_renamelock_exit,
1136d285189Shannken 	.vfs_fsync = (void *)eopnotsupp,
1146d285189Shannken 	.vfs_opv_descs = mfs_vnodeopv_descs
115264b874cSmycroft };
116a1221b6dSrumble 
1179120d451Spgoyette SYSCTL_SETUP(mfs_sysctl_setup, "mfs sysctl")
118a1221b6dSrumble {
119a1221b6dSrumble 
1209120d451Spgoyette 	sysctl_createv(clog, 0, NULL, NULL,
12119af35fdSatatat 		       CTLFLAG_PERMANENT|CTLFLAG_ALIAS,
12253c62565Satatat 		       CTLTYPE_NODE, "mfs",
12353c62565Satatat 		       SYSCTL_DESCR("Memory based file system"),
12413f8d2ceSatatat 		       NULL, 1, NULL, 0,
12513f8d2ceSatatat 		       CTL_VFS, 3, CTL_EOL);
12613f8d2ceSatatat 	/*
12713f8d2ceSatatat 	 * XXX the "1" and the "3" above could be dynamic, thereby
12813f8d2ceSatatat 	 * eliminating one more instance of the "number to vfs"
12913f8d2ceSatatat 	 * mapping problem, but they are in order as taken from
13013f8d2ceSatatat 	 * sys/mount.h
13113f8d2ceSatatat 	 */
1329120d451Spgoyette }
1339120d451Spgoyette 
1349120d451Spgoyette static int
mfs_modcmd(modcmd_t cmd,void * arg)1359120d451Spgoyette mfs_modcmd(modcmd_t cmd, void *arg)
1369120d451Spgoyette {
1379120d451Spgoyette 	int error;
1389120d451Spgoyette 
1399120d451Spgoyette 	switch (cmd) {
1409120d451Spgoyette 	case MODULE_CMD_INIT:
1419120d451Spgoyette 		error = vfs_attach(&mfs_vfsops);
1429120d451Spgoyette 		if (error != 0)
1439120d451Spgoyette 			break;
14428f5ebd8Srumble 		break;
14528f5ebd8Srumble 	case MODULE_CMD_FINI:
14628f5ebd8Srumble 		error = vfs_detach(&mfs_vfsops);
14728f5ebd8Srumble 		if (error != 0)
14828f5ebd8Srumble 			break;
14928f5ebd8Srumble 		break;
15028f5ebd8Srumble 	default:
15128f5ebd8Srumble 		error = ENOTTY;
15228f5ebd8Srumble 		break;
15328f5ebd8Srumble 	}
15428f5ebd8Srumble 
15528f5ebd8Srumble 	return (error);
15613f8d2ceSatatat }
15713f8d2ceSatatat 
158264b874cSmycroft /*
159e5bc90f4Sfvdl  * Memory based filesystem initialization.
160264b874cSmycroft  */
161e5bc90f4Sfvdl void
mfs_init(void)16223ebf62dSxtraeme mfs_init(void)
163e5bc90f4Sfvdl {
164835b0326Spooka 
165021b86ddSad 	if (mfs_initcnt++ == 0) {
166021b86ddSad 		mutex_init(&mfs_lock, MUTEX_DEFAULT, IPL_NONE);
16703efc0b2Sjdolecek 		ffs_init();
168e5bc90f4Sfvdl 	}
169021b86ddSad }
170e5bc90f4Sfvdl 
17103efc0b2Sjdolecek void
mfs_reinit(void)17223ebf62dSxtraeme mfs_reinit(void)
173adf5d360Schs {
174021b86ddSad 
175adf5d360Schs 	ffs_reinit();
176adf5d360Schs }
177adf5d360Schs 
178adf5d360Schs void
mfs_done(void)17923ebf62dSxtraeme mfs_done(void)
18003efc0b2Sjdolecek {
181021b86ddSad 
182021b86ddSad 	if (--mfs_initcnt == 0) {
18303efc0b2Sjdolecek 		ffs_done();
184021b86ddSad 		mutex_destroy(&mfs_lock);
185021b86ddSad 	}
18603efc0b2Sjdolecek }
187e5bc90f4Sfvdl 
188e5bc90f4Sfvdl /*
189e5bc90f4Sfvdl  * Called by main() when mfs is going to be mounted as root.
190e5bc90f4Sfvdl  */
191264b874cSmycroft 
192573481f5Schristos int
mfs_mountroot(void)19323ebf62dSxtraeme mfs_mountroot(void)
194264b874cSmycroft {
195e5bc90f4Sfvdl 	struct fs *fs;
196e5bc90f4Sfvdl 	struct mount *mp;
19795e1ffb1Schristos 	struct lwp *l = curlwp;		/* XXX */
198264b874cSmycroft 	struct ufsmount *ump;
199264b874cSmycroft 	struct mfsnode *mfsp;
200e5bc90f4Sfvdl 	int error = 0;
201264b874cSmycroft 
202976aedb7Swrstuden 	if ((error = vfs_rootmountalloc(MOUNT_MFS, "mfs_root", &mp))) {
203976aedb7Swrstuden 		vrele(rootvp);
204e5bc90f4Sfvdl 		return (error);
205976aedb7Swrstuden 	}
206e5bc90f4Sfvdl 
207021b86ddSad 	mfsp = kmem_alloc(sizeof(*mfsp), KM_SLEEP);
208264b874cSmycroft 	rootvp->v_data = mfsp;
209264b874cSmycroft 	rootvp->v_op = mfs_vnodeop_p;
210264b874cSmycroft 	rootvp->v_tag = VT_MFS;
211264b874cSmycroft 	mfsp->mfs_baseoff = mfs_rootbase;
212264b874cSmycroft 	mfsp->mfs_size = mfs_rootsize;
213264b874cSmycroft 	mfsp->mfs_vnode = rootvp;
2146d7f14dcSthorpej 	mfsp->mfs_proc = NULL;		/* indicate kernel space */
215d4c062b4Shannken 	mfsp->mfs_shutdown = 0;
216021b86ddSad 	cv_init(&mfsp->mfs_cv, "mfs");
217021b86ddSad 	mfsp->mfs_refcnt = 1;
218aec75b1cSyamt 	bufq_alloc(&mfsp->mfs_buflist, "fcfs", 0);
21995e1ffb1Schristos 	if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
22020bb034fShannken 		vfs_unbusy(mp);
221aec75b1cSyamt 		bufq_free(mfsp->mfs_buflist);
222ebb8f73bShannken 		vfs_rele(mp);
223021b86ddSad 		kmem_free(mfsp, sizeof(*mfsp));
224264b874cSmycroft 		return (error);
225264b874cSmycroft 	}
2260b725b63Schristos 	mountlist_append(mp);
227264b874cSmycroft 	mp->mnt_vnodecovered = NULLVP;
228264b874cSmycroft 	ump = VFSTOUFS(mp);
229264b874cSmycroft 	fs = ump->um_fs;
230e5bc90f4Sfvdl 	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
23161e8303eSpooka 	(void)ffs_statvfs(mp, &mp->mnt_stat);
23220bb034fShannken 	vfs_unbusy(mp);
233264b874cSmycroft 	return (0);
234264b874cSmycroft }
235264b874cSmycroft 
236264b874cSmycroft /*
237264b874cSmycroft  * VFS Operations.
238264b874cSmycroft  *
239264b874cSmycroft  * mount system call
240264b874cSmycroft  */
241264b874cSmycroft /* ARGSUSED */
242264b874cSmycroft int
mfs_mount(struct mount * mp,const char * path,void * data,size_t * data_len)24361e8303eSpooka mfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
244264b874cSmycroft {
24561e8303eSpooka 	struct lwp *l = curlwp;
246264b874cSmycroft 	struct vnode *devvp;
2472721ab6cSdsl 	struct mfs_args *args = data;
248264b874cSmycroft 	struct ufsmount *ump;
249169ac5b3Saugustss 	struct fs *fs;
250169ac5b3Saugustss 	struct mfsnode *mfsp;
25195e1ffb1Schristos 	struct proc *p;
2522547f842Shannken 	devminor_t minor;
2532721ab6cSdsl 	int flags, error = 0;
2542721ab6cSdsl 
25523f76b6dSmaxv 	if (args == NULL)
25623f76b6dSmaxv 		return EINVAL;
2572721ab6cSdsl 	if (*data_len < sizeof *args)
2582721ab6cSdsl 		return EINVAL;
259264b874cSmycroft 
26095e1ffb1Schristos 	p = l->l_proc;
2616f3945a8Schristos 	if (mp->mnt_flag & MNT_GETARGS) {
2626f3945a8Schristos 		struct vnode *vp;
2636f3945a8Schristos 
2646f3945a8Schristos 		ump = VFSTOUFS(mp);
2656f3945a8Schristos 		if (ump == NULL)
2666f3945a8Schristos 			return EIO;
2676f3945a8Schristos 
2686f3945a8Schristos 		vp = ump->um_devvp;
2696f3945a8Schristos 		if (vp == NULL)
2706f3945a8Schristos 			return EIO;
2716f3945a8Schristos 
2726f3945a8Schristos 		mfsp = VTOMFS(vp);
2736f3945a8Schristos 		if (mfsp == NULL)
2746f3945a8Schristos 			return EIO;
2756f3945a8Schristos 
2762721ab6cSdsl 		args->fspec = NULL;
2772721ab6cSdsl 		args->base = mfsp->mfs_baseoff;
2782721ab6cSdsl 		args->size = mfsp->mfs_size;
2792721ab6cSdsl 		*data_len = sizeof *args;
2802721ab6cSdsl 		return 0;
2816f3945a8Schristos 	}
282eecf9e20Schs 	/*
283eecf9e20Schs 	 * XXX turn off async to avoid hangs when writing lots of data.
284eecf9e20Schs 	 * the problem is that MFS needs to allocate pages to clean pages,
285eecf9e20Schs 	 * so if we wait until the last minute to clean pages then there
286eecf9e20Schs 	 * may not be any pages available to do the cleaning.
287ea6ddab6Schs 	 * ... and since the default partially-synchronous mode turns out
288ea6ddab6Schs 	 * to not be sufficient under heavy load, make it full synchronous.
289eecf9e20Schs 	 */
290eecf9e20Schs 	mp->mnt_flag &= ~MNT_ASYNC;
291ea6ddab6Schs 	mp->mnt_flag |= MNT_SYNCHRONOUS;
292eecf9e20Schs 
293264b874cSmycroft 	/*
294264b874cSmycroft 	 * If updating, check whether changing from read-only to
295264b874cSmycroft 	 * read/write; if there is no device name, that's all we do.
296264b874cSmycroft 	 */
297264b874cSmycroft 	if (mp->mnt_flag & MNT_UPDATE) {
298264b874cSmycroft 		ump = VFSTOUFS(mp);
299264b874cSmycroft 		fs = ump->um_fs;
300264b874cSmycroft 		if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
301264b874cSmycroft 			flags = WRITECLOSE;
302264b874cSmycroft 			if (mp->mnt_flag & MNT_FORCE)
303264b874cSmycroft 				flags |= FORCECLOSE;
30495e1ffb1Schristos 			error = ffs_flushfiles(mp, flags, l);
305264b874cSmycroft 			if (error)
306264b874cSmycroft 				return (error);
307264b874cSmycroft 		}
308fe7c7868Sdbj 		if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR))
309264b874cSmycroft 			fs->fs_ronly = 0;
3102721ab6cSdsl 		if (args->fspec == NULL)
3112a3e5eebSjmmv 			return EINVAL;
312264b874cSmycroft 		return (0);
313264b874cSmycroft 	}
3142547f842Shannken 	mutex_enter(&mfs_lock);
3152547f842Shannken 	minor = mfs_minor++;
3162547f842Shannken 	mutex_exit(&mfs_lock);
3172547f842Shannken 	error = bdevvp(makedev(255, minor), &devvp);
318264b874cSmycroft 	if (error)
319264b874cSmycroft 		return (error);
320021b86ddSad 	mfsp = kmem_alloc(sizeof(*mfsp), KM_SLEEP);
3212547f842Shannken 	/*
3222547f842Shannken 	 * Changing v_op and v_data here is safe as we are
3232547f842Shannken 	 * the exclusive owner of this device node.
3242547f842Shannken 	 */
3252547f842Shannken 	KASSERT(devvp->v_op == spec_vnodeop_p);
3262547f842Shannken 	KASSERT(devvp->v_data == NULL);
3272547f842Shannken 	devvp->v_op = mfs_vnodeop_p;
328264b874cSmycroft 	devvp->v_data = mfsp;
3292721ab6cSdsl 	mfsp->mfs_baseoff = args->base;
3302721ab6cSdsl 	mfsp->mfs_size = args->size;
331264b874cSmycroft 	mfsp->mfs_vnode = devvp;
3326d7f14dcSthorpej 	mfsp->mfs_proc = p;
333d4c062b4Shannken 	mfsp->mfs_shutdown = 0;
334110d5cc2Sad 	cv_init(&mfsp->mfs_cv, "mfsidl");
335021b86ddSad 	mfsp->mfs_refcnt = 1;
336aec75b1cSyamt 	bufq_alloc(&mfsp->mfs_buflist, "fcfs", 0);
33795e1ffb1Schristos 	if ((error = ffs_mountfs(devvp, mp, l)) != 0) {
338d4c062b4Shannken 		mfsp->mfs_shutdown = 1;
339264b874cSmycroft 		vrele(devvp);
340264b874cSmycroft 		return (error);
341264b874cSmycroft 	}
342264b874cSmycroft 	ump = VFSTOUFS(mp);
343264b874cSmycroft 	fs = ump->um_fs;
3442721ab6cSdsl 	error = set_statvfs_info(path, UIO_USERSPACE, args->fspec,
345e24b0872Spooka 	    UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l);
3460b9201b1Schristos 	if (error)
34780ecd573Schristos 		return error;
3480b9201b1Schristos 	(void)strncpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
3490b9201b1Schristos 		sizeof(fs->fs_fsmnt));
3500b9201b1Schristos 	fs->fs_fsmnt[sizeof(fs->fs_fsmnt) - 1] = '\0';
3510b9201b1Schristos 	/* XXX: cleanup on error */
3520b9201b1Schristos 	return 0;
353264b874cSmycroft }
354264b874cSmycroft 
355264b874cSmycroft /*
356264b874cSmycroft  * Used to grab the process and keep it in the kernel to service
357264b874cSmycroft  * memory filesystem I/O requests.
358264b874cSmycroft  *
3595026e056Sthorpej  * Loop servicing I/O requests.
3605026e056Sthorpej  * Copy the requested data into or out of the memory filesystem
3615026e056Sthorpej  * address space.
362264b874cSmycroft  */
363264b874cSmycroft /* ARGSUSED */
364264b874cSmycroft int
mfs_start(struct mount * mp,int flags)36561e8303eSpooka mfs_start(struct mount *mp, int flags)
366264b874cSmycroft {
367021b86ddSad 	struct vnode *vp;
368021b86ddSad 	struct mfsnode *mfsp;
369b07ec3fcSad 	struct proc *p;
3705026e056Sthorpej 	struct buf *bp;
37153524e44Schristos 	void *base;
372021b86ddSad 	int sleepreturn = 0, refcnt, error;
373b07ec3fcSad 	ksiginfoq_t kq;
374264b874cSmycroft 
375021b86ddSad 	/*
376021b86ddSad 	 * Ensure that file system is still mounted when getting mfsnode.
377021b86ddSad 	 * Add a reference to the mfsnode to prevent it disappearing in
378021b86ddSad 	 * this routine.
379021b86ddSad 	 */
38020bb034fShannken 	if ((error = vfs_busy(mp)) != 0)
381021b86ddSad 		return error;
382021b86ddSad 	vp = VFSTOUFS(mp)->um_devvp;
383021b86ddSad 	mfsp = VTOMFS(vp);
384021b86ddSad 	mutex_enter(&mfs_lock);
385021b86ddSad 	mfsp->mfs_refcnt++;
386021b86ddSad 	mutex_exit(&mfs_lock);
38720bb034fShannken 	vfs_unbusy(mp);
388021b86ddSad 
3895026e056Sthorpej 	base = mfsp->mfs_baseoff;
390021b86ddSad 	mutex_enter(&mfs_lock);
391d4c062b4Shannken 	while (mfsp->mfs_shutdown != 1) {
39270de9736Syamt 		while ((bp = bufq_get(mfsp->mfs_buflist)) != NULL) {
393021b86ddSad 			mutex_exit(&mfs_lock);
394ec25ea9fSsimonb 			mfs_doio(bp, base);
395021b86ddSad 			mutex_enter(&mfs_lock);
396ec25ea9fSsimonb 		}
397e5bc90f4Sfvdl 		/*
398e5bc90f4Sfvdl 		 * If a non-ignored signal is received, try to unmount.
399e5bc90f4Sfvdl 		 * If that fails, or the filesystem is already in the
400e5bc90f4Sfvdl 		 * process of being unmounted, clear the signal (it has been
401e5bc90f4Sfvdl 		 * "processed"), otherwise we will loop here, as tsleep
402e5bc90f4Sfvdl 		 * will always return EINTR/ERESTART.
403e5bc90f4Sfvdl 		 */
404e5bc90f4Sfvdl 		if (sleepreturn != 0) {
405021b86ddSad 			mutex_exit(&mfs_lock);
40642d06267Sad 			if (dounmount(mp, 0, curlwp) != 0) {
407021b86ddSad 				p = curproc;
408b07ec3fcSad 				ksiginfo_queue_init(&kq);
409284c2b9aSad 				mutex_enter(p->p_lock);
410b07ec3fcSad 				sigclearall(p, NULL, &kq);
411284c2b9aSad 				mutex_exit(p->p_lock);
412b07ec3fcSad 				ksiginfo_queue_drain(&kq);
413b07ec3fcSad 			}
414e5bc90f4Sfvdl 			sleepreturn = 0;
415021b86ddSad 			mutex_enter(&mfs_lock);
416e5bc90f4Sfvdl 			continue;
417e5bc90f4Sfvdl 		}
4185026e056Sthorpej 
419021b86ddSad 		sleepreturn = cv_wait_sig(&mfsp->mfs_cv, &mfs_lock);
420264b874cSmycroft 	}
42170de9736Syamt 	KASSERT(bufq_peek(mfsp->mfs_buflist) == NULL);
422021b86ddSad 	refcnt = --mfsp->mfs_refcnt;
423021b86ddSad 	mutex_exit(&mfs_lock);
424021b86ddSad 	if (refcnt == 0) {
425aec75b1cSyamt 		bufq_free(mfsp->mfs_buflist);
426021b86ddSad 		cv_destroy(&mfsp->mfs_cv);
427021b86ddSad 		kmem_free(mfsp, sizeof(*mfsp));
428021b86ddSad 	}
429e5bc90f4Sfvdl 	return (sleepreturn);
430264b874cSmycroft }
431264b874cSmycroft 
432264b874cSmycroft /*
433264b874cSmycroft  * Get file system statistics.
434264b874cSmycroft  */
435573481f5Schristos int
mfs_statvfs(struct mount * mp,struct statvfs * sbp)43661e8303eSpooka mfs_statvfs(struct mount *mp, struct statvfs *sbp)
437264b874cSmycroft {
438264b874cSmycroft 	int error;
439264b874cSmycroft 
44061e8303eSpooka 	error = ffs_statvfs(mp, sbp);
4410b9201b1Schristos 	if (error)
4420b9201b1Schristos 		return error;
4430b9201b1Schristos 	(void)strncpy(sbp->f_fstypename, mp->mnt_op->vfs_name,
4440b9201b1Schristos 	    sizeof(sbp->f_fstypename));
4450b9201b1Schristos 	sbp->f_fstypename[sizeof(sbp->f_fstypename) - 1] = '\0';
4460b9201b1Schristos 	return 0;
447264b874cSmycroft }
448