1427e5fc6SMatthew Dillon /* 2b84de5afSMatthew Dillon * Copyright (c) 2007-2008 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 * 3444a83111SMatthew Dillon * $DragonFly: src/sys/vfs/hammer/hammer_vfsops.c,v 1.74 2008/11/13 02:18:43 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 505987cc42SMatthew Dillon int hammer_supported_version = HAMMER_VOL_VERSION_TWO; 512f85fa4dSMatthew Dillon int hammer_debug_io; 52d5ef456eSMatthew Dillon int hammer_debug_general; 531b0ab2c3SMatthew Dillon int hammer_debug_debug = 1; /* medium-error panics */ 54e8599db1SMatthew Dillon int hammer_debug_inode; 557d683b0fSMatthew Dillon int hammer_debug_locks; 56b3deaf57SMatthew Dillon int hammer_debug_btree; 57d113fda1SMatthew Dillon int hammer_debug_tid; 5846fe7ae1SMatthew Dillon int hammer_debug_recover; /* -1 will disable, +1 will force */ 5946fe7ae1SMatthew Dillon int hammer_debug_recover_faults; 601b0ab2c3SMatthew Dillon int hammer_cluster_enable = 1; /* enable read clustering by default */ 617a61b85dSMatthew Dillon int hammer_count_fsyncs; 62b3deaf57SMatthew Dillon int hammer_count_inodes; 63af209b0fSMatthew Dillon int hammer_count_iqueued; 649f5097dcSMatthew Dillon int hammer_count_reclaiming; 65b3deaf57SMatthew Dillon int hammer_count_records; 66b3deaf57SMatthew Dillon int hammer_count_record_datas; 67b3deaf57SMatthew Dillon int hammer_count_volumes; 68b3deaf57SMatthew Dillon int hammer_count_buffers; 69b3deaf57SMatthew Dillon int hammer_count_nodes; 70a7e9bef1SMatthew Dillon int64_t hammer_count_extra_space_used; 71cb51be26SMatthew Dillon int64_t hammer_stats_btree_lookups; 72cb51be26SMatthew Dillon int64_t hammer_stats_btree_searches; 73cb51be26SMatthew Dillon int64_t hammer_stats_btree_inserts; 74cb51be26SMatthew Dillon int64_t hammer_stats_btree_deletes; 75cb51be26SMatthew Dillon int64_t hammer_stats_btree_elements; 76cb51be26SMatthew Dillon int64_t hammer_stats_btree_splits; 77cb51be26SMatthew Dillon int64_t hammer_stats_btree_iterations; 7839d8fd63SMatthew Dillon int64_t hammer_stats_btree_root_iterations; 79cb51be26SMatthew Dillon int64_t hammer_stats_record_iterations; 80ce0138a6SMatthew Dillon 81ce0138a6SMatthew Dillon int64_t hammer_stats_file_read; 82ce0138a6SMatthew Dillon int64_t hammer_stats_file_write; 83ce0138a6SMatthew Dillon int64_t hammer_stats_file_iopsr; 84ce0138a6SMatthew Dillon int64_t hammer_stats_file_iopsw; 85ce0138a6SMatthew Dillon int64_t hammer_stats_disk_read; 86ce0138a6SMatthew Dillon int64_t hammer_stats_disk_write; 87ce0138a6SMatthew Dillon int64_t hammer_stats_inode_flushes; 88ce0138a6SMatthew Dillon int64_t hammer_stats_commits; 89ce0138a6SMatthew Dillon 90f5a07a7aSMatthew Dillon int hammer_count_dirtybufspace; /* global */ 91a99b9ea2SMatthew Dillon int hammer_count_refedbufs; /* global */ 920832c9bbSMatthew Dillon int hammer_count_reservations; 93a99b9ea2SMatthew Dillon int hammer_count_io_running_read; 94a99b9ea2SMatthew Dillon int hammer_count_io_running_write; 95a99b9ea2SMatthew Dillon int hammer_count_io_locked; 96f5a07a7aSMatthew Dillon int hammer_limit_dirtybufspace; /* per-mount */ 970832c9bbSMatthew Dillon int hammer_limit_recs; /* as a whole XXX */ 9821fde338SMatthew Dillon int hammer_autoflush = 2000; /* auto flush */ 991f07f686SMatthew Dillon int hammer_bio_count; 100cb51be26SMatthew Dillon int hammer_verify_zone; 1011b0ab2c3SMatthew Dillon int hammer_verify_data = 1; 102cb51be26SMatthew Dillon int hammer_write_mode; 1037d683b0fSMatthew Dillon int64_t hammer_contention_count; 104f03c9cf4SMatthew Dillon int64_t hammer_zone_limit; 105b3deaf57SMatthew Dillon 106b3deaf57SMatthew Dillon SYSCTL_NODE(_vfs, OID_AUTO, hammer, CTLFLAG_RW, 0, "HAMMER filesystem"); 1075987cc42SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, supported_version, CTLFLAG_RD, 1085987cc42SMatthew Dillon &hammer_supported_version, 0, ""); 109d5ef456eSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_general, CTLFLAG_RW, 110d5ef456eSMatthew Dillon &hammer_debug_general, 0, ""); 1112f85fa4dSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_io, CTLFLAG_RW, 1122f85fa4dSMatthew Dillon &hammer_debug_io, 0, ""); 11377062c8aSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_debug, CTLFLAG_RW, 11477062c8aSMatthew Dillon &hammer_debug_debug, 0, ""); 115e8599db1SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_inode, CTLFLAG_RW, 116e8599db1SMatthew Dillon &hammer_debug_inode, 0, ""); 1177d683b0fSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_locks, CTLFLAG_RW, 1187d683b0fSMatthew Dillon &hammer_debug_locks, 0, ""); 119b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_btree, CTLFLAG_RW, 120b3deaf57SMatthew Dillon &hammer_debug_btree, 0, ""); 121d113fda1SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_tid, CTLFLAG_RW, 122d113fda1SMatthew Dillon &hammer_debug_tid, 0, ""); 123b33e2cc0SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_recover, CTLFLAG_RW, 124b33e2cc0SMatthew Dillon &hammer_debug_recover, 0, ""); 12546fe7ae1SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, debug_recover_faults, CTLFLAG_RW, 12646fe7ae1SMatthew Dillon &hammer_debug_recover_faults, 0, ""); 1271b0ab2c3SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, cluster_enable, CTLFLAG_RW, 1281b0ab2c3SMatthew Dillon &hammer_cluster_enable, 0, ""); 1299480ff55SMatthew Dillon 130f5a07a7aSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, limit_dirtybufspace, CTLFLAG_RW, 131f5a07a7aSMatthew Dillon &hammer_limit_dirtybufspace, 0, ""); 13247637bffSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, limit_recs, CTLFLAG_RW, 13347637bffSMatthew Dillon &hammer_limit_recs, 0, ""); 1349480ff55SMatthew Dillon 1357a61b85dSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_fsyncs, CTLFLAG_RD, 1367a61b85dSMatthew Dillon &hammer_count_fsyncs, 0, ""); 137b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_inodes, CTLFLAG_RD, 138b3deaf57SMatthew Dillon &hammer_count_inodes, 0, ""); 139af209b0fSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_iqueued, CTLFLAG_RD, 140af209b0fSMatthew Dillon &hammer_count_iqueued, 0, ""); 1419f5097dcSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_reclaiming, CTLFLAG_RD, 1429f5097dcSMatthew Dillon &hammer_count_reclaiming, 0, ""); 143b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_records, CTLFLAG_RD, 144b3deaf57SMatthew Dillon &hammer_count_records, 0, ""); 145b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_record_datas, CTLFLAG_RD, 146b3deaf57SMatthew Dillon &hammer_count_record_datas, 0, ""); 147b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_volumes, CTLFLAG_RD, 148b3deaf57SMatthew Dillon &hammer_count_volumes, 0, ""); 149b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_buffers, CTLFLAG_RD, 150b3deaf57SMatthew Dillon &hammer_count_buffers, 0, ""); 151b3deaf57SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_nodes, CTLFLAG_RD, 152b3deaf57SMatthew Dillon &hammer_count_nodes, 0, ""); 153a7e9bef1SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, count_extra_space_used, CTLFLAG_RD, 154a7e9bef1SMatthew Dillon &hammer_count_extra_space_used, 0, ""); 155ce0138a6SMatthew Dillon 156cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_searches, CTLFLAG_RD, 157cb51be26SMatthew Dillon &hammer_stats_btree_searches, 0, ""); 158cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_lookups, CTLFLAG_RD, 159cb51be26SMatthew Dillon &hammer_stats_btree_lookups, 0, ""); 160cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_inserts, CTLFLAG_RD, 161cb51be26SMatthew Dillon &hammer_stats_btree_inserts, 0, ""); 162cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_deletes, CTLFLAG_RD, 163cb51be26SMatthew Dillon &hammer_stats_btree_deletes, 0, ""); 164cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_elements, CTLFLAG_RD, 165cb51be26SMatthew Dillon &hammer_stats_btree_elements, 0, ""); 166cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_splits, CTLFLAG_RD, 167cb51be26SMatthew Dillon &hammer_stats_btree_splits, 0, ""); 168cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_iterations, CTLFLAG_RD, 169cb51be26SMatthew Dillon &hammer_stats_btree_iterations, 0, ""); 17039d8fd63SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_btree_root_iterations, CTLFLAG_RD, 17139d8fd63SMatthew Dillon &hammer_stats_btree_root_iterations, 0, ""); 172cb51be26SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_record_iterations, CTLFLAG_RD, 173cb51be26SMatthew Dillon &hammer_stats_record_iterations, 0, ""); 174ce0138a6SMatthew Dillon 175ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_file_read, CTLFLAG_RD, 176ce0138a6SMatthew Dillon &hammer_stats_file_read, 0, ""); 177ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_file_write, CTLFLAG_RD, 178ce0138a6SMatthew Dillon &hammer_stats_file_write, 0, ""); 179ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_file_iopsr, CTLFLAG_RD, 180ce0138a6SMatthew Dillon &hammer_stats_file_iopsr, 0, ""); 181ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_file_iopsw, CTLFLAG_RD, 182ce0138a6SMatthew Dillon &hammer_stats_file_iopsw, 0, ""); 183ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_disk_read, CTLFLAG_RD, 184ce0138a6SMatthew Dillon &hammer_stats_disk_read, 0, ""); 185ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_disk_write, CTLFLAG_RD, 186ce0138a6SMatthew Dillon &hammer_stats_disk_write, 0, ""); 187ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_inode_flushes, CTLFLAG_RD, 188ce0138a6SMatthew Dillon &hammer_stats_inode_flushes, 0, ""); 189ce0138a6SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, stats_commits, CTLFLAG_RD, 190ce0138a6SMatthew Dillon &hammer_stats_commits, 0, ""); 191ce0138a6SMatthew Dillon 192f5a07a7aSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_dirtybufspace, CTLFLAG_RD, 193f5a07a7aSMatthew Dillon &hammer_count_dirtybufspace, 0, ""); 194a99b9ea2SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_refedbufs, CTLFLAG_RD, 195a99b9ea2SMatthew Dillon &hammer_count_refedbufs, 0, ""); 1960832c9bbSMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_reservations, CTLFLAG_RD, 1970832c9bbSMatthew Dillon &hammer_count_reservations, 0, ""); 198a99b9ea2SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_io_running_read, CTLFLAG_RD, 199a99b9ea2SMatthew Dillon &hammer_count_io_running_read, 0, ""); 200a99b9ea2SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_io_locked, CTLFLAG_RD, 201a99b9ea2SMatthew Dillon &hammer_count_io_locked, 0, ""); 202a99b9ea2SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, count_io_running_write, CTLFLAG_RD, 203a99b9ea2SMatthew Dillon &hammer_count_io_running_write, 0, ""); 204f03c9cf4SMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, zone_limit, CTLFLAG_RW, 205f03c9cf4SMatthew Dillon &hammer_zone_limit, 0, ""); 2067d683b0fSMatthew Dillon SYSCTL_QUAD(_vfs_hammer, OID_AUTO, contention_count, CTLFLAG_RW, 2077d683b0fSMatthew Dillon &hammer_contention_count, 0, ""); 20821fde338SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, autoflush, CTLFLAG_RW, 20921fde338SMatthew Dillon &hammer_autoflush, 0, ""); 210cb51be26SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, verify_zone, CTLFLAG_RW, 211cb51be26SMatthew Dillon &hammer_verify_zone, 0, ""); 2121b0ab2c3SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, verify_data, CTLFLAG_RW, 2131b0ab2c3SMatthew Dillon &hammer_verify_data, 0, ""); 214cb51be26SMatthew Dillon SYSCTL_INT(_vfs_hammer, OID_AUTO, write_mode, CTLFLAG_RW, 215cb51be26SMatthew Dillon &hammer_write_mode, 0, ""); 216b3deaf57SMatthew Dillon 217bcac4bbbSMatthew Dillon KTR_INFO_MASTER(hammer); 218bcac4bbbSMatthew Dillon 219427e5fc6SMatthew Dillon /* 220427e5fc6SMatthew Dillon * VFS ABI 221427e5fc6SMatthew Dillon */ 222427e5fc6SMatthew Dillon static void hammer_free_hmp(struct mount *mp); 223427e5fc6SMatthew Dillon 224427e5fc6SMatthew Dillon static int hammer_vfs_mount(struct mount *mp, char *path, caddr_t data, 225427e5fc6SMatthew Dillon struct ucred *cred); 226427e5fc6SMatthew Dillon static int hammer_vfs_unmount(struct mount *mp, int mntflags); 227427e5fc6SMatthew Dillon static int hammer_vfs_root(struct mount *mp, struct vnode **vpp); 228427e5fc6SMatthew Dillon static int hammer_vfs_statfs(struct mount *mp, struct statfs *sbp, 229427e5fc6SMatthew Dillon struct ucred *cred); 2306f97fce3SMatthew Dillon static int hammer_vfs_statvfs(struct mount *mp, struct statvfs *sbp, 2316f97fce3SMatthew Dillon struct ucred *cred); 232427e5fc6SMatthew Dillon static int hammer_vfs_sync(struct mount *mp, int waitfor); 233513ca7d7SMatthew Dillon static int hammer_vfs_vget(struct mount *mp, ino_t ino, 234513ca7d7SMatthew Dillon struct vnode **vpp); 235427e5fc6SMatthew Dillon static int hammer_vfs_init(struct vfsconf *conf); 23667863d04SMatthew Dillon static int hammer_vfs_fhtovp(struct mount *mp, struct vnode *rootvp, 23767863d04SMatthew Dillon struct fid *fhp, struct vnode **vpp); 238513ca7d7SMatthew Dillon static int hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp); 239513ca7d7SMatthew Dillon static int hammer_vfs_checkexp(struct mount *mp, struct sockaddr *nam, 240513ca7d7SMatthew Dillon int *exflagsp, struct ucred **credanonp); 241513ca7d7SMatthew Dillon 242427e5fc6SMatthew Dillon 243427e5fc6SMatthew Dillon static struct vfsops hammer_vfsops = { 244427e5fc6SMatthew Dillon .vfs_mount = hammer_vfs_mount, 245427e5fc6SMatthew Dillon .vfs_unmount = hammer_vfs_unmount, 246427e5fc6SMatthew Dillon .vfs_root = hammer_vfs_root, 247427e5fc6SMatthew Dillon .vfs_statfs = hammer_vfs_statfs, 2486f97fce3SMatthew Dillon .vfs_statvfs = hammer_vfs_statvfs, 249427e5fc6SMatthew Dillon .vfs_sync = hammer_vfs_sync, 250427e5fc6SMatthew Dillon .vfs_vget = hammer_vfs_vget, 251513ca7d7SMatthew Dillon .vfs_init = hammer_vfs_init, 252513ca7d7SMatthew Dillon .vfs_vptofh = hammer_vfs_vptofh, 253513ca7d7SMatthew Dillon .vfs_fhtovp = hammer_vfs_fhtovp, 254513ca7d7SMatthew Dillon .vfs_checkexp = hammer_vfs_checkexp 255427e5fc6SMatthew Dillon }; 256427e5fc6SMatthew Dillon 257bac808feSMatthew Dillon MALLOC_DEFINE(M_HAMMER, "HAMMER-mount", ""); 258427e5fc6SMatthew Dillon 259427e5fc6SMatthew Dillon VFS_SET(hammer_vfsops, hammer, 0); 260427e5fc6SMatthew Dillon MODULE_VERSION(hammer, 1); 261427e5fc6SMatthew Dillon 262427e5fc6SMatthew Dillon static int 263427e5fc6SMatthew Dillon hammer_vfs_init(struct vfsconf *conf) 264427e5fc6SMatthew Dillon { 2653098dc2fSMatthew Dillon int n; 2663098dc2fSMatthew Dillon 2673098dc2fSMatthew Dillon if (hammer_limit_recs == 0) { 268a99b9ea2SMatthew Dillon hammer_limit_recs = nbuf * 25; 2693098dc2fSMatthew Dillon n = kmalloc_limit(M_HAMMER) / 512; 2703098dc2fSMatthew Dillon if (hammer_limit_recs > n) 2713098dc2fSMatthew Dillon hammer_limit_recs = n; 2723098dc2fSMatthew Dillon } 273f5a07a7aSMatthew Dillon if (hammer_limit_dirtybufspace == 0) { 274f5a07a7aSMatthew Dillon hammer_limit_dirtybufspace = hidirtybufspace / 2; 275f5a07a7aSMatthew Dillon if (hammer_limit_dirtybufspace < 100) 276f5a07a7aSMatthew Dillon hammer_limit_dirtybufspace = 100; 2779f5097dcSMatthew Dillon } 278427e5fc6SMatthew Dillon return(0); 279427e5fc6SMatthew Dillon } 280427e5fc6SMatthew Dillon 281427e5fc6SMatthew Dillon static int 282427e5fc6SMatthew Dillon hammer_vfs_mount(struct mount *mp, char *mntpt, caddr_t data, 283427e5fc6SMatthew Dillon struct ucred *cred) 284427e5fc6SMatthew Dillon { 285427e5fc6SMatthew Dillon struct hammer_mount_info info; 286a89aec1bSMatthew Dillon hammer_mount_t hmp; 287a89aec1bSMatthew Dillon hammer_volume_t rootvol; 28827ea2398SMatthew Dillon struct vnode *rootvp; 2897c19b529SMichael Neumann struct vnode *devvp = NULL; 290427e5fc6SMatthew Dillon const char *upath; /* volume name in userspace */ 291427e5fc6SMatthew Dillon char *path; /* volume name in system space */ 292427e5fc6SMatthew Dillon int error; 293427e5fc6SMatthew Dillon int i; 294732a1697SMatthew Dillon int master_id; 295ab0bf4a3SMatthew Dillon int maxinodes; 296ab0bf4a3SMatthew Dillon 297ab0bf4a3SMatthew Dillon /* 298ab0bf4a3SMatthew Dillon * Accept hammer_mount_info. mntpt is NULL for root mounts at boot. 299ab0bf4a3SMatthew Dillon */ 300ab0bf4a3SMatthew Dillon if (mntpt == NULL) { 3017c19b529SMichael Neumann if ((error = bdevvp(rootdev, &devvp))) { 3027c19b529SMichael Neumann kprintf("hammer_mountroot: can't find devvp\n"); 3037c19b529SMichael Neumann return (error); 3047c19b529SMichael Neumann } 3057c19b529SMichael Neumann mp->mnt_flag &= ~MNT_RDONLY; /* mount R/W */ 3067c19b529SMichael Neumann bzero(&info, sizeof(info)); 3077c19b529SMichael Neumann info.asof = 0; 3087c19b529SMichael Neumann info.hflags = 0; 3097c19b529SMichael Neumann info.nvolumes = 1; 3107c19b529SMichael Neumann } else { 311427e5fc6SMatthew Dillon if ((error = copyin(data, &info, sizeof(info))) != 0) 312427e5fc6SMatthew Dillon return (error); 3137c19b529SMichael Neumann } 314427e5fc6SMatthew Dillon 315427e5fc6SMatthew Dillon /* 316732a1697SMatthew Dillon * updating or new mount 317427e5fc6SMatthew Dillon */ 318195c19a1SMatthew Dillon if (mp->mnt_flag & MNT_UPDATE) { 319195c19a1SMatthew Dillon hmp = (void *)mp->mnt_data; 320195c19a1SMatthew Dillon KKASSERT(hmp != NULL); 321195c19a1SMatthew Dillon } else { 322732a1697SMatthew Dillon if (info.nvolumes <= 0 || info.nvolumes >= 32768) 323732a1697SMatthew Dillon return (EINVAL); 324732a1697SMatthew Dillon hmp = NULL; 325732a1697SMatthew Dillon } 326732a1697SMatthew Dillon 327732a1697SMatthew Dillon /* 328732a1697SMatthew Dillon * master-id validation. The master id may not be changed by a 329732a1697SMatthew Dillon * mount update. 330732a1697SMatthew Dillon */ 331732a1697SMatthew Dillon if (info.hflags & HMNT_MASTERID) { 332732a1697SMatthew Dillon if (hmp && hmp->master_id != info.master_id) { 333732a1697SMatthew Dillon kprintf("hammer: cannot change master id " 334732a1697SMatthew Dillon "with mount update\n"); 335732a1697SMatthew Dillon return(EINVAL); 336732a1697SMatthew Dillon } 337732a1697SMatthew Dillon master_id = info.master_id; 338732a1697SMatthew Dillon if (master_id < -1 || master_id >= HAMMER_MAX_MASTERS) 339732a1697SMatthew Dillon return (EINVAL); 340732a1697SMatthew Dillon } else { 341732a1697SMatthew Dillon if (hmp) 342732a1697SMatthew Dillon master_id = hmp->master_id; 343732a1697SMatthew Dillon else 344732a1697SMatthew Dillon master_id = 0; 345732a1697SMatthew Dillon } 346732a1697SMatthew Dillon 347732a1697SMatthew Dillon /* 348732a1697SMatthew Dillon * Interal mount data structure 349732a1697SMatthew Dillon */ 350732a1697SMatthew Dillon if (hmp == NULL) { 351427e5fc6SMatthew Dillon hmp = kmalloc(sizeof(*hmp), M_HAMMER, M_WAITOK | M_ZERO); 352427e5fc6SMatthew Dillon mp->mnt_data = (qaddr_t)hmp; 353427e5fc6SMatthew Dillon hmp->mp = mp; 35446fe7ae1SMatthew Dillon /*TAILQ_INIT(&hmp->recycle_list);*/ 35547197d71SMatthew Dillon 356bac808feSMatthew Dillon /* 357bac808feSMatthew Dillon * Make sure kmalloc type limits are set appropriately. If root 358bac808feSMatthew Dillon * increases the vnode limit you may have to do a dummy remount 359bac808feSMatthew Dillon * to adjust the HAMMER inode limit. 360bac808feSMatthew Dillon */ 361bac808feSMatthew Dillon kmalloc_create(&hmp->m_misc, "HAMMER-others"); 362bac808feSMatthew Dillon kmalloc_create(&hmp->m_inodes, "HAMMER-inodes"); 363bac808feSMatthew Dillon 364bac808feSMatthew Dillon maxinodes = desiredvnodes + desiredvnodes / 5 + 365bac808feSMatthew Dillon HAMMER_RECLAIM_WAIT; 366bac808feSMatthew Dillon kmalloc_raise_limit(hmp->m_inodes, 367bac808feSMatthew Dillon maxinodes * sizeof(struct hammer_inode)); 368bac808feSMatthew Dillon 369dd94f1b1SMatthew Dillon hmp->root_btree_beg.localization = 0x00000000U; 37047197d71SMatthew Dillon hmp->root_btree_beg.obj_id = -0x8000000000000000LL; 37147197d71SMatthew Dillon hmp->root_btree_beg.key = -0x8000000000000000LL; 37247197d71SMatthew Dillon hmp->root_btree_beg.create_tid = 1; 37347197d71SMatthew Dillon hmp->root_btree_beg.delete_tid = 1; 37447197d71SMatthew Dillon hmp->root_btree_beg.rec_type = 0; 37547197d71SMatthew Dillon hmp->root_btree_beg.obj_type = 0; 37647197d71SMatthew Dillon 377dd94f1b1SMatthew Dillon hmp->root_btree_end.localization = 0xFFFFFFFFU; 37847197d71SMatthew Dillon hmp->root_btree_end.obj_id = 0x7FFFFFFFFFFFFFFFLL; 37947197d71SMatthew Dillon hmp->root_btree_end.key = 0x7FFFFFFFFFFFFFFFLL; 38047197d71SMatthew Dillon hmp->root_btree_end.create_tid = 0xFFFFFFFFFFFFFFFFULL; 38147197d71SMatthew Dillon hmp->root_btree_end.delete_tid = 0; /* special case */ 38247197d71SMatthew Dillon hmp->root_btree_end.rec_type = 0xFFFFU; 38347197d71SMatthew Dillon hmp->root_btree_end.obj_type = 0; 384f03c9cf4SMatthew Dillon 385cdb6e4e6SMatthew Dillon hmp->krate.freq = 1; /* maximum reporting rate (hz) */ 386cdb6e4e6SMatthew Dillon hmp->krate.count = -16; /* initial burst */ 387cdb6e4e6SMatthew Dillon 3889480ff55SMatthew Dillon hmp->sync_lock.refs = 1; 389c9b9e29dSMatthew Dillon hmp->free_lock.refs = 1; 390d99d6bf5SMatthew Dillon hmp->undo_lock.refs = 1; 391d99d6bf5SMatthew Dillon hmp->blkmap_lock.refs = 1; 3929480ff55SMatthew Dillon 393cebe9493SMatthew Dillon TAILQ_INIT(&hmp->delay_list); 3947a61b85dSMatthew Dillon TAILQ_INIT(&hmp->flush_group_list); 3950729c8c8SMatthew Dillon TAILQ_INIT(&hmp->objid_cache_list); 396e8599db1SMatthew Dillon TAILQ_INIT(&hmp->undo_lru_list); 3977bc5b8c2SMatthew Dillon TAILQ_INIT(&hmp->reclaim_list); 398195c19a1SMatthew Dillon } 39951c35492SMatthew Dillon hmp->hflags &= ~HMNT_USERFLAGS; 40051c35492SMatthew Dillon hmp->hflags |= info.hflags & HMNT_USERFLAGS; 401732a1697SMatthew Dillon 402732a1697SMatthew Dillon hmp->master_id = master_id; 403732a1697SMatthew Dillon 4047f7c1f84SMatthew Dillon if (info.asof) { 4057f7c1f84SMatthew Dillon mp->mnt_flag |= MNT_RDONLY; 4067f7c1f84SMatthew Dillon hmp->asof = info.asof; 4077f7c1f84SMatthew Dillon } else { 4087f7c1f84SMatthew Dillon hmp->asof = HAMMER_MAX_TID; 4097f7c1f84SMatthew Dillon } 410195c19a1SMatthew Dillon 411195c19a1SMatthew Dillon /* 41251c35492SMatthew Dillon * Re-open read-write if originally read-only, or vise-versa. 413195c19a1SMatthew Dillon */ 414195c19a1SMatthew Dillon if (mp->mnt_flag & MNT_UPDATE) { 41551c35492SMatthew Dillon error = 0; 41651c35492SMatthew Dillon if (hmp->ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { 41751c35492SMatthew Dillon kprintf("HAMMER read-only -> read-write\n"); 418195c19a1SMatthew Dillon hmp->ronly = 0; 41951c35492SMatthew Dillon RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL, 42051c35492SMatthew Dillon hammer_adjust_volume_mode, NULL); 42151c35492SMatthew Dillon rootvol = hammer_get_root_volume(hmp, &error); 42251c35492SMatthew Dillon if (rootvol) { 42306ad81ffSMatthew Dillon hammer_recover_flush_buffers(hmp, rootvol, 1); 4249f5097dcSMatthew Dillon bcopy(rootvol->ondisk->vol0_blockmap, 4259f5097dcSMatthew Dillon hmp->blockmap, 4269f5097dcSMatthew Dillon sizeof(hmp->blockmap)); 42751c35492SMatthew Dillon hammer_rel_volume(rootvol, 0); 428195c19a1SMatthew Dillon } 42951c35492SMatthew Dillon RB_SCAN(hammer_ino_rb_tree, &hmp->rb_inos_root, NULL, 43051c35492SMatthew Dillon hammer_reload_inode, NULL); 43151c35492SMatthew Dillon /* kernel clears MNT_RDONLY */ 43251c35492SMatthew Dillon } else if (hmp->ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 43351c35492SMatthew Dillon kprintf("HAMMER read-write -> read-only\n"); 43451c35492SMatthew Dillon hmp->ronly = 1; /* messy */ 43551c35492SMatthew Dillon RB_SCAN(hammer_ino_rb_tree, &hmp->rb_inos_root, NULL, 43651c35492SMatthew Dillon hammer_reload_inode, NULL); 43751c35492SMatthew Dillon hmp->ronly = 0; 43851c35492SMatthew Dillon hammer_flusher_sync(hmp); 43951c35492SMatthew Dillon hammer_flusher_sync(hmp); 44051c35492SMatthew Dillon hammer_flusher_sync(hmp); 44151c35492SMatthew Dillon hmp->ronly = 1; 44251c35492SMatthew Dillon RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL, 44351c35492SMatthew Dillon hammer_adjust_volume_mode, NULL); 44451c35492SMatthew Dillon } 44551c35492SMatthew Dillon return(error); 446195c19a1SMatthew Dillon } 447195c19a1SMatthew Dillon 448427e5fc6SMatthew Dillon RB_INIT(&hmp->rb_vols_root); 449427e5fc6SMatthew Dillon RB_INIT(&hmp->rb_inos_root); 45040043e7fSMatthew Dillon RB_INIT(&hmp->rb_nods_root); 451e8599db1SMatthew Dillon RB_INIT(&hmp->rb_undo_root); 4520832c9bbSMatthew Dillon RB_INIT(&hmp->rb_resv_root); 4530832c9bbSMatthew Dillon RB_INIT(&hmp->rb_bufs_root); 4545fa5c92fSMatthew Dillon RB_INIT(&hmp->rb_pfsm_root); 4550832c9bbSMatthew Dillon 456195c19a1SMatthew Dillon hmp->ronly = ((mp->mnt_flag & MNT_RDONLY) != 0); 457427e5fc6SMatthew Dillon 45810a5d1baSMatthew Dillon TAILQ_INIT(&hmp->volu_list); 45910a5d1baSMatthew Dillon TAILQ_INIT(&hmp->undo_list); 46010a5d1baSMatthew Dillon TAILQ_INIT(&hmp->data_list); 46110a5d1baSMatthew Dillon TAILQ_INIT(&hmp->meta_list); 46210a5d1baSMatthew Dillon TAILQ_INIT(&hmp->lose_list); 46310a5d1baSMatthew Dillon 464427e5fc6SMatthew Dillon /* 465427e5fc6SMatthew Dillon * Load volumes 466427e5fc6SMatthew Dillon */ 467427e5fc6SMatthew Dillon path = objcache_get(namei_oc, M_WAITOK); 4681b0ab2c3SMatthew Dillon hmp->nvolumes = -1; 469427e5fc6SMatthew Dillon for (i = 0; i < info.nvolumes; ++i) { 4707c19b529SMichael Neumann if (mntpt == NULL) { 4717c19b529SMichael Neumann /* 4727c19b529SMichael Neumann * Root mount. 4737c19b529SMichael Neumann * Only one volume; and no need for copyin. 4747c19b529SMichael Neumann */ 4757c19b529SMichael Neumann KKASSERT(info.nvolumes == 1); 4767c19b529SMichael Neumann ksnprintf(path, MAXPATHLEN, "/dev/%s", 4777c19b529SMichael Neumann mp->mnt_stat.f_mntfromname); 4787c19b529SMichael Neumann error = 0; 4797c19b529SMichael Neumann } else { 4807c19b529SMichael Neumann error = copyin(&info.volumes[i], &upath, 4817c19b529SMichael Neumann sizeof(char *)); 482427e5fc6SMatthew Dillon if (error == 0) 4837c19b529SMichael Neumann error = copyinstr(upath, path, 4847c19b529SMichael Neumann MAXPATHLEN, NULL); 4857c19b529SMichael Neumann } 486427e5fc6SMatthew Dillon if (error == 0) 4877c19b529SMichael Neumann error = hammer_install_volume(hmp, path, devvp); 488427e5fc6SMatthew Dillon if (error) 489427e5fc6SMatthew Dillon break; 490427e5fc6SMatthew Dillon } 491427e5fc6SMatthew Dillon objcache_put(namei_oc, path); 492427e5fc6SMatthew Dillon 493427e5fc6SMatthew Dillon /* 494427e5fc6SMatthew Dillon * Make sure we found a root volume 495427e5fc6SMatthew Dillon */ 496427e5fc6SMatthew Dillon if (error == 0 && hmp->rootvol == NULL) { 497427e5fc6SMatthew Dillon kprintf("hammer_mount: No root volume found!\n"); 498427e5fc6SMatthew Dillon error = EINVAL; 499427e5fc6SMatthew Dillon } 5001b0ab2c3SMatthew Dillon 5011b0ab2c3SMatthew Dillon /* 5021b0ab2c3SMatthew Dillon * Check that all required volumes are available 5031b0ab2c3SMatthew Dillon */ 5041b0ab2c3SMatthew Dillon if (error == 0 && hammer_mountcheck_volumes(hmp)) { 5051b0ab2c3SMatthew Dillon kprintf("hammer_mount: Missing volumes, cannot mount!\n"); 5061b0ab2c3SMatthew Dillon error = EINVAL; 5071b0ab2c3SMatthew Dillon } 5081b0ab2c3SMatthew Dillon 509427e5fc6SMatthew Dillon if (error) { 510427e5fc6SMatthew Dillon hammer_free_hmp(mp); 511427e5fc6SMatthew Dillon return (error); 512427e5fc6SMatthew Dillon } 513427e5fc6SMatthew Dillon 514427e5fc6SMatthew Dillon /* 51527ea2398SMatthew Dillon * No errors, setup enough of the mount point so we can lookup the 51627ea2398SMatthew Dillon * root vnode. 517427e5fc6SMatthew Dillon */ 518427e5fc6SMatthew Dillon mp->mnt_iosize_max = MAXPHYS; 519427e5fc6SMatthew Dillon mp->mnt_kern_flag |= MNTK_FSMID; 520c0ade690SMatthew Dillon 521c0ade690SMatthew Dillon /* 522c0ade690SMatthew Dillon * note: f_iosize is used by vnode_pager_haspage() when constructing 523c0ade690SMatthew Dillon * its VOP_BMAP call. 524c0ade690SMatthew Dillon */ 525c0ade690SMatthew Dillon mp->mnt_stat.f_iosize = HAMMER_BUFSIZE; 526fbc6e32aSMatthew Dillon mp->mnt_stat.f_bsize = HAMMER_BUFSIZE; 5276f97fce3SMatthew Dillon 5286f97fce3SMatthew Dillon mp->mnt_vstat.f_frsize = HAMMER_BUFSIZE; 5296f97fce3SMatthew Dillon mp->mnt_vstat.f_bsize = HAMMER_BUFSIZE; 5306f97fce3SMatthew Dillon 531427e5fc6SMatthew Dillon mp->mnt_maxsymlinklen = 255; 532427e5fc6SMatthew Dillon mp->mnt_flag |= MNT_LOCAL; 533427e5fc6SMatthew Dillon 534427e5fc6SMatthew Dillon vfs_add_vnodeops(mp, &hammer_vnode_vops, &mp->mnt_vn_norm_ops); 5357a04d74fSMatthew Dillon vfs_add_vnodeops(mp, &hammer_spec_vops, &mp->mnt_vn_spec_ops); 5367a04d74fSMatthew Dillon vfs_add_vnodeops(mp, &hammer_fifo_vops, &mp->mnt_vn_fifo_ops); 53727ea2398SMatthew Dillon 53827ea2398SMatthew Dillon /* 539a89aec1bSMatthew Dillon * The root volume's ondisk pointer is only valid if we hold a 540a89aec1bSMatthew Dillon * reference to it. 541a89aec1bSMatthew Dillon */ 542a89aec1bSMatthew Dillon rootvol = hammer_get_root_volume(hmp, &error); 543a89aec1bSMatthew Dillon if (error) 544f90dde4cSMatthew Dillon goto failed; 545f90dde4cSMatthew Dillon 546f90dde4cSMatthew Dillon /* 5479f5097dcSMatthew Dillon * Perform any necessary UNDO operations. The recovery code does 5480729c8c8SMatthew Dillon * call hammer_undo_lookup() so we have to pre-cache the blockmap, 5490729c8c8SMatthew Dillon * and then re-copy it again after recovery is complete. 550c9b9e29dSMatthew Dillon * 55151c35492SMatthew Dillon * If this is a read-only mount the UNDO information is retained 55251c35492SMatthew Dillon * in memory in the form of dirty buffer cache buffers, and not 55351c35492SMatthew Dillon * written back to the media. 554f90dde4cSMatthew Dillon */ 5550729c8c8SMatthew Dillon bcopy(rootvol->ondisk->vol0_blockmap, hmp->blockmap, 5560729c8c8SMatthew Dillon sizeof(hmp->blockmap)); 557c9b9e29dSMatthew Dillon 5587a61b85dSMatthew Dillon /* 55944a83111SMatthew Dillon * Check filesystem version 56044a83111SMatthew Dillon */ 56144a83111SMatthew Dillon hmp->version = rootvol->ondisk->vol_version; 56244a83111SMatthew Dillon if (hmp->version < HAMMER_VOL_VERSION_MIN || 56344a83111SMatthew Dillon hmp->version > HAMMER_VOL_VERSION_MAX) { 56444a83111SMatthew Dillon kprintf("HAMMER: mount unsupported fs version %d\n", 56544a83111SMatthew Dillon hmp->version); 56644a83111SMatthew Dillon error = ERANGE; 56744a83111SMatthew Dillon goto done; 56844a83111SMatthew Dillon } 56944a83111SMatthew Dillon 57044a83111SMatthew Dillon /* 5717a61b85dSMatthew Dillon * The undo_rec_limit limits the size of flush groups to avoid 5727a61b85dSMatthew Dillon * blowing out the UNDO FIFO. This calculation is typically in 5737a61b85dSMatthew Dillon * the tens of thousands and is designed primarily when small 5747a61b85dSMatthew Dillon * HAMMER filesystems are created. 5757a61b85dSMatthew Dillon */ 5767a61b85dSMatthew Dillon hmp->undo_rec_limit = hammer_undo_max(hmp) / 8192 + 100; 5777a61b85dSMatthew Dillon if (hammer_debug_general & 0x0001) 5787a61b85dSMatthew Dillon kprintf("HAMMER: undo_rec_limit %d\n", hmp->undo_rec_limit); 5797a61b85dSMatthew Dillon 580f90dde4cSMatthew Dillon error = hammer_recover(hmp, rootvol); 581f90dde4cSMatthew Dillon if (error) { 582f90dde4cSMatthew Dillon kprintf("Failed to recover HAMMER filesystem on mount\n"); 583a89aec1bSMatthew Dillon goto done; 584f90dde4cSMatthew Dillon } 585f90dde4cSMatthew Dillon 586f90dde4cSMatthew Dillon /* 587adf01747SMatthew Dillon * Finish setup now that we have a good root volume. 588adf01747SMatthew Dillon * 589adf01747SMatthew Dillon * The top 16 bits of fsid.val[1] is a pfs id. 590f90dde4cSMatthew Dillon */ 591a89aec1bSMatthew Dillon ksnprintf(mp->mnt_stat.f_mntfromname, 592a89aec1bSMatthew Dillon sizeof(mp->mnt_stat.f_mntfromname), "%s", 593a89aec1bSMatthew Dillon rootvol->ondisk->vol_name); 594513ca7d7SMatthew Dillon mp->mnt_stat.f_fsid.val[0] = 595513ca7d7SMatthew Dillon crc32((char *)&rootvol->ondisk->vol_fsid + 0, 8); 596513ca7d7SMatthew Dillon mp->mnt_stat.f_fsid.val[1] = 597513ca7d7SMatthew Dillon crc32((char *)&rootvol->ondisk->vol_fsid + 8, 8); 598adf01747SMatthew Dillon mp->mnt_stat.f_fsid.val[1] &= 0x0000FFFF; 599b84de5afSMatthew Dillon 6006f97fce3SMatthew Dillon mp->mnt_vstat.f_fsid_uuid = rootvol->ondisk->vol_fsid; 6016f97fce3SMatthew Dillon mp->mnt_vstat.f_fsid = crc32(&mp->mnt_vstat.f_fsid_uuid, 6026f97fce3SMatthew Dillon sizeof(mp->mnt_vstat.f_fsid_uuid)); 6036f97fce3SMatthew Dillon 6040729c8c8SMatthew Dillon /* 6050729c8c8SMatthew Dillon * Certain often-modified fields in the root volume are cached in 6060729c8c8SMatthew Dillon * the hammer_mount structure so we do not have to generate lots 6070729c8c8SMatthew Dillon * of little UNDO structures for them. 608c9b9e29dSMatthew Dillon * 6099f5097dcSMatthew Dillon * Recopy after recovery. This also has the side effect of 6109f5097dcSMatthew Dillon * setting our cached undo FIFO's first_offset, which serves to 6119f5097dcSMatthew Dillon * placemark the FIFO start for the NEXT flush cycle while the 6129f5097dcSMatthew Dillon * on-disk first_offset represents the LAST flush cycle. 6130729c8c8SMatthew Dillon */ 614b84de5afSMatthew Dillon hmp->next_tid = rootvol->ondisk->vol0_next_tid; 6154889cbd4SMatthew Dillon hmp->flush_tid1 = hmp->next_tid; 6164889cbd4SMatthew Dillon hmp->flush_tid2 = hmp->next_tid; 6170729c8c8SMatthew Dillon bcopy(rootvol->ondisk->vol0_blockmap, hmp->blockmap, 6180729c8c8SMatthew Dillon sizeof(hmp->blockmap)); 619e63644f0SMatthew Dillon hmp->copy_stat_freebigblocks = rootvol->ondisk->vol0_stat_freebigblocks; 6200729c8c8SMatthew Dillon 621059819e3SMatthew Dillon hammer_flusher_create(hmp); 622059819e3SMatthew Dillon 623a89aec1bSMatthew Dillon /* 62427ea2398SMatthew Dillon * Locate the root directory using the root cluster's B-Tree as a 62527ea2398SMatthew Dillon * starting point. The root directory uses an obj_id of 1. 62627ea2398SMatthew Dillon * 62727ea2398SMatthew Dillon * FUTURE: Leave the root directory cached referenced but unlocked 62827ea2398SMatthew Dillon * in hmp->rootvp (need to flush it on unmount). 62927ea2398SMatthew Dillon */ 63027ea2398SMatthew Dillon error = hammer_vfs_vget(mp, 1, &rootvp); 631a89aec1bSMatthew Dillon if (error) 632a89aec1bSMatthew Dillon goto done; 63327ea2398SMatthew Dillon vput(rootvp); 63427ea2398SMatthew Dillon /*vn_unlock(hmp->rootvp);*/ 63527ea2398SMatthew Dillon 636a89aec1bSMatthew Dillon done: 637f90dde4cSMatthew Dillon hammer_rel_volume(rootvol, 0); 638f90dde4cSMatthew Dillon failed: 63927ea2398SMatthew Dillon /* 64027ea2398SMatthew Dillon * Cleanup and return. 64127ea2398SMatthew Dillon */ 64227ea2398SMatthew Dillon if (error) 64327ea2398SMatthew Dillon hammer_free_hmp(mp); 644427e5fc6SMatthew Dillon return (error); 645427e5fc6SMatthew Dillon } 646427e5fc6SMatthew Dillon 647427e5fc6SMatthew Dillon static int 648427e5fc6SMatthew Dillon hammer_vfs_unmount(struct mount *mp, int mntflags) 649427e5fc6SMatthew Dillon { 650427e5fc6SMatthew Dillon #if 0 651427e5fc6SMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 652427e5fc6SMatthew Dillon #endif 653427e5fc6SMatthew Dillon int flags; 65466325755SMatthew Dillon int error; 65527ea2398SMatthew Dillon 65627ea2398SMatthew Dillon /* 657427e5fc6SMatthew Dillon * Clean out the vnodes 658427e5fc6SMatthew Dillon */ 65966325755SMatthew Dillon flags = 0; 66066325755SMatthew Dillon if (mntflags & MNT_FORCE) 66166325755SMatthew Dillon flags |= FORCECLOSE; 66266325755SMatthew Dillon if ((error = vflush(mp, 0, flags)) != 0) 66366325755SMatthew Dillon return (error); 664427e5fc6SMatthew Dillon 665427e5fc6SMatthew Dillon /* 666427e5fc6SMatthew Dillon * Clean up the internal mount structure and related entities. This 667427e5fc6SMatthew Dillon * may issue I/O. 668427e5fc6SMatthew Dillon */ 669427e5fc6SMatthew Dillon hammer_free_hmp(mp); 670427e5fc6SMatthew Dillon return(0); 671427e5fc6SMatthew Dillon } 672427e5fc6SMatthew Dillon 673427e5fc6SMatthew Dillon /* 674427e5fc6SMatthew Dillon * Clean up the internal mount structure and disassociate it from the mount. 675427e5fc6SMatthew Dillon * This may issue I/O. 676427e5fc6SMatthew Dillon */ 677427e5fc6SMatthew Dillon static void 678427e5fc6SMatthew Dillon hammer_free_hmp(struct mount *mp) 679427e5fc6SMatthew Dillon { 680427e5fc6SMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 681cdb6e4e6SMatthew Dillon hammer_flush_group_t flg; 6821b0ab2c3SMatthew Dillon int count; 683d40bfecaSMatthew Dillon int dummy; 684427e5fc6SMatthew Dillon 685427e5fc6SMatthew Dillon /* 686cdb6e4e6SMatthew Dillon * Flush anything dirty. This won't even run if the 687cdb6e4e6SMatthew Dillon * filesystem errored-out. 688427e5fc6SMatthew Dillon */ 6891b0ab2c3SMatthew Dillon count = 0; 6901b0ab2c3SMatthew Dillon while (hammer_flusher_haswork(hmp)) { 691059819e3SMatthew Dillon hammer_flusher_sync(hmp); 6921b0ab2c3SMatthew Dillon ++count; 6931b0ab2c3SMatthew Dillon if (count >= 5) { 6941b0ab2c3SMatthew Dillon if (count == 5) 6951b0ab2c3SMatthew Dillon kprintf("HAMMER: umount flushing."); 6961b0ab2c3SMatthew Dillon else 6971b0ab2c3SMatthew Dillon kprintf("."); 698d40bfecaSMatthew Dillon tsleep(&dummy, 0, "hmrufl", hz); 6991b0ab2c3SMatthew Dillon } 7001b0ab2c3SMatthew Dillon if (count == 30) { 7011b0ab2c3SMatthew Dillon kprintf("giving up\n"); 7021b0ab2c3SMatthew Dillon break; 7031b0ab2c3SMatthew Dillon } 7041b0ab2c3SMatthew Dillon } 7051b0ab2c3SMatthew Dillon if (count >= 5 && count < 30) 7061b0ab2c3SMatthew Dillon kprintf("\n"); 707cdb6e4e6SMatthew Dillon 708cdb6e4e6SMatthew Dillon /* 709cdb6e4e6SMatthew Dillon * If the mount had a critical error we have to destroy any 710cdb6e4e6SMatthew Dillon * remaining inodes before we can finish cleaning up the flusher. 711cdb6e4e6SMatthew Dillon */ 712cdb6e4e6SMatthew Dillon if (hmp->flags & HAMMER_MOUNT_CRITICAL_ERROR) { 713cdb6e4e6SMatthew Dillon RB_SCAN(hammer_ino_rb_tree, &hmp->rb_inos_root, NULL, 714cdb6e4e6SMatthew Dillon hammer_destroy_inode_callback, NULL); 715cdb6e4e6SMatthew Dillon } 716cdb6e4e6SMatthew Dillon 717cdb6e4e6SMatthew Dillon /* 718cdb6e4e6SMatthew Dillon * There shouldn't be any inodes left now and any left over 719cdb6e4e6SMatthew Dillon * flush groups should now be empty. 720cdb6e4e6SMatthew Dillon */ 721cdb6e4e6SMatthew Dillon KKASSERT(RB_EMPTY(&hmp->rb_inos_root)); 722cdb6e4e6SMatthew Dillon while ((flg = TAILQ_FIRST(&hmp->flush_group_list)) != NULL) { 723cdb6e4e6SMatthew Dillon TAILQ_REMOVE(&hmp->flush_group_list, flg, flush_entry); 724cdb6e4e6SMatthew Dillon KKASSERT(TAILQ_EMPTY(&flg->flush_list)); 725cdb6e4e6SMatthew Dillon if (flg->refs) { 726cdb6e4e6SMatthew Dillon kprintf("HAMMER: Warning, flush_group %p was " 727cdb6e4e6SMatthew Dillon "not empty on umount!\n", flg); 728cdb6e4e6SMatthew Dillon } 729bac808feSMatthew Dillon kfree(flg, hmp->m_misc); 730cdb6e4e6SMatthew Dillon } 731cdb6e4e6SMatthew Dillon 732cdb6e4e6SMatthew Dillon /* 733cdb6e4e6SMatthew Dillon * We can finally destroy the flusher 734cdb6e4e6SMatthew Dillon */ 735059819e3SMatthew Dillon hammer_flusher_destroy(hmp); 736427e5fc6SMatthew Dillon 737b84de5afSMatthew Dillon /* 73800f16fadSMatthew Dillon * We may have held recovered buffers due to a read-only mount. 73900f16fadSMatthew Dillon * These must be discarded. 74000f16fadSMatthew Dillon */ 74100f16fadSMatthew Dillon if (hmp->ronly) 74200f16fadSMatthew Dillon hammer_recover_flush_buffers(hmp, NULL, -1); 74300f16fadSMatthew Dillon 74400f16fadSMatthew Dillon /* 7450832c9bbSMatthew Dillon * Unload buffers and then volumes 746b84de5afSMatthew Dillon */ 7470832c9bbSMatthew Dillon RB_SCAN(hammer_buf_rb_tree, &hmp->rb_bufs_root, NULL, 7480832c9bbSMatthew Dillon hammer_unload_buffer, NULL); 749427e5fc6SMatthew Dillon RB_SCAN(hammer_vol_rb_tree, &hmp->rb_vols_root, NULL, 750427e5fc6SMatthew Dillon hammer_unload_volume, NULL); 751427e5fc6SMatthew Dillon 752427e5fc6SMatthew Dillon mp->mnt_data = NULL; 75366325755SMatthew Dillon mp->mnt_flag &= ~MNT_LOCAL; 754427e5fc6SMatthew Dillon hmp->mp = NULL; 7550729c8c8SMatthew Dillon hammer_destroy_objid_cache(hmp); 756bac808feSMatthew Dillon kmalloc_destroy(&hmp->m_misc); 757bac808feSMatthew Dillon kmalloc_destroy(&hmp->m_inodes); 758427e5fc6SMatthew Dillon kfree(hmp, M_HAMMER); 759427e5fc6SMatthew Dillon } 760427e5fc6SMatthew Dillon 761427e5fc6SMatthew Dillon /* 762cdb6e4e6SMatthew Dillon * Report critical errors. ip may be NULL. 763cdb6e4e6SMatthew Dillon */ 764cdb6e4e6SMatthew Dillon void 765cdb6e4e6SMatthew Dillon hammer_critical_error(hammer_mount_t hmp, hammer_inode_t ip, 766cdb6e4e6SMatthew Dillon int error, const char *msg) 767cdb6e4e6SMatthew Dillon { 768cdb6e4e6SMatthew Dillon hmp->flags |= HAMMER_MOUNT_CRITICAL_ERROR; 769cdb6e4e6SMatthew Dillon krateprintf(&hmp->krate, 770cdb6e4e6SMatthew Dillon "HAMMER(%s): Critical error inode=%lld %s\n", 771cdb6e4e6SMatthew Dillon hmp->mp->mnt_stat.f_mntfromname, 772973c11b9SMatthew Dillon (long long)(ip ? ip->obj_id : -1), msg); 773cdb6e4e6SMatthew Dillon if (hmp->ronly == 0) { 774cdb6e4e6SMatthew Dillon hmp->ronly = 2; /* special errored read-only mode */ 775cdb6e4e6SMatthew Dillon hmp->mp->mnt_flag |= MNT_RDONLY; 776cdb6e4e6SMatthew Dillon kprintf("HAMMER(%s): Forcing read-only mode\n", 777cdb6e4e6SMatthew Dillon hmp->mp->mnt_stat.f_mntfromname); 778cdb6e4e6SMatthew Dillon } 779cdb6e4e6SMatthew Dillon hmp->error = error; 780cdb6e4e6SMatthew Dillon } 781cdb6e4e6SMatthew Dillon 782cdb6e4e6SMatthew Dillon 783cdb6e4e6SMatthew Dillon /* 784513ca7d7SMatthew Dillon * Obtain a vnode for the specified inode number. An exclusively locked 785513ca7d7SMatthew Dillon * vnode is returned. 786513ca7d7SMatthew Dillon */ 787513ca7d7SMatthew Dillon int 788513ca7d7SMatthew Dillon hammer_vfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) 789513ca7d7SMatthew Dillon { 79036f82b23SMatthew Dillon struct hammer_transaction trans; 791513ca7d7SMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 792513ca7d7SMatthew Dillon struct hammer_inode *ip; 793513ca7d7SMatthew Dillon int error; 794513ca7d7SMatthew Dillon 79536f82b23SMatthew Dillon hammer_simple_transaction(&trans, hmp); 79636f82b23SMatthew Dillon 797513ca7d7SMatthew Dillon /* 79836f82b23SMatthew Dillon * Lookup the requested HAMMER inode. The structure must be 79936f82b23SMatthew Dillon * left unlocked while we manipulate the related vnode to avoid 80036f82b23SMatthew Dillon * a deadlock. 801513ca7d7SMatthew Dillon */ 802ddfdf542SMatthew Dillon ip = hammer_get_inode(&trans, NULL, ino, 803ddfdf542SMatthew Dillon hmp->asof, HAMMER_DEF_LOCALIZATION, 804ddfdf542SMatthew Dillon 0, &error); 805513ca7d7SMatthew Dillon if (ip == NULL) { 806513ca7d7SMatthew Dillon *vpp = NULL; 80700f16fadSMatthew Dillon hammer_done_transaction(&trans); 808513ca7d7SMatthew Dillon return(error); 809513ca7d7SMatthew Dillon } 810e8599db1SMatthew Dillon error = hammer_get_vnode(ip, vpp); 811513ca7d7SMatthew Dillon hammer_rel_inode(ip, 0); 812b84de5afSMatthew Dillon hammer_done_transaction(&trans); 813513ca7d7SMatthew Dillon return (error); 814513ca7d7SMatthew Dillon } 815513ca7d7SMatthew Dillon 816513ca7d7SMatthew Dillon /* 817427e5fc6SMatthew Dillon * Return the root vnode for the filesystem. 818427e5fc6SMatthew Dillon * 819427e5fc6SMatthew Dillon * HAMMER stores the root vnode in the hammer_mount structure so 820427e5fc6SMatthew Dillon * getting it is easy. 821427e5fc6SMatthew Dillon */ 822427e5fc6SMatthew Dillon static int 823427e5fc6SMatthew Dillon hammer_vfs_root(struct mount *mp, struct vnode **vpp) 824427e5fc6SMatthew Dillon { 82547197d71SMatthew Dillon #if 0 826427e5fc6SMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 82747197d71SMatthew Dillon #endif 82827ea2398SMatthew Dillon int error; 829427e5fc6SMatthew Dillon 83027ea2398SMatthew Dillon error = hammer_vfs_vget(mp, 1, vpp); 83127ea2398SMatthew Dillon return (error); 832427e5fc6SMatthew Dillon } 833427e5fc6SMatthew Dillon 834427e5fc6SMatthew Dillon static int 835427e5fc6SMatthew Dillon hammer_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 836427e5fc6SMatthew Dillon { 837fbc6e32aSMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 838fbc6e32aSMatthew Dillon hammer_volume_t volume; 839fbc6e32aSMatthew Dillon hammer_volume_ondisk_t ondisk; 840fbc6e32aSMatthew Dillon int error; 84147197d71SMatthew Dillon int64_t bfree; 842*31a56ce2SMatthew Dillon int64_t breserved; 843fbc6e32aSMatthew Dillon 844fbc6e32aSMatthew Dillon volume = hammer_get_root_volume(hmp, &error); 845fbc6e32aSMatthew Dillon if (error) 846fbc6e32aSMatthew Dillon return(error); 847fbc6e32aSMatthew Dillon ondisk = volume->ondisk; 848fbc6e32aSMatthew Dillon 84947197d71SMatthew Dillon /* 85047197d71SMatthew Dillon * Basic stats 85147197d71SMatthew Dillon */ 852*31a56ce2SMatthew Dillon _hammer_checkspace(hmp, HAMMER_CHKSPC_WRITE, &breserved); 853fbc6e32aSMatthew Dillon mp->mnt_stat.f_files = ondisk->vol0_stat_inodes; 854c3be93f2SMatthew Dillon bfree = ondisk->vol0_stat_freebigblocks * HAMMER_LARGEBLOCK_SIZE; 85540043e7fSMatthew Dillon hammer_rel_volume(volume, 0); 85647197d71SMatthew Dillon 857*31a56ce2SMatthew Dillon mp->mnt_stat.f_bfree = (bfree - breserved) / HAMMER_BUFSIZE; 85847197d71SMatthew Dillon mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree; 859fbc6e32aSMatthew Dillon if (mp->mnt_stat.f_files < 0) 860fbc6e32aSMatthew Dillon mp->mnt_stat.f_files = 0; 861fbc6e32aSMatthew Dillon 86227ea2398SMatthew Dillon *sbp = mp->mnt_stat; 86327ea2398SMatthew Dillon return(0); 864427e5fc6SMatthew Dillon } 865427e5fc6SMatthew Dillon 8666f97fce3SMatthew Dillon static int 8676f97fce3SMatthew Dillon hammer_vfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) 8686f97fce3SMatthew Dillon { 8696f97fce3SMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 8706f97fce3SMatthew Dillon hammer_volume_t volume; 8716f97fce3SMatthew Dillon hammer_volume_ondisk_t ondisk; 8726f97fce3SMatthew Dillon int error; 8736f97fce3SMatthew Dillon int64_t bfree; 8740f65be10SMatthew Dillon int64_t breserved; 8756f97fce3SMatthew Dillon 8766f97fce3SMatthew Dillon volume = hammer_get_root_volume(hmp, &error); 8776f97fce3SMatthew Dillon if (error) 8786f97fce3SMatthew Dillon return(error); 8796f97fce3SMatthew Dillon ondisk = volume->ondisk; 8806f97fce3SMatthew Dillon 8816f97fce3SMatthew Dillon /* 8826f97fce3SMatthew Dillon * Basic stats 8836f97fce3SMatthew Dillon */ 8840f65be10SMatthew Dillon _hammer_checkspace(hmp, HAMMER_CHKSPC_WRITE, &breserved); 8856f97fce3SMatthew Dillon mp->mnt_vstat.f_files = ondisk->vol0_stat_inodes; 8866f97fce3SMatthew Dillon bfree = ondisk->vol0_stat_freebigblocks * HAMMER_LARGEBLOCK_SIZE; 8876f97fce3SMatthew Dillon hammer_rel_volume(volume, 0); 8886f97fce3SMatthew Dillon 8890f65be10SMatthew Dillon mp->mnt_vstat.f_bfree = (bfree - breserved) / HAMMER_BUFSIZE; 8906f97fce3SMatthew Dillon mp->mnt_vstat.f_bavail = mp->mnt_stat.f_bfree; 8916f97fce3SMatthew Dillon if (mp->mnt_vstat.f_files < 0) 8926f97fce3SMatthew Dillon mp->mnt_vstat.f_files = 0; 8936f97fce3SMatthew Dillon *sbp = mp->mnt_vstat; 8946f97fce3SMatthew Dillon return(0); 8956f97fce3SMatthew Dillon } 8966f97fce3SMatthew Dillon 8970729c8c8SMatthew Dillon /* 8980729c8c8SMatthew Dillon * Sync the filesystem. Currently we have to run it twice, the second 8990729c8c8SMatthew Dillon * one will advance the undo start index to the end index, so if a crash 9000729c8c8SMatthew Dillon * occurs no undos will be run on mount. 90177062c8aSMatthew Dillon * 90277062c8aSMatthew Dillon * We do not sync the filesystem if we are called from a panic. If we did 90377062c8aSMatthew Dillon * we might end up blowing up a sync that was already in progress. 9040729c8c8SMatthew Dillon */ 905427e5fc6SMatthew Dillon static int 906427e5fc6SMatthew Dillon hammer_vfs_sync(struct mount *mp, int waitfor) 907427e5fc6SMatthew Dillon { 908fbc6e32aSMatthew Dillon struct hammer_mount *hmp = (void *)mp->mnt_data; 9090729c8c8SMatthew Dillon int error; 9100729c8c8SMatthew Dillon 91177062c8aSMatthew Dillon if (panicstr == NULL) { 9120729c8c8SMatthew Dillon error = hammer_sync_hmp(hmp, waitfor); 91377062c8aSMatthew Dillon } else { 91477062c8aSMatthew Dillon error = EIO; 91577062c8aSMatthew Dillon } 9160729c8c8SMatthew Dillon return (error); 917427e5fc6SMatthew Dillon } 918427e5fc6SMatthew Dillon 919513ca7d7SMatthew Dillon /* 920513ca7d7SMatthew Dillon * Convert a vnode to a file handle. 921513ca7d7SMatthew Dillon */ 922513ca7d7SMatthew Dillon static int 923513ca7d7SMatthew Dillon hammer_vfs_vptofh(struct vnode *vp, struct fid *fhp) 924513ca7d7SMatthew Dillon { 925513ca7d7SMatthew Dillon hammer_inode_t ip; 926513ca7d7SMatthew Dillon 927513ca7d7SMatthew Dillon KKASSERT(MAXFIDSZ >= 16); 928513ca7d7SMatthew Dillon ip = VTOI(vp); 929513ca7d7SMatthew Dillon fhp->fid_len = offsetof(struct fid, fid_data[16]); 930adf01747SMatthew Dillon fhp->fid_ext = ip->obj_localization >> 16; 931513ca7d7SMatthew Dillon bcopy(&ip->obj_id, fhp->fid_data + 0, sizeof(ip->obj_id)); 932513ca7d7SMatthew Dillon bcopy(&ip->obj_asof, fhp->fid_data + 8, sizeof(ip->obj_asof)); 933513ca7d7SMatthew Dillon return(0); 934513ca7d7SMatthew Dillon } 935513ca7d7SMatthew Dillon 936513ca7d7SMatthew Dillon 937513ca7d7SMatthew Dillon /* 938513ca7d7SMatthew Dillon * Convert a file handle back to a vnode. 93967863d04SMatthew Dillon * 94067863d04SMatthew Dillon * Use rootvp to enforce PFS isolation when a PFS is exported via a 94167863d04SMatthew Dillon * null mount. 942513ca7d7SMatthew Dillon */ 943513ca7d7SMatthew Dillon static int 94467863d04SMatthew Dillon hammer_vfs_fhtovp(struct mount *mp, struct vnode *rootvp, 94567863d04SMatthew Dillon struct fid *fhp, struct vnode **vpp) 946513ca7d7SMatthew Dillon { 94736f82b23SMatthew Dillon struct hammer_transaction trans; 948513ca7d7SMatthew Dillon struct hammer_inode *ip; 949513ca7d7SMatthew Dillon struct hammer_inode_info info; 950513ca7d7SMatthew Dillon int error; 951adf01747SMatthew Dillon u_int32_t localization; 952513ca7d7SMatthew Dillon 953513ca7d7SMatthew Dillon bcopy(fhp->fid_data + 0, &info.obj_id, sizeof(info.obj_id)); 954513ca7d7SMatthew Dillon bcopy(fhp->fid_data + 8, &info.obj_asof, sizeof(info.obj_asof)); 95567863d04SMatthew Dillon if (rootvp) 95667863d04SMatthew Dillon localization = VTOI(rootvp)->obj_localization; 95767863d04SMatthew Dillon else 958adf01747SMatthew Dillon localization = (u_int32_t)fhp->fid_ext << 16; 959513ca7d7SMatthew Dillon 96036f82b23SMatthew Dillon hammer_simple_transaction(&trans, (void *)mp->mnt_data); 96136f82b23SMatthew Dillon 962513ca7d7SMatthew Dillon /* 963513ca7d7SMatthew Dillon * Get/allocate the hammer_inode structure. The structure must be 964513ca7d7SMatthew Dillon * unlocked while we manipulate the related vnode to avoid a 965513ca7d7SMatthew Dillon * deadlock. 966513ca7d7SMatthew Dillon */ 967ddfdf542SMatthew Dillon ip = hammer_get_inode(&trans, NULL, info.obj_id, 968adf01747SMatthew Dillon info.obj_asof, localization, 0, &error); 969513ca7d7SMatthew Dillon if (ip == NULL) { 970513ca7d7SMatthew Dillon *vpp = NULL; 971513ca7d7SMatthew Dillon return(error); 972513ca7d7SMatthew Dillon } 973e8599db1SMatthew Dillon error = hammer_get_vnode(ip, vpp); 974513ca7d7SMatthew Dillon hammer_rel_inode(ip, 0); 975b84de5afSMatthew Dillon hammer_done_transaction(&trans); 976513ca7d7SMatthew Dillon return (error); 977513ca7d7SMatthew Dillon } 978513ca7d7SMatthew Dillon 979513ca7d7SMatthew Dillon static int 980513ca7d7SMatthew Dillon hammer_vfs_checkexp(struct mount *mp, struct sockaddr *nam, 981513ca7d7SMatthew Dillon int *exflagsp, struct ucred **credanonp) 982513ca7d7SMatthew Dillon { 983513ca7d7SMatthew Dillon hammer_mount_t hmp = (void *)mp->mnt_data; 984513ca7d7SMatthew Dillon struct netcred *np; 985513ca7d7SMatthew Dillon int error; 986513ca7d7SMatthew Dillon 987513ca7d7SMatthew Dillon np = vfs_export_lookup(mp, &hmp->export, nam); 988513ca7d7SMatthew Dillon if (np) { 989513ca7d7SMatthew Dillon *exflagsp = np->netc_exflags; 990513ca7d7SMatthew Dillon *credanonp = &np->netc_anon; 991513ca7d7SMatthew Dillon error = 0; 992513ca7d7SMatthew Dillon } else { 993513ca7d7SMatthew Dillon error = EACCES; 994513ca7d7SMatthew Dillon } 995513ca7d7SMatthew Dillon return (error); 996513ca7d7SMatthew Dillon 997513ca7d7SMatthew Dillon } 998513ca7d7SMatthew Dillon 999513ca7d7SMatthew Dillon int 1000513ca7d7SMatthew Dillon hammer_vfs_export(struct mount *mp, int op, const struct export_args *export) 1001513ca7d7SMatthew Dillon { 1002513ca7d7SMatthew Dillon hammer_mount_t hmp = (void *)mp->mnt_data; 1003513ca7d7SMatthew Dillon int error; 1004513ca7d7SMatthew Dillon 1005513ca7d7SMatthew Dillon switch(op) { 1006513ca7d7SMatthew Dillon case MOUNTCTL_SET_EXPORT: 1007513ca7d7SMatthew Dillon error = vfs_export(mp, &hmp->export, export); 1008513ca7d7SMatthew Dillon break; 1009513ca7d7SMatthew Dillon default: 1010513ca7d7SMatthew Dillon error = EOPNOTSUPP; 1011513ca7d7SMatthew Dillon break; 1012513ca7d7SMatthew Dillon } 1013513ca7d7SMatthew Dillon return(error); 1014513ca7d7SMatthew Dillon } 1015513ca7d7SMatthew Dillon 1016