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