xref: /dflybsd-src/sys/vfs/hammer/hammer_vfsops.c (revision d26d0ae9b763bc95e7517d9825f5488bd3e53e67)
1427e5fc6SMatthew Dillon /*
2427e5fc6SMatthew Dillon  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3427e5fc6SMatthew Dillon  *
4427e5fc6SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5427e5fc6SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6427e5fc6SMatthew Dillon  *
7427e5fc6SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8427e5fc6SMatthew Dillon  * modification, are permitted provided that the following conditions
9427e5fc6SMatthew Dillon  * are met:
10427e5fc6SMatthew Dillon  *
11427e5fc6SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12427e5fc6SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13427e5fc6SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14427e5fc6SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15427e5fc6SMatthew Dillon  *    the documentation and/or other materials provided with the
16427e5fc6SMatthew Dillon  *    distribution.
17427e5fc6SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18427e5fc6SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19427e5fc6SMatthew Dillon  *    from this software without specific, prior written permission.
20427e5fc6SMatthew Dillon  *
21427e5fc6SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22427e5fc6SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23427e5fc6SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24427e5fc6SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25427e5fc6SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26427e5fc6SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27427e5fc6SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28427e5fc6SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29427e5fc6SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30427e5fc6SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31427e5fc6SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32427e5fc6SMatthew Dillon  * SUCH DAMAGE.
33427e5fc6SMatthew Dillon  *
34*d26d0ae9SMatthew Dillon  * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.10 2007/12/29 09:01:27 dillon Exp $
35427e5fc6SMatthew Dillon  */
36427e5fc6SMatthew Dillon 
37427e5fc6SMatthew Dillon #include <sys/param.h>
38427e5fc6SMatthew Dillon #include <sys/systm.h>
39427e5fc6SMatthew Dillon #include <sys/kernel.h>
40427e5fc6SMatthew Dillon #include <sys/vnode.h>
41427e5fc6SMatthew Dillon #include <sys/mount.h>
42427e5fc6SMatthew Dillon #include <sys/malloc.h>
43427e5fc6SMatthew Dillon #include <sys/nlookup.h>
44427e5fc6SMatthew Dillon #include <sys/fcntl.h>
45427e5fc6SMatthew Dillon #include <sys/buf.h>
46427e5fc6SMatthew Dillon #include <sys/buf2.h>
47427e5fc6SMatthew Dillon #include "hammer.h"
48427e5fc6SMatthew Dillon 
49427e5fc6SMatthew Dillon /*
50427e5fc6SMatthew Dillon  * VFS ABI
51427e5fc6SMatthew Dillon  */
52427e5fc6SMatthew Dillon static void	hammer_free_hmp(struct mount *mp);
53427e5fc6SMatthew Dillon 
54427e5fc6SMatthew Dillon static int	hammer_vfs_mount(struct mount *mp, char *path, caddr_t data,
55427e5fc6SMatthew Dillon 				struct ucred *cred);
56427e5fc6SMatthew Dillon static int	hammer_vfs_unmount(struct mount *mp, int mntflags);
57427e5fc6SMatthew Dillon static int	hammer_vfs_root(struct mount *mp, struct vnode **vpp);
58427e5fc6SMatthew Dillon static int	hammer_vfs_statfs(struct mount *mp, struct statfs *sbp,
59427e5fc6SMatthew Dillon 				struct ucred *cred);
60427e5fc6SMatthew Dillon static int	hammer_vfs_sync(struct mount *mp, int waitfor);
61427e5fc6SMatthew Dillon static int	hammer_vfs_init(struct vfsconf *conf);
62427e5fc6SMatthew Dillon 
63427e5fc6SMatthew Dillon static struct vfsops hammer_vfsops = {
64427e5fc6SMatthew Dillon 	.vfs_mount	= hammer_vfs_mount,
65427e5fc6SMatthew Dillon 	.vfs_unmount	= hammer_vfs_unmount,
66427e5fc6SMatthew Dillon 	.vfs_root 	= hammer_vfs_root,
67427e5fc6SMatthew Dillon 	.vfs_statfs	= hammer_vfs_statfs,
68427e5fc6SMatthew Dillon 	.vfs_sync	= hammer_vfs_sync,
69427e5fc6SMatthew Dillon 	.vfs_vget	= hammer_vfs_vget,
70427e5fc6SMatthew Dillon 	.vfs_init	= hammer_vfs_init
71427e5fc6SMatthew Dillon };
72427e5fc6SMatthew Dillon 
73427e5fc6SMatthew Dillon MALLOC_DEFINE(M_HAMMER, "hammer-mount", "hammer mount");
74427e5fc6SMatthew Dillon 
75427e5fc6SMatthew Dillon VFS_SET(hammer_vfsops, hammer, 0);
76427e5fc6SMatthew Dillon MODULE_VERSION(hammer, 1);
77427e5fc6SMatthew Dillon 
78427e5fc6SMatthew Dillon static int
79427e5fc6SMatthew Dillon hammer_vfs_init(struct vfsconf *conf)
80427e5fc6SMatthew Dillon {
81427e5fc6SMatthew Dillon 	hammer_init_alist_config();
82427e5fc6SMatthew Dillon 	return(0);
83427e5fc6SMatthew Dillon }
84427e5fc6SMatthew Dillon 
85427e5fc6SMatthew Dillon static int
86427e5fc6SMatthew Dillon hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data,
87427e5fc6SMatthew Dillon 		 struct ucred *cred)
88427e5fc6SMatthew Dillon {
89427e5fc6SMatthew Dillon 	struct hammer_mount_info info;
90a89aec1bSMatthew Dillon 	hammer_mount_t hmp;
91a89aec1bSMatthew Dillon 	hammer_volume_t rootvol;
9227ea2398SMatthew Dillon 	struct vnode *rootvp;
93427e5fc6SMatthew Dillon 	const char *upath;	/* volume name in userspace */
94427e5fc6SMatthew Dillon 	char *path;		/* volume name in system space */
95427e5fc6SMatthew Dillon 	int error;
96427e5fc6SMatthew Dillon 	int i;
97427e5fc6SMatthew Dillon 
98427e5fc6SMatthew Dillon 	if ((error = copyin(data, &info, sizeof(info))) != 0)
99427e5fc6SMatthew Dillon 		return (error);
100427e5fc6SMatthew Dillon 	if (info.nvolumes <= 0 || info.nvolumes >= 32768)
101427e5fc6SMatthew Dillon 		return (EINVAL);
102427e5fc6SMatthew Dillon 
103427e5fc6SMatthew Dillon 	/*
104427e5fc6SMatthew Dillon 	 * Interal mount data structure
105427e5fc6SMatthew Dillon 	 */
106195c19a1SMatthew Dillon 	if (mp->mnt_flag & MNT_UPDATE) {
107195c19a1SMatthew Dillon 		hmp = (void *)mp->mnt_data;
108195c19a1SMatthew Dillon 		KKASSERT(hmp != NULL);
109195c19a1SMatthew Dillon 	} else {
110427e5fc6SMatthew Dillon 		hmp = kmalloc(sizeof(*hmp), M_HAMMER, M_WAITOK | M_ZERO);
111427e5fc6SMatthew Dillon 		mp->mnt_data = (qaddr_t)hmp;
112427e5fc6SMatthew Dillon 		hmp->mp = mp;
113195c19a1SMatthew Dillon 		hmp->zbuf = kmalloc(HAMMER_BUFSIZE, M_HAMMER, M_WAITOK|M_ZERO);
114195c19a1SMatthew Dillon 		hmp->namekey_iterator = mycpu->gd_time_seconds;
115195c19a1SMatthew Dillon 	}
116195c19a1SMatthew Dillon 	hmp->hflags = info.hflags;
1177f7c1f84SMatthew Dillon 	if (info.asof) {
1187f7c1f84SMatthew Dillon 		mp->mnt_flag |= MNT_RDONLY;
1197f7c1f84SMatthew Dillon 		hmp->asof = info.asof;
1207f7c1f84SMatthew Dillon 	} else {
1217f7c1f84SMatthew Dillon 		hmp->asof = HAMMER_MAX_TID;
1227f7c1f84SMatthew Dillon 	}
123195c19a1SMatthew Dillon 
124195c19a1SMatthew Dillon 	/*
125195c19a1SMatthew Dillon 	 * Re-open read-write if originally read-only, or vise-versa XXX
126195c19a1SMatthew Dillon 	 */
127195c19a1SMatthew Dillon 	if (mp->mnt_flag & MNT_UPDATE) {
128195c19a1SMatthew Dillon 		if (hmp->ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
129195c19a1SMatthew Dillon 			kprintf("HAMMER read-write -> read-only XXX\n");
130195c19a1SMatthew Dillon 			hmp->ronly = 1;
131195c19a1SMatthew Dillon 		} else if (hmp->ronly && (mp->mnt_flag & MNT_RDONLY) == 0) {
132195c19a1SMatthew Dillon 			kprintf("HAMMER read-only -> read-write XXX\n");
133195c19a1SMatthew Dillon 			hmp->ronly = 0;
134195c19a1SMatthew Dillon 		}
135195c19a1SMatthew Dillon 		return(0);
136195c19a1SMatthew Dillon 	}
137195c19a1SMatthew Dillon 
138427e5fc6SMatthew Dillon 	RB_INIT(&hmp->rb_vols_root);
139427e5fc6SMatthew Dillon 	RB_INIT(&hmp->rb_inos_root);
140195c19a1SMatthew Dillon 	hmp->ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
141427e5fc6SMatthew Dillon 
142427e5fc6SMatthew Dillon 	/*
143427e5fc6SMatthew Dillon 	 * Load volumes
144427e5fc6SMatthew Dillon 	 */
145427e5fc6SMatthew Dillon 	path = objcache_get(namei_oc, M_WAITOK);
146*d26d0ae9SMatthew Dillon 	hmp->nvolumes = info.nvolumes;
147427e5fc6SMatthew Dillon 	for (i = 0; i < info.nvolumes; ++i) {
148427e5fc6SMatthew Dillon 		error = copyin(&info.volumes[i], &upath, sizeof(char *));
149427e5fc6SMatthew Dillon 		if (error == 0)
150427e5fc6SMatthew Dillon 			error = copyinstr(upath, path, MAXPATHLEN, NULL);
151427e5fc6SMatthew Dillon 		if (error == 0)
1528cd0a023SMatthew Dillon 			error = hammer_install_volume(hmp, path);
153427e5fc6SMatthew Dillon 		if (error)
154427e5fc6SMatthew Dillon 			break;
155427e5fc6SMatthew Dillon 	}
156427e5fc6SMatthew Dillon 	objcache_put(namei_oc, path);
157427e5fc6SMatthew Dillon 
158427e5fc6SMatthew Dillon 	/*
159427e5fc6SMatthew Dillon 	 * Make sure we found a root volume
160427e5fc6SMatthew Dillon 	 */
161427e5fc6SMatthew Dillon 	if (error == 0 && hmp->rootvol == NULL) {
162427e5fc6SMatthew Dillon 		kprintf("hammer_mount: No root volume found!\n");
163427e5fc6SMatthew Dillon 		error = EINVAL;
164427e5fc6SMatthew Dillon 	}
165427e5fc6SMatthew Dillon 	if (error == 0 && hmp->rootcl == NULL) {
166427e5fc6SMatthew Dillon 		kprintf("hammer_mount: No root cluster found!\n");
167427e5fc6SMatthew Dillon 		error = EINVAL;
168427e5fc6SMatthew Dillon 	}
169427e5fc6SMatthew Dillon 	if (error) {
170427e5fc6SMatthew Dillon 		hammer_free_hmp(mp);
171427e5fc6SMatthew Dillon 		return (error);
172427e5fc6SMatthew Dillon 	}
173427e5fc6SMatthew Dillon 
174427e5fc6SMatthew Dillon 	/*
17527ea2398SMatthew Dillon 	 * No errors, setup enough of the mount point so we can lookup the
17627ea2398SMatthew Dillon 	 * root vnode.
177427e5fc6SMatthew Dillon 	 */
178427e5fc6SMatthew Dillon 	mp->mnt_iosize_max = MAXPHYS;
179427e5fc6SMatthew Dillon 	mp->mnt_kern_flag |= MNTK_FSMID;
180427e5fc6SMatthew Dillon 	mp->mnt_stat.f_fsid.val[0] = 0;	/* XXX */
181427e5fc6SMatthew Dillon 	mp->mnt_stat.f_fsid.val[1] = 0;	/* XXX */
182c0ade690SMatthew Dillon 
183c0ade690SMatthew Dillon 	/*
184c0ade690SMatthew Dillon 	 * note: f_iosize is used by vnode_pager_haspage() when constructing
185c0ade690SMatthew Dillon 	 * its VOP_BMAP call.
186c0ade690SMatthew Dillon 	 */
187c0ade690SMatthew Dillon 	mp->mnt_stat.f_iosize = HAMMER_BUFSIZE;
188fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bsize = HAMMER_BUFSIZE;
189427e5fc6SMatthew Dillon 	vfs_getnewfsid(mp);		/* XXX */
190427e5fc6SMatthew Dillon 	mp->mnt_maxsymlinklen = 255;
191427e5fc6SMatthew Dillon 	mp->mnt_flag |= MNT_LOCAL;
192427e5fc6SMatthew Dillon 
193427e5fc6SMatthew Dillon 	vfs_add_vnodeops(mp, &hammer_vnode_vops, &mp->mnt_vn_norm_ops);
19427ea2398SMatthew Dillon 
19527ea2398SMatthew Dillon 	/*
196a89aec1bSMatthew Dillon 	 * The root volume's ondisk pointer is only valid if we hold a
197a89aec1bSMatthew Dillon 	 * reference to it.
198a89aec1bSMatthew Dillon 	 */
199a89aec1bSMatthew Dillon 	rootvol = hammer_get_root_volume(hmp, &error);
200a89aec1bSMatthew Dillon 	if (error)
201a89aec1bSMatthew Dillon 		goto done;
202a89aec1bSMatthew Dillon 	ksnprintf(mp->mnt_stat.f_mntfromname,
203a89aec1bSMatthew Dillon 		  sizeof(mp->mnt_stat.f_mntfromname), "%s",
204a89aec1bSMatthew Dillon 		  rootvol->ondisk->vol_name);
205a89aec1bSMatthew Dillon 	hammer_rel_volume(rootvol, 0);
206a89aec1bSMatthew Dillon 
207a89aec1bSMatthew Dillon 	/*
20827ea2398SMatthew Dillon 	 * Locate the root directory using the root cluster's B-Tree as a
20927ea2398SMatthew Dillon 	 * starting point.  The root directory uses an obj_id of 1.
21027ea2398SMatthew Dillon 	 *
21127ea2398SMatthew Dillon 	 * FUTURE: Leave the root directory cached referenced but unlocked
21227ea2398SMatthew Dillon 	 * in hmp->rootvp (need to flush it on unmount).
21327ea2398SMatthew Dillon 	 */
21427ea2398SMatthew Dillon 	error = hammer_vfs_vget(mp, 1, &rootvp);
215a89aec1bSMatthew Dillon 	if (error)
216a89aec1bSMatthew Dillon 		goto done;
21727ea2398SMatthew Dillon 	vput(rootvp);
21827ea2398SMatthew Dillon 	/*vn_unlock(hmp->rootvp);*/
21927ea2398SMatthew Dillon 
220a89aec1bSMatthew Dillon done:
22127ea2398SMatthew Dillon 	/*
22227ea2398SMatthew Dillon 	 * Cleanup and return.
22327ea2398SMatthew Dillon 	 */
22427ea2398SMatthew Dillon 	if (error)
22527ea2398SMatthew Dillon 		hammer_free_hmp(mp);
226427e5fc6SMatthew Dillon 	return (error);
227427e5fc6SMatthew Dillon }
228427e5fc6SMatthew Dillon 
229427e5fc6SMatthew Dillon static int
230427e5fc6SMatthew Dillon hammer_vfs_unmount(struct mount *mp, int mntflags)
231427e5fc6SMatthew Dillon {
232427e5fc6SMatthew Dillon #if 0
233427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
234427e5fc6SMatthew Dillon #endif
235427e5fc6SMatthew Dillon 	int flags;
23666325755SMatthew Dillon 	int error;
23727ea2398SMatthew Dillon 
23827ea2398SMatthew Dillon 	/*
239427e5fc6SMatthew Dillon 	 * Clean out the vnodes
240427e5fc6SMatthew Dillon 	 */
24166325755SMatthew Dillon 	flags = 0;
24266325755SMatthew Dillon 	if (mntflags & MNT_FORCE)
24366325755SMatthew Dillon 		flags |= FORCECLOSE;
24466325755SMatthew Dillon 	if ((error = vflush(mp, 0, flags)) != 0)
24566325755SMatthew Dillon 		return (error);
246427e5fc6SMatthew Dillon 
247427e5fc6SMatthew Dillon 	/*
248427e5fc6SMatthew Dillon 	 * Clean up the internal mount structure and related entities.  This
249427e5fc6SMatthew Dillon 	 * may issue I/O.
250427e5fc6SMatthew Dillon 	 */
251427e5fc6SMatthew Dillon 	hammer_free_hmp(mp);
252427e5fc6SMatthew Dillon 	return(0);
253427e5fc6SMatthew Dillon }
254427e5fc6SMatthew Dillon 
255427e5fc6SMatthew Dillon /*
256427e5fc6SMatthew Dillon  * Clean up the internal mount structure and disassociate it from the mount.
257427e5fc6SMatthew Dillon  * This may issue I/O.
258427e5fc6SMatthew Dillon  */
259427e5fc6SMatthew Dillon static void
260427e5fc6SMatthew Dillon hammer_free_hmp(struct mount *mp)
261427e5fc6SMatthew Dillon {
262427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
263427e5fc6SMatthew Dillon 
26427ea2398SMatthew Dillon #if 0
265427e5fc6SMatthew Dillon 	/*
266427e5fc6SMatthew Dillon 	 * Clean up the root vnode
267427e5fc6SMatthew Dillon 	 */
268427e5fc6SMatthew Dillon 	if (hmp->rootvp) {
269427e5fc6SMatthew Dillon 		vrele(hmp->rootvp);
270427e5fc6SMatthew Dillon 		hmp->rootvp = NULL;
271427e5fc6SMatthew Dillon 	}
27227ea2398SMatthew Dillon #endif
273427e5fc6SMatthew Dillon 
274427e5fc6SMatthew Dillon 	/*
275427e5fc6SMatthew Dillon 	 * Unload & flush inodes
276427e5fc6SMatthew Dillon 	 */
277427e5fc6SMatthew Dillon 	RB_SCAN(hammer_ino_rb_tree, &hmp->rb_inos_root, NULL,
27866325755SMatthew Dillon 		hammer_unload_inode, NULL);
279427e5fc6SMatthew Dillon 
280427e5fc6SMatthew Dillon 	/*
281427e5fc6SMatthew Dillon 	 * Unload & flush volumes
282427e5fc6SMatthew Dillon 	 */
283427e5fc6SMatthew Dillon 	RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL,
284427e5fc6SMatthew Dillon 		hammer_unload_volume, NULL);
285427e5fc6SMatthew Dillon 
286427e5fc6SMatthew Dillon 	mp->mnt_data = NULL;
28766325755SMatthew Dillon 	mp->mnt_flag &= ~MNT_LOCAL;
288427e5fc6SMatthew Dillon 	hmp->mp = NULL;
28966325755SMatthew Dillon 	kfree(hmp->zbuf, M_HAMMER);
290427e5fc6SMatthew Dillon 	kfree(hmp, M_HAMMER);
291427e5fc6SMatthew Dillon }
292427e5fc6SMatthew Dillon 
293427e5fc6SMatthew Dillon /*
294427e5fc6SMatthew Dillon  * Return the root vnode for the filesystem.
295427e5fc6SMatthew Dillon  *
296427e5fc6SMatthew Dillon  * HAMMER stores the root vnode in the hammer_mount structure so
297427e5fc6SMatthew Dillon  * getting it is easy.
298427e5fc6SMatthew Dillon  */
299427e5fc6SMatthew Dillon static int
300427e5fc6SMatthew Dillon hammer_vfs_root(struct mount *mp, struct vnode **vpp)
301427e5fc6SMatthew Dillon {
302427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
30327ea2398SMatthew Dillon 	int error;
304427e5fc6SMatthew Dillon 
30527ea2398SMatthew Dillon 	if (hmp->rootcl == NULL)
30627ea2398SMatthew Dillon 		error = EIO;
30727ea2398SMatthew Dillon 	else
30827ea2398SMatthew Dillon 		error = hammer_vfs_vget(mp, 1, vpp);
30927ea2398SMatthew Dillon 	return (error);
31027ea2398SMatthew Dillon #if 0
31127ea2398SMatthew Dillon 	/* FUTURE - cached root vnode */
312427e5fc6SMatthew Dillon 	if ((vp = hmp->rootvp) != NULL) {
313427e5fc6SMatthew Dillon 		vref(vp);
314427e5fc6SMatthew Dillon 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
315427e5fc6SMatthew Dillon 		*vpp = vp;
316427e5fc6SMatthew Dillon 		return (0);
317427e5fc6SMatthew Dillon 	} else {
318427e5fc6SMatthew Dillon 		*vpp = NULL;
319427e5fc6SMatthew Dillon 		return (EIO);
320427e5fc6SMatthew Dillon 	}
32127ea2398SMatthew Dillon #endif
322427e5fc6SMatthew Dillon }
323427e5fc6SMatthew Dillon 
324427e5fc6SMatthew Dillon static int
325427e5fc6SMatthew Dillon hammer_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
326427e5fc6SMatthew Dillon {
327fbc6e32aSMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
328fbc6e32aSMatthew Dillon 	hammer_volume_t volume;
329fbc6e32aSMatthew Dillon 	hammer_volume_ondisk_t ondisk;
330fbc6e32aSMatthew Dillon 	int error;
331fbc6e32aSMatthew Dillon 
332fbc6e32aSMatthew Dillon 	volume = hammer_get_root_volume(hmp, &error);
333fbc6e32aSMatthew Dillon 	if (error)
334fbc6e32aSMatthew Dillon 		return(error);
335fbc6e32aSMatthew Dillon 
336fbc6e32aSMatthew Dillon 	ondisk = volume->ondisk;
337fbc6e32aSMatthew Dillon 
338fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bfree = mp->mnt_stat.f_blocks -
339fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_idx_bufs -
340fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_rec_bufs -
341fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_data_bufs;
342fbc6e32aSMatthew Dillon 	if (mp->mnt_stat.f_bfree < 0)
343fbc6e32aSMatthew Dillon 		mp->mnt_stat.f_bfree = 0;
344fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree;
345fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_files = ondisk->vol0_stat_inodes;
346fbc6e32aSMatthew Dillon 	if (mp->mnt_stat.f_files < 0)
347fbc6e32aSMatthew Dillon 		mp->mnt_stat.f_files = 0;
348fbc6e32aSMatthew Dillon 
349fbc6e32aSMatthew Dillon 	hammer_rel_volume(volume, 0);
35027ea2398SMatthew Dillon 	*sbp = mp->mnt_stat;
35127ea2398SMatthew Dillon 	return(0);
352427e5fc6SMatthew Dillon }
353427e5fc6SMatthew Dillon 
354427e5fc6SMatthew Dillon static int
355427e5fc6SMatthew Dillon hammer_vfs_sync(struct mount *mp, int waitfor)
356427e5fc6SMatthew Dillon {
357fbc6e32aSMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
358fbc6e32aSMatthew Dillon 	int error;
359fbc6e32aSMatthew Dillon 
360fbc6e32aSMatthew Dillon 	error = hammer_sync_hmp(hmp, waitfor);
361fbc6e32aSMatthew Dillon 	return(error);
362427e5fc6SMatthew Dillon }
363427e5fc6SMatthew Dillon 
364