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