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