xref: /dflybsd-src/sys/vfs/hammer/hammer_vfsops.c (revision 46fe7ae18255f7b9f7e3025d0d4c937ec671ef7c)
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*46fe7ae1SMatthew Dillon  * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.15 2008/01/25 05:49:08 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>
45b3deaf57SMatthew Dillon #include <sys/sysctl.h>
46427e5fc6SMatthew Dillon #include <sys/buf.h>
47427e5fc6SMatthew Dillon #include <sys/buf2.h>
48427e5fc6SMatthew Dillon #include "hammer.h"
49427e5fc6SMatthew Dillon 
50b3deaf57SMatthew Dillon int hammer_debug_btree;
51d113fda1SMatthew Dillon int hammer_debug_tid;
52*46fe7ae1SMatthew Dillon int hammer_debug_recover;	/* -1 will disable, +1 will force */
53*46fe7ae1SMatthew Dillon int hammer_debug_recover_faults;
54b3deaf57SMatthew Dillon int hammer_count_inodes;
55b3deaf57SMatthew Dillon int hammer_count_records;
56b3deaf57SMatthew Dillon int hammer_count_record_datas;
57b3deaf57SMatthew Dillon int hammer_count_volumes;
58b3deaf57SMatthew Dillon int hammer_count_supercls;
59b3deaf57SMatthew Dillon int hammer_count_clusters;
60b3deaf57SMatthew Dillon int hammer_count_buffers;
61b3deaf57SMatthew Dillon int hammer_count_nodes;
62b3deaf57SMatthew Dillon int hammer_count_spikes;
63b3deaf57SMatthew Dillon 
64b3deaf57SMatthew Dillon SYSCTL_NODE(_vfs, OID_AUTO, hammer, CTLFLAG_RW, 0, "HAMMER filesystem");
65b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_btree, CTLFLAG_RW,
66b3deaf57SMatthew Dillon 	   &hammer_debug_btree, 0, "");
67d113fda1SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_tid, CTLFLAG_RW,
68d113fda1SMatthew Dillon 	   &hammer_debug_tid, 0, "");
69b33e2cc0SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_recover, CTLFLAG_RW,
70b33e2cc0SMatthew Dillon 	   &hammer_debug_recover, 0, "");
71*46fe7ae1SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_recover_faults, CTLFLAG_RW,
72*46fe7ae1SMatthew Dillon 	   &hammer_debug_recover_faults, 0, "");
73b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_inodes, CTLFLAG_RD,
74b3deaf57SMatthew Dillon 	   &hammer_count_inodes, 0, "");
75b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_records, CTLFLAG_RD,
76b3deaf57SMatthew Dillon 	   &hammer_count_records, 0, "");
77b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_record_datas, CTLFLAG_RD,
78b3deaf57SMatthew Dillon 	   &hammer_count_record_datas, 0, "");
79b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_volumes, CTLFLAG_RD,
80b3deaf57SMatthew Dillon 	   &hammer_count_volumes, 0, "");
81b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_supercls, CTLFLAG_RD,
82b3deaf57SMatthew Dillon 	   &hammer_count_supercls, 0, "");
83b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_clusters, CTLFLAG_RD,
84b3deaf57SMatthew Dillon 	   &hammer_count_clusters, 0, "");
85b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_buffers, CTLFLAG_RD,
86b3deaf57SMatthew Dillon 	   &hammer_count_buffers, 0, "");
87b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_nodes, CTLFLAG_RD,
88b3deaf57SMatthew Dillon 	   &hammer_count_nodes, 0, "");
89b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_spikes, CTLFLAG_RD,
90b3deaf57SMatthew Dillon 	   &hammer_count_spikes, 0, "");
91b3deaf57SMatthew Dillon 
92427e5fc6SMatthew Dillon /*
93427e5fc6SMatthew Dillon  * VFS ABI
94427e5fc6SMatthew Dillon  */
95427e5fc6SMatthew Dillon static void	hammer_free_hmp(struct mount *mp);
96427e5fc6SMatthew Dillon 
97427e5fc6SMatthew Dillon static int	hammer_vfs_mount(struct mount *mp, char *path, caddr_t data,
98427e5fc6SMatthew Dillon 				struct ucred *cred);
99427e5fc6SMatthew Dillon static int	hammer_vfs_unmount(struct mount *mp, int mntflags);
100427e5fc6SMatthew Dillon static int	hammer_vfs_root(struct mount *mp, struct vnode **vpp);
101427e5fc6SMatthew Dillon static int	hammer_vfs_statfs(struct mount *mp, struct statfs *sbp,
102427e5fc6SMatthew Dillon 				struct ucred *cred);
103427e5fc6SMatthew Dillon static int	hammer_vfs_sync(struct mount *mp, int waitfor);
104427e5fc6SMatthew Dillon static int	hammer_vfs_init(struct vfsconf *conf);
105427e5fc6SMatthew Dillon 
106427e5fc6SMatthew Dillon static struct vfsops hammer_vfsops = {
107427e5fc6SMatthew Dillon 	.vfs_mount	= hammer_vfs_mount,
108427e5fc6SMatthew Dillon 	.vfs_unmount	= hammer_vfs_unmount,
109427e5fc6SMatthew Dillon 	.vfs_root 	= hammer_vfs_root,
110427e5fc6SMatthew Dillon 	.vfs_statfs	= hammer_vfs_statfs,
111427e5fc6SMatthew Dillon 	.vfs_sync	= hammer_vfs_sync,
112427e5fc6SMatthew Dillon 	.vfs_vget	= hammer_vfs_vget,
113427e5fc6SMatthew Dillon 	.vfs_init	= hammer_vfs_init
114427e5fc6SMatthew Dillon };
115427e5fc6SMatthew Dillon 
116427e5fc6SMatthew Dillon MALLOC_DEFINE(M_HAMMER, "hammer-mount", "hammer mount");
117427e5fc6SMatthew Dillon 
118427e5fc6SMatthew Dillon VFS_SET(hammer_vfsops, hammer, 0);
119427e5fc6SMatthew Dillon MODULE_VERSION(hammer, 1);
120427e5fc6SMatthew Dillon 
121427e5fc6SMatthew Dillon static int
122427e5fc6SMatthew Dillon hammer_vfs_init(struct vfsconf *conf)
123427e5fc6SMatthew Dillon {
124427e5fc6SMatthew Dillon 	hammer_init_alist_config();
125427e5fc6SMatthew Dillon 	return(0);
126427e5fc6SMatthew Dillon }
127427e5fc6SMatthew Dillon 
128427e5fc6SMatthew Dillon static int
129427e5fc6SMatthew Dillon hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data,
130427e5fc6SMatthew Dillon 		 struct ucred *cred)
131427e5fc6SMatthew Dillon {
132427e5fc6SMatthew Dillon 	struct hammer_mount_info info;
133a89aec1bSMatthew Dillon 	hammer_mount_t hmp;
134a89aec1bSMatthew Dillon 	hammer_volume_t rootvol;
13527ea2398SMatthew Dillon 	struct vnode *rootvp;
136427e5fc6SMatthew Dillon 	const char *upath;	/* volume name in userspace */
137427e5fc6SMatthew Dillon 	char *path;		/* volume name in system space */
138427e5fc6SMatthew Dillon 	int error;
139427e5fc6SMatthew Dillon 	int i;
140427e5fc6SMatthew Dillon 
141427e5fc6SMatthew Dillon 	if ((error = copyin(data, &info, sizeof(info))) != 0)
142427e5fc6SMatthew Dillon 		return (error);
143427e5fc6SMatthew Dillon 	if (info.nvolumes <= 0 || info.nvolumes >= 32768)
144427e5fc6SMatthew Dillon 		return (EINVAL);
145427e5fc6SMatthew Dillon 
146427e5fc6SMatthew Dillon 	/*
147427e5fc6SMatthew Dillon 	 * Interal mount data structure
148427e5fc6SMatthew Dillon 	 */
149195c19a1SMatthew Dillon 	if (mp->mnt_flag & MNT_UPDATE) {
150195c19a1SMatthew Dillon 		hmp = (void *)mp->mnt_data;
151195c19a1SMatthew Dillon 		KKASSERT(hmp != NULL);
152195c19a1SMatthew Dillon 	} else {
153427e5fc6SMatthew Dillon 		hmp = kmalloc(sizeof(*hmp), M_HAMMER, M_WAITOK | M_ZERO);
154427e5fc6SMatthew Dillon 		mp->mnt_data = (qaddr_t)hmp;
155427e5fc6SMatthew Dillon 		hmp->mp = mp;
156195c19a1SMatthew Dillon 		hmp->zbuf = kmalloc(HAMMER_BUFSIZE, M_HAMMER, M_WAITOK|M_ZERO);
157195c19a1SMatthew Dillon 		hmp->namekey_iterator = mycpu->gd_time_seconds;
158*46fe7ae1SMatthew Dillon 		/*TAILQ_INIT(&hmp->recycle_list);*/
159195c19a1SMatthew Dillon 	}
160195c19a1SMatthew Dillon 	hmp->hflags = info.hflags;
1617f7c1f84SMatthew Dillon 	if (info.asof) {
1627f7c1f84SMatthew Dillon 		mp->mnt_flag |= MNT_RDONLY;
1637f7c1f84SMatthew Dillon 		hmp->asof = info.asof;
1647f7c1f84SMatthew Dillon 	} else {
1657f7c1f84SMatthew Dillon 		hmp->asof = HAMMER_MAX_TID;
1667f7c1f84SMatthew Dillon 	}
167195c19a1SMatthew Dillon 
168195c19a1SMatthew Dillon 	/*
169195c19a1SMatthew Dillon 	 * Re-open read-write if originally read-only, or vise-versa XXX
170195c19a1SMatthew Dillon 	 */
171195c19a1SMatthew Dillon 	if (mp->mnt_flag & MNT_UPDATE) {
172195c19a1SMatthew Dillon 		if (hmp->ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
173195c19a1SMatthew Dillon 			kprintf("HAMMER read-write -> read-only XXX\n");
174195c19a1SMatthew Dillon 			hmp->ronly = 1;
175195c19a1SMatthew Dillon 		} else if (hmp->ronly && (mp->mnt_flag & MNT_RDONLY) == 0) {
176195c19a1SMatthew Dillon 			kprintf("HAMMER read-only -> read-write XXX\n");
177195c19a1SMatthew Dillon 			hmp->ronly = 0;
178195c19a1SMatthew Dillon 		}
179195c19a1SMatthew Dillon 		return(0);
180195c19a1SMatthew Dillon 	}
181195c19a1SMatthew Dillon 
182427e5fc6SMatthew Dillon 	RB_INIT(&hmp->rb_vols_root);
183427e5fc6SMatthew Dillon 	RB_INIT(&hmp->rb_inos_root);
184195c19a1SMatthew Dillon 	hmp->ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
185427e5fc6SMatthew Dillon 
186427e5fc6SMatthew Dillon 	/*
187427e5fc6SMatthew Dillon 	 * Load volumes
188427e5fc6SMatthew Dillon 	 */
189427e5fc6SMatthew Dillon 	path = objcache_get(namei_oc, M_WAITOK);
190d26d0ae9SMatthew Dillon 	hmp->nvolumes = info.nvolumes;
191427e5fc6SMatthew Dillon 	for (i = 0; i < info.nvolumes; ++i) {
192427e5fc6SMatthew Dillon 		error = copyin(&info.volumes[i], &upath, sizeof(char *));
193427e5fc6SMatthew Dillon 		if (error == 0)
194427e5fc6SMatthew Dillon 			error = copyinstr(upath, path, MAXPATHLEN, NULL);
195427e5fc6SMatthew Dillon 		if (error == 0)
1968cd0a023SMatthew Dillon 			error = hammer_install_volume(hmp, path);
197427e5fc6SMatthew Dillon 		if (error)
198427e5fc6SMatthew Dillon 			break;
199427e5fc6SMatthew Dillon 	}
200427e5fc6SMatthew Dillon 	objcache_put(namei_oc, path);
201427e5fc6SMatthew Dillon 
202427e5fc6SMatthew Dillon 	/*
203427e5fc6SMatthew Dillon 	 * Make sure we found a root volume
204427e5fc6SMatthew Dillon 	 */
205427e5fc6SMatthew Dillon 	if (error == 0 && hmp->rootvol == NULL) {
206427e5fc6SMatthew Dillon 		kprintf("hammer_mount: No root volume found!\n");
207427e5fc6SMatthew Dillon 		error = EINVAL;
208427e5fc6SMatthew Dillon 	}
209427e5fc6SMatthew Dillon 	if (error == 0 && hmp->rootcl == NULL) {
210427e5fc6SMatthew Dillon 		kprintf("hammer_mount: No root cluster found!\n");
211427e5fc6SMatthew Dillon 		error = EINVAL;
212427e5fc6SMatthew Dillon 	}
213427e5fc6SMatthew Dillon 	if (error) {
214427e5fc6SMatthew Dillon 		hammer_free_hmp(mp);
215427e5fc6SMatthew Dillon 		return (error);
216427e5fc6SMatthew Dillon 	}
217427e5fc6SMatthew Dillon 
218427e5fc6SMatthew Dillon 	/*
21927ea2398SMatthew Dillon 	 * No errors, setup enough of the mount point so we can lookup the
22027ea2398SMatthew Dillon 	 * root vnode.
221427e5fc6SMatthew Dillon 	 */
222427e5fc6SMatthew Dillon 	mp->mnt_iosize_max = MAXPHYS;
223427e5fc6SMatthew Dillon 	mp->mnt_kern_flag |= MNTK_FSMID;
224427e5fc6SMatthew Dillon 	mp->mnt_stat.f_fsid.val[0] = 0;	/* XXX */
225427e5fc6SMatthew Dillon 	mp->mnt_stat.f_fsid.val[1] = 0;	/* XXX */
226c0ade690SMatthew Dillon 
227c0ade690SMatthew Dillon 	/*
228c0ade690SMatthew Dillon 	 * note: f_iosize is used by vnode_pager_haspage() when constructing
229c0ade690SMatthew Dillon 	 * its VOP_BMAP call.
230c0ade690SMatthew Dillon 	 */
231c0ade690SMatthew Dillon 	mp->mnt_stat.f_iosize = HAMMER_BUFSIZE;
232fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bsize = HAMMER_BUFSIZE;
233427e5fc6SMatthew Dillon 	vfs_getnewfsid(mp);		/* XXX */
234427e5fc6SMatthew Dillon 	mp->mnt_maxsymlinklen = 255;
235427e5fc6SMatthew Dillon 	mp->mnt_flag |= MNT_LOCAL;
236427e5fc6SMatthew Dillon 
237427e5fc6SMatthew Dillon 	vfs_add_vnodeops(mp, &hammer_vnode_vops, &mp->mnt_vn_norm_ops);
2387a04d74fSMatthew Dillon 	vfs_add_vnodeops(mp, &hammer_spec_vops, &mp->mnt_vn_spec_ops);
2397a04d74fSMatthew Dillon 	vfs_add_vnodeops(mp, &hammer_fifo_vops, &mp->mnt_vn_fifo_ops);
24027ea2398SMatthew Dillon 
24127ea2398SMatthew Dillon 	/*
242a89aec1bSMatthew Dillon 	 * The root volume's ondisk pointer is only valid if we hold a
243a89aec1bSMatthew Dillon 	 * reference to it.
244a89aec1bSMatthew Dillon 	 */
245a89aec1bSMatthew Dillon 	rootvol = hammer_get_root_volume(hmp, &error);
246a89aec1bSMatthew Dillon 	if (error)
247a89aec1bSMatthew Dillon 		goto done;
248a89aec1bSMatthew Dillon 	ksnprintf(mp->mnt_stat.f_mntfromname,
249a89aec1bSMatthew Dillon 		  sizeof(mp->mnt_stat.f_mntfromname), "%s",
250a89aec1bSMatthew Dillon 		  rootvol->ondisk->vol_name);
251a89aec1bSMatthew Dillon 	hammer_rel_volume(rootvol, 0);
252a89aec1bSMatthew Dillon 
253a89aec1bSMatthew Dillon 	/*
25427ea2398SMatthew Dillon 	 * Locate the root directory using the root cluster's B-Tree as a
25527ea2398SMatthew Dillon 	 * starting point.  The root directory uses an obj_id of 1.
25627ea2398SMatthew Dillon 	 *
25727ea2398SMatthew Dillon 	 * FUTURE: Leave the root directory cached referenced but unlocked
25827ea2398SMatthew Dillon 	 * in hmp->rootvp (need to flush it on unmount).
25927ea2398SMatthew Dillon 	 */
26027ea2398SMatthew Dillon 	error = hammer_vfs_vget(mp, 1, &rootvp);
261a89aec1bSMatthew Dillon 	if (error)
262a89aec1bSMatthew Dillon 		goto done;
26327ea2398SMatthew Dillon 	vput(rootvp);
26427ea2398SMatthew Dillon 	/*vn_unlock(hmp->rootvp);*/
26527ea2398SMatthew Dillon 
266a89aec1bSMatthew Dillon done:
26727ea2398SMatthew Dillon 	/*
26827ea2398SMatthew Dillon 	 * Cleanup and return.
26927ea2398SMatthew Dillon 	 */
27027ea2398SMatthew Dillon 	if (error)
27127ea2398SMatthew Dillon 		hammer_free_hmp(mp);
272427e5fc6SMatthew Dillon 	return (error);
273427e5fc6SMatthew Dillon }
274427e5fc6SMatthew Dillon 
275427e5fc6SMatthew Dillon static int
276427e5fc6SMatthew Dillon hammer_vfs_unmount(struct mount *mp, int mntflags)
277427e5fc6SMatthew Dillon {
278427e5fc6SMatthew Dillon #if 0
279427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
280427e5fc6SMatthew Dillon #endif
281427e5fc6SMatthew Dillon 	int flags;
28266325755SMatthew Dillon 	int error;
28327ea2398SMatthew Dillon 
28427ea2398SMatthew Dillon 	/*
285427e5fc6SMatthew Dillon 	 * Clean out the vnodes
286427e5fc6SMatthew Dillon 	 */
28766325755SMatthew Dillon 	flags = 0;
28866325755SMatthew Dillon 	if (mntflags & MNT_FORCE)
28966325755SMatthew Dillon 		flags |= FORCECLOSE;
29066325755SMatthew Dillon 	if ((error = vflush(mp, 0, flags)) != 0)
29166325755SMatthew Dillon 		return (error);
292427e5fc6SMatthew Dillon 
293427e5fc6SMatthew Dillon 	/*
294427e5fc6SMatthew Dillon 	 * Clean up the internal mount structure and related entities.  This
295427e5fc6SMatthew Dillon 	 * may issue I/O.
296427e5fc6SMatthew Dillon 	 */
297427e5fc6SMatthew Dillon 	hammer_free_hmp(mp);
298427e5fc6SMatthew Dillon 	return(0);
299427e5fc6SMatthew Dillon }
300427e5fc6SMatthew Dillon 
301427e5fc6SMatthew Dillon /*
302427e5fc6SMatthew Dillon  * Clean up the internal mount structure and disassociate it from the mount.
303427e5fc6SMatthew Dillon  * This may issue I/O.
304427e5fc6SMatthew Dillon  */
305427e5fc6SMatthew Dillon static void
306427e5fc6SMatthew Dillon hammer_free_hmp(struct mount *mp)
307427e5fc6SMatthew Dillon {
308427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
309427e5fc6SMatthew Dillon 
31027ea2398SMatthew Dillon #if 0
311427e5fc6SMatthew Dillon 	/*
312427e5fc6SMatthew Dillon 	 * Clean up the root vnode
313427e5fc6SMatthew Dillon 	 */
314427e5fc6SMatthew Dillon 	if (hmp->rootvp) {
315427e5fc6SMatthew Dillon 		vrele(hmp->rootvp);
316427e5fc6SMatthew Dillon 		hmp->rootvp = NULL;
317427e5fc6SMatthew Dillon 	}
31827ea2398SMatthew Dillon #endif
319427e5fc6SMatthew Dillon 
320427e5fc6SMatthew Dillon 	/*
321427e5fc6SMatthew Dillon 	 * Unload & flush inodes
322427e5fc6SMatthew Dillon 	 */
323427e5fc6SMatthew Dillon 	RB_SCAN(hammer_ino_rb_tree, &hmp->rb_inos_root, NULL,
324d113fda1SMatthew Dillon 		hammer_unload_inode, (void *)MNT_WAIT);
325427e5fc6SMatthew Dillon 
326427e5fc6SMatthew Dillon 	/*
327427e5fc6SMatthew Dillon 	 * Unload & flush volumes
328427e5fc6SMatthew Dillon 	 */
329427e5fc6SMatthew Dillon 	RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL,
330427e5fc6SMatthew Dillon 		hammer_unload_volume, NULL);
331427e5fc6SMatthew Dillon 
332427e5fc6SMatthew Dillon 	mp->mnt_data = NULL;
33366325755SMatthew Dillon 	mp->mnt_flag &= ~MNT_LOCAL;
334427e5fc6SMatthew Dillon 	hmp->mp = NULL;
33566325755SMatthew Dillon 	kfree(hmp->zbuf, M_HAMMER);
336427e5fc6SMatthew Dillon 	kfree(hmp, M_HAMMER);
337427e5fc6SMatthew Dillon }
338427e5fc6SMatthew Dillon 
339427e5fc6SMatthew Dillon /*
340427e5fc6SMatthew Dillon  * Return the root vnode for the filesystem.
341427e5fc6SMatthew Dillon  *
342427e5fc6SMatthew Dillon  * HAMMER stores the root vnode in the hammer_mount structure so
343427e5fc6SMatthew Dillon  * getting it is easy.
344427e5fc6SMatthew Dillon  */
345427e5fc6SMatthew Dillon static int
346427e5fc6SMatthew Dillon hammer_vfs_root(struct mount *mp, struct vnode **vpp)
347427e5fc6SMatthew Dillon {
348427e5fc6SMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
34927ea2398SMatthew Dillon 	int error;
350427e5fc6SMatthew Dillon 
35127ea2398SMatthew Dillon 	if (hmp->rootcl == NULL)
35227ea2398SMatthew Dillon 		error = EIO;
35327ea2398SMatthew Dillon 	else
35427ea2398SMatthew Dillon 		error = hammer_vfs_vget(mp, 1, vpp);
35527ea2398SMatthew Dillon 	return (error);
35627ea2398SMatthew Dillon #if 0
35727ea2398SMatthew Dillon 	/* FUTURE - cached root vnode */
358427e5fc6SMatthew Dillon 	if ((vp = hmp->rootvp) != NULL) {
359427e5fc6SMatthew Dillon 		vref(vp);
360427e5fc6SMatthew Dillon 		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
361427e5fc6SMatthew Dillon 		*vpp = vp;
362427e5fc6SMatthew Dillon 		return (0);
363427e5fc6SMatthew Dillon 	} else {
364427e5fc6SMatthew Dillon 		*vpp = NULL;
365427e5fc6SMatthew Dillon 		return (EIO);
366427e5fc6SMatthew Dillon 	}
36727ea2398SMatthew Dillon #endif
368427e5fc6SMatthew Dillon }
369427e5fc6SMatthew Dillon 
370427e5fc6SMatthew Dillon static int
371427e5fc6SMatthew Dillon hammer_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
372427e5fc6SMatthew Dillon {
373fbc6e32aSMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
374fbc6e32aSMatthew Dillon 	hammer_volume_t volume;
375fbc6e32aSMatthew Dillon 	hammer_volume_ondisk_t ondisk;
376fbc6e32aSMatthew Dillon 	int error;
377fbc6e32aSMatthew Dillon 
378fbc6e32aSMatthew Dillon 	volume = hammer_get_root_volume(hmp, &error);
379fbc6e32aSMatthew Dillon 	if (error)
380fbc6e32aSMatthew Dillon 		return(error);
381fbc6e32aSMatthew Dillon 
382fbc6e32aSMatthew Dillon 	ondisk = volume->ondisk;
383fbc6e32aSMatthew Dillon 
384fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bfree = mp->mnt_stat.f_blocks -
385fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_idx_bufs -
386fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_rec_bufs -
387fbc6e32aSMatthew Dillon 				ondisk->vol0_stat_data_bufs;
388fbc6e32aSMatthew Dillon 	if (mp->mnt_stat.f_bfree < 0)
389fbc6e32aSMatthew Dillon 		mp->mnt_stat.f_bfree = 0;
390fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree;
391fbc6e32aSMatthew Dillon 	mp->mnt_stat.f_files = ondisk->vol0_stat_inodes;
392fbc6e32aSMatthew Dillon 	if (mp->mnt_stat.f_files < 0)
393fbc6e32aSMatthew Dillon 		mp->mnt_stat.f_files = 0;
394fbc6e32aSMatthew Dillon 
395fbc6e32aSMatthew Dillon 	hammer_rel_volume(volume, 0);
39627ea2398SMatthew Dillon 	*sbp = mp->mnt_stat;
39727ea2398SMatthew Dillon 	return(0);
398427e5fc6SMatthew Dillon }
399427e5fc6SMatthew Dillon 
400427e5fc6SMatthew Dillon static int
401427e5fc6SMatthew Dillon hammer_vfs_sync(struct mount *mp, int waitfor)
402427e5fc6SMatthew Dillon {
403fbc6e32aSMatthew Dillon 	struct hammer_mount *hmp = (void *)mp->mnt_data;
404fbc6e32aSMatthew Dillon 	int error;
405fbc6e32aSMatthew Dillon 
406fbc6e32aSMatthew Dillon 	error = hammer_sync_hmp(hmp, waitfor);
407fbc6e32aSMatthew Dillon 	return(error);
408427e5fc6SMatthew Dillon }
409427e5fc6SMatthew Dillon 
410