1 /*- 2 * Copyright (c) 2011-2013 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * by Daniel Flores (GSOC 2013 - mentored by Matthew Dillon, compression) 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/nlookup.h> 39 #include <sys/vnode.h> 40 #include <sys/mount.h> 41 #include <sys/fcntl.h> 42 #include <sys/buf.h> 43 #include <sys/uuid.h> 44 #include <sys/vfsops.h> 45 #include <sys/sysctl.h> 46 #include <sys/socket.h> 47 #include <sys/objcache.h> 48 49 #include <sys/proc.h> 50 #include <sys/namei.h> 51 #include <sys/mountctl.h> 52 #include <sys/dirent.h> 53 #include <sys/uio.h> 54 55 #include <sys/mutex.h> 56 #include <sys/mutex2.h> 57 58 #include "hammer2.h" 59 #include "hammer2_disk.h" 60 #include "hammer2_mount.h" 61 62 #include "hammer2.h" 63 #include "hammer2_lz4.h" 64 65 #include "zlib/hammer2_zlib.h" 66 67 #define REPORT_REFS_ERRORS 1 /* XXX remove me */ 68 69 MALLOC_DEFINE(M_OBJCACHE, "objcache", "Object Cache"); 70 71 struct hammer2_sync_info { 72 hammer2_trans_t trans; 73 int error; 74 int waitfor; 75 }; 76 77 TAILQ_HEAD(hammer2_mntlist, hammer2_mount); 78 static struct hammer2_mntlist hammer2_mntlist; 79 static struct lock hammer2_mntlk; 80 81 int hammer2_debug; 82 int hammer2_cluster_enable = 1; 83 int hammer2_hardlink_enable = 1; 84 int hammer2_flush_pipe = 100; 85 long hammer2_limit_dirty_chains; 86 long hammer2_iod_file_read; 87 long hammer2_iod_meta_read; 88 long hammer2_iod_indr_read; 89 long hammer2_iod_fmap_read; 90 long hammer2_iod_volu_read; 91 long hammer2_iod_file_write; 92 long hammer2_iod_meta_write; 93 long hammer2_iod_indr_write; 94 long hammer2_iod_fmap_write; 95 long hammer2_iod_volu_write; 96 long hammer2_ioa_file_read; 97 long hammer2_ioa_meta_read; 98 long hammer2_ioa_indr_read; 99 long hammer2_ioa_fmap_read; 100 long hammer2_ioa_volu_read; 101 long hammer2_ioa_fmap_write; 102 long hammer2_ioa_file_write; 103 long hammer2_ioa_meta_write; 104 long hammer2_ioa_indr_write; 105 long hammer2_ioa_volu_write; 106 107 MALLOC_DECLARE(C_BUFFER); 108 MALLOC_DEFINE(C_BUFFER, "compbuffer", "Buffer used for compression."); 109 110 MALLOC_DECLARE(D_BUFFER); 111 MALLOC_DEFINE(D_BUFFER, "decompbuffer", "Buffer used for decompression."); 112 113 SYSCTL_NODE(_vfs, OID_AUTO, hammer2, CTLFLAG_RW, 0, "HAMMER2 filesystem"); 114 115 SYSCTL_INT(_vfs_hammer2, OID_AUTO, debug, CTLFLAG_RW, 116 &hammer2_debug, 0, ""); 117 SYSCTL_INT(_vfs_hammer2, OID_AUTO, cluster_enable, CTLFLAG_RW, 118 &hammer2_cluster_enable, 0, ""); 119 SYSCTL_INT(_vfs_hammer2, OID_AUTO, hardlink_enable, CTLFLAG_RW, 120 &hammer2_hardlink_enable, 0, ""); 121 SYSCTL_INT(_vfs_hammer2, OID_AUTO, flush_pipe, CTLFLAG_RW, 122 &hammer2_flush_pipe, 0, ""); 123 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, limit_dirty_chains, CTLFLAG_RW, 124 &hammer2_limit_dirty_chains, 0, ""); 125 126 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_file_read, CTLFLAG_RW, 127 &hammer2_iod_file_read, 0, ""); 128 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_meta_read, CTLFLAG_RW, 129 &hammer2_iod_meta_read, 0, ""); 130 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_indr_read, CTLFLAG_RW, 131 &hammer2_iod_indr_read, 0, ""); 132 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_fmap_read, CTLFLAG_RW, 133 &hammer2_iod_fmap_read, 0, ""); 134 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_volu_read, CTLFLAG_RW, 135 &hammer2_iod_volu_read, 0, ""); 136 137 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_file_write, CTLFLAG_RW, 138 &hammer2_iod_file_write, 0, ""); 139 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_meta_write, CTLFLAG_RW, 140 &hammer2_iod_meta_write, 0, ""); 141 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_indr_write, CTLFLAG_RW, 142 &hammer2_iod_indr_write, 0, ""); 143 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_fmap_write, CTLFLAG_RW, 144 &hammer2_iod_fmap_write, 0, ""); 145 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, iod_volu_write, CTLFLAG_RW, 146 &hammer2_iod_volu_write, 0, ""); 147 148 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_file_read, CTLFLAG_RW, 149 &hammer2_ioa_file_read, 0, ""); 150 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_meta_read, CTLFLAG_RW, 151 &hammer2_ioa_meta_read, 0, ""); 152 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_indr_read, CTLFLAG_RW, 153 &hammer2_ioa_indr_read, 0, ""); 154 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_fmap_read, CTLFLAG_RW, 155 &hammer2_ioa_fmap_read, 0, ""); 156 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_volu_read, CTLFLAG_RW, 157 &hammer2_ioa_volu_read, 0, ""); 158 159 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_file_write, CTLFLAG_RW, 160 &hammer2_ioa_file_write, 0, ""); 161 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_meta_write, CTLFLAG_RW, 162 &hammer2_ioa_meta_write, 0, ""); 163 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_indr_write, CTLFLAG_RW, 164 &hammer2_ioa_indr_write, 0, ""); 165 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_fmap_write, CTLFLAG_RW, 166 &hammer2_ioa_fmap_write, 0, ""); 167 SYSCTL_LONG(_vfs_hammer2, OID_AUTO, ioa_volu_write, CTLFLAG_RW, 168 &hammer2_ioa_volu_write, 0, ""); 169 170 static int hammer2_vfs_init(struct vfsconf *conf); 171 static int hammer2_vfs_uninit(struct vfsconf *vfsp); 172 static int hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data, 173 struct ucred *cred); 174 static int hammer2_remount(hammer2_mount_t *, struct mount *, char *, 175 struct vnode *, struct ucred *); 176 static int hammer2_recovery(hammer2_mount_t *hmp); 177 static int hammer2_vfs_unmount(struct mount *mp, int mntflags); 178 static int hammer2_vfs_root(struct mount *mp, struct vnode **vpp); 179 static int hammer2_vfs_statfs(struct mount *mp, struct statfs *sbp, 180 struct ucred *cred); 181 static int hammer2_vfs_statvfs(struct mount *mp, struct statvfs *sbp, 182 struct ucred *cred); 183 static int hammer2_vfs_vget(struct mount *mp, struct vnode *dvp, 184 ino_t ino, struct vnode **vpp); 185 static int hammer2_vfs_fhtovp(struct mount *mp, struct vnode *rootvp, 186 struct fid *fhp, struct vnode **vpp); 187 static int hammer2_vfs_vptofh(struct vnode *vp, struct fid *fhp); 188 static int hammer2_vfs_checkexp(struct mount *mp, struct sockaddr *nam, 189 int *exflagsp, struct ucred **credanonp); 190 191 static int hammer2_install_volume_header(hammer2_mount_t *hmp); 192 static int hammer2_sync_scan2(struct mount *mp, struct vnode *vp, void *data); 193 194 static void hammer2_write_thread(void *arg); 195 196 static void hammer2_vfs_unmount_hmp1(struct mount *mp, hammer2_mount_t *hmp); 197 static void hammer2_vfs_unmount_hmp2(struct mount *mp, hammer2_mount_t *hmp); 198 199 /* 200 * Functions for compression in threads, 201 * from hammer2_vnops.c 202 */ 203 static void hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans, 204 hammer2_inode_t *ip, 205 hammer2_inode_data_t *ipdata, 206 hammer2_chain_t **parentp, 207 hammer2_key_t lbase, int ioflag, int pblksize, 208 int *errorp); 209 static void hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans, 210 hammer2_inode_t *ip, 211 hammer2_inode_data_t *ipdata, 212 hammer2_chain_t **parentp, 213 hammer2_key_t lbase, int ioflag, 214 int pblksize, int *errorp, int comp_algo); 215 static void hammer2_zero_check_and_write(struct buf *bp, 216 hammer2_trans_t *trans, hammer2_inode_t *ip, 217 hammer2_inode_data_t *ipdata, 218 hammer2_chain_t **parentp, 219 hammer2_key_t lbase, 220 int ioflag, int pblksize, int *errorp); 221 static int test_block_zeros(const char *buf, size_t bytes); 222 static void zero_write(struct buf *bp, hammer2_trans_t *trans, 223 hammer2_inode_t *ip, 224 hammer2_inode_data_t *ipdata, 225 hammer2_chain_t **parentp, 226 hammer2_key_t lbase, 227 int *errorp); 228 static void hammer2_write_bp(hammer2_chain_t *chain, struct buf *bp, 229 int ioflag, int pblksize, int *errorp); 230 231 static int hammer2_rcvdmsg(kdmsg_msg_t *msg); 232 static void hammer2_autodmsg(kdmsg_msg_t *msg); 233 234 235 /* 236 * HAMMER2 vfs operations. 237 */ 238 static struct vfsops hammer2_vfsops = { 239 .vfs_init = hammer2_vfs_init, 240 .vfs_uninit = hammer2_vfs_uninit, 241 .vfs_sync = hammer2_vfs_sync, 242 .vfs_mount = hammer2_vfs_mount, 243 .vfs_unmount = hammer2_vfs_unmount, 244 .vfs_root = hammer2_vfs_root, 245 .vfs_statfs = hammer2_vfs_statfs, 246 .vfs_statvfs = hammer2_vfs_statvfs, 247 .vfs_vget = hammer2_vfs_vget, 248 .vfs_vptofh = hammer2_vfs_vptofh, 249 .vfs_fhtovp = hammer2_vfs_fhtovp, 250 .vfs_checkexp = hammer2_vfs_checkexp 251 }; 252 253 MALLOC_DEFINE(M_HAMMER2, "HAMMER2-mount", ""); 254 255 VFS_SET(hammer2_vfsops, hammer2, 0); 256 MODULE_VERSION(hammer2, 1); 257 258 static 259 int 260 hammer2_vfs_init(struct vfsconf *conf) 261 { 262 static struct objcache_malloc_args margs_read; 263 static struct objcache_malloc_args margs_write; 264 265 int error; 266 267 error = 0; 268 269 if (HAMMER2_BLOCKREF_BYTES != sizeof(struct hammer2_blockref)) 270 error = EINVAL; 271 if (HAMMER2_INODE_BYTES != sizeof(struct hammer2_inode_data)) 272 error = EINVAL; 273 if (HAMMER2_VOLUME_BYTES != sizeof(struct hammer2_volume_data)) 274 error = EINVAL; 275 276 if (error) 277 kprintf("HAMMER2 structure size mismatch; cannot continue.\n"); 278 279 margs_read.objsize = 65536; 280 margs_read.mtype = D_BUFFER; 281 282 margs_write.objsize = 32768; 283 margs_write.mtype = C_BUFFER; 284 285 cache_buffer_read = objcache_create(margs_read.mtype->ks_shortdesc, 286 0, 1, NULL, NULL, NULL, objcache_malloc_alloc, 287 objcache_malloc_free, &margs_read); 288 cache_buffer_write = objcache_create(margs_write.mtype->ks_shortdesc, 289 0, 1, NULL, NULL, NULL, objcache_malloc_alloc, 290 objcache_malloc_free, &margs_write); 291 292 lockinit(&hammer2_mntlk, "mntlk", 0, 0); 293 TAILQ_INIT(&hammer2_mntlist); 294 295 hammer2_limit_dirty_chains = desiredvnodes / 10; 296 297 return (error); 298 } 299 300 static 301 int 302 hammer2_vfs_uninit(struct vfsconf *vfsp __unused) 303 { 304 objcache_destroy(cache_buffer_read); 305 objcache_destroy(cache_buffer_write); 306 return 0; 307 } 308 309 /* 310 * Mount or remount HAMMER2 fileystem from physical media 311 * 312 * mountroot 313 * mp mount point structure 314 * path NULL 315 * data <unused> 316 * cred <unused> 317 * 318 * mount 319 * mp mount point structure 320 * path path to mount point 321 * data pointer to argument structure in user space 322 * volume volume path (device@LABEL form) 323 * hflags user mount flags 324 * cred user credentials 325 * 326 * RETURNS: 0 Success 327 * !0 error number 328 */ 329 static 330 int 331 hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data, 332 struct ucred *cred) 333 { 334 struct hammer2_mount_info info; 335 hammer2_pfsmount_t *pmp; 336 hammer2_mount_t *hmp; 337 hammer2_key_t key_next; 338 hammer2_key_t key_dummy; 339 hammer2_key_t lhc; 340 struct vnode *devvp; 341 struct nlookupdata nd; 342 hammer2_chain_t *parent; 343 hammer2_chain_t *schain; 344 hammer2_chain_t *rchain; 345 struct file *fp; 346 char devstr[MNAMELEN]; 347 size_t size; 348 size_t done; 349 char *dev; 350 char *label; 351 int ronly = 1; 352 int error; 353 int cache_index; 354 int i; 355 356 hmp = NULL; 357 pmp = NULL; 358 dev = NULL; 359 label = NULL; 360 devvp = NULL; 361 cache_index = -1; 362 363 kprintf("hammer2_mount\n"); 364 365 if (path == NULL) { 366 /* 367 * Root mount 368 */ 369 bzero(&info, sizeof(info)); 370 info.cluster_fd = -1; 371 return (EOPNOTSUPP); 372 } else { 373 /* 374 * Non-root mount or updating a mount 375 */ 376 error = copyin(data, &info, sizeof(info)); 377 if (error) 378 return (error); 379 380 error = copyinstr(info.volume, devstr, MNAMELEN - 1, &done); 381 if (error) 382 return (error); 383 384 /* Extract device and label */ 385 dev = devstr; 386 label = strchr(devstr, '@'); 387 if (label == NULL || 388 ((label + 1) - dev) > done) { 389 return (EINVAL); 390 } 391 *label = '\0'; 392 label++; 393 if (*label == '\0') 394 return (EINVAL); 395 396 if (mp->mnt_flag & MNT_UPDATE) { 397 /* Update mount */ 398 /* HAMMER2 implements NFS export via mountctl */ 399 pmp = MPTOPMP(mp); 400 for (i = 0; i < pmp->cluster.nchains; ++i) { 401 hmp = pmp->cluster.chains[i]->hmp; 402 devvp = hmp->devvp; 403 error = hammer2_remount(hmp, mp, path, 404 devvp, cred); 405 if (error) 406 break; 407 } 408 return error; 409 } 410 } 411 412 /* 413 * PFS mount 414 * 415 * Lookup name and verify it refers to a block device. 416 */ 417 error = nlookup_init(&nd, dev, UIO_SYSSPACE, NLC_FOLLOW); 418 if (error == 0) 419 error = nlookup(&nd); 420 if (error == 0) 421 error = cache_vref(&nd.nl_nch, nd.nl_cred, &devvp); 422 nlookup_done(&nd); 423 424 if (error == 0) { 425 if (vn_isdisk(devvp, &error)) 426 error = vfs_mountedon(devvp); 427 } 428 429 /* 430 * Determine if the device has already been mounted. After this 431 * check hmp will be non-NULL if we are doing the second or more 432 * hammer2 mounts from the same device. 433 */ 434 lockmgr(&hammer2_mntlk, LK_EXCLUSIVE); 435 TAILQ_FOREACH(hmp, &hammer2_mntlist, mntentry) { 436 if (hmp->devvp == devvp) 437 break; 438 } 439 440 /* 441 * Open the device if this isn't a secondary mount and construct 442 * the H2 device mount (hmp). 443 */ 444 if (hmp == NULL) { 445 if (error == 0 && vcount(devvp) > 0) 446 error = EBUSY; 447 448 /* 449 * Now open the device 450 */ 451 if (error == 0) { 452 ronly = ((mp->mnt_flag & MNT_RDONLY) != 0); 453 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 454 error = vinvalbuf(devvp, V_SAVE, 0, 0); 455 if (error == 0) { 456 error = VOP_OPEN(devvp, 457 ronly ? FREAD : FREAD | FWRITE, 458 FSCRED, NULL); 459 } 460 vn_unlock(devvp); 461 } 462 if (error && devvp) { 463 vrele(devvp); 464 devvp = NULL; 465 } 466 if (error) { 467 lockmgr(&hammer2_mntlk, LK_RELEASE); 468 return error; 469 } 470 hmp = kmalloc(sizeof(*hmp), M_HAMMER2, M_WAITOK | M_ZERO); 471 hmp->ronly = ronly; 472 hmp->devvp = devvp; 473 kmalloc_create(&hmp->mchain, "HAMMER2-chains"); 474 TAILQ_INSERT_TAIL(&hammer2_mntlist, hmp, mntentry); 475 RB_INIT(&hmp->iotree); 476 477 lockinit(&hmp->alloclk, "h2alloc", 0, 0); 478 lockinit(&hmp->voldatalk, "voldata", 0, LK_CANRECURSE); 479 TAILQ_INIT(&hmp->transq); 480 481 /* 482 * vchain setup. vchain.data is embedded. 483 * vchain.refs is initialized and will never drop to 0. 484 * 485 * NOTE! voldata is not yet loaded. 486 */ 487 hmp->vchain.hmp = hmp; 488 hmp->vchain.refs = 1; 489 hmp->vchain.data = (void *)&hmp->voldata; 490 hmp->vchain.bref.type = HAMMER2_BREF_TYPE_VOLUME; 491 hmp->vchain.bref.data_off = 0 | HAMMER2_PBUFRADIX; 492 hmp->vchain.delete_tid = HAMMER2_MAX_TID; 493 494 hammer2_chain_core_alloc(NULL, &hmp->vchain, NULL); 495 /* hmp->vchain.u.xxx is left NULL */ 496 497 /* 498 * fchain setup. fchain.data is embedded. 499 * fchain.refs is initialized and will never drop to 0. 500 * 501 * The data is not used but needs to be initialized to 502 * pass assertion muster. We use this chain primarily 503 * as a placeholder for the freemap's top-level RBTREE 504 * so it does not interfere with the volume's topology 505 * RBTREE. 506 */ 507 hmp->fchain.hmp = hmp; 508 hmp->fchain.refs = 1; 509 hmp->fchain.data = (void *)&hmp->voldata.freemap_blockset; 510 hmp->fchain.bref.type = HAMMER2_BREF_TYPE_FREEMAP; 511 hmp->fchain.bref.data_off = 0 | HAMMER2_PBUFRADIX; 512 hmp->fchain.bref.methods = 513 HAMMER2_ENC_CHECK(HAMMER2_CHECK_FREEMAP) | 514 HAMMER2_ENC_COMP(HAMMER2_COMP_NONE); 515 hmp->fchain.delete_tid = HAMMER2_MAX_TID; 516 517 hammer2_chain_core_alloc(NULL, &hmp->fchain, NULL); 518 /* hmp->fchain.u.xxx is left NULL */ 519 520 /* 521 * Install the volume header and initialize fields from 522 * voldata. 523 */ 524 error = hammer2_install_volume_header(hmp); 525 if (error) { 526 ++hmp->pmp_count; 527 hammer2_vfs_unmount_hmp1(mp, hmp); 528 hammer2_vfs_unmount_hmp2(mp, hmp); 529 hammer2_vfs_unmount(mp, MNT_FORCE); 530 return error; 531 } 532 533 hmp->vchain.bref.mirror_tid = hmp->voldata.mirror_tid; 534 hmp->vchain.modify_tid = hmp->voldata.mirror_tid; 535 hmp->fchain.bref.mirror_tid = hmp->voldata.freemap_tid; 536 hmp->fchain.modify_tid = hmp->voldata.freemap_tid; 537 538 /* 539 * First locate the super-root inode, which is key 0 540 * relative to the volume header's blockset. 541 * 542 * Then locate the root inode by scanning the directory keyspace 543 * represented by the label. 544 */ 545 parent = hammer2_chain_lookup_init(&hmp->vchain, 0); 546 schain = hammer2_chain_lookup(&parent, &key_dummy, 547 HAMMER2_SROOT_KEY, HAMMER2_SROOT_KEY, 548 &cache_index, 0); 549 hammer2_chain_lookup_done(parent); 550 if (schain == NULL) { 551 kprintf("hammer2_mount: invalid super-root\n"); 552 ++hmp->pmp_count; 553 hammer2_vfs_unmount_hmp1(mp, hmp); 554 hammer2_vfs_unmount_hmp2(mp, hmp); 555 hammer2_vfs_unmount(mp, MNT_FORCE); 556 return EINVAL; 557 } 558 559 /* 560 * NOTE: inode_get sucks up schain's lock. 561 */ 562 atomic_set_int(&schain->flags, HAMMER2_CHAIN_PFSROOT); 563 hmp->sroot = hammer2_inode_get(NULL, NULL, schain); 564 hammer2_inode_ref(hmp->sroot); 565 hammer2_inode_unlock_ex(hmp->sroot, schain); 566 schain = NULL; 567 /* leave hmp->sroot with one ref */ 568 569 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 570 error = hammer2_recovery(hmp); 571 /* XXX do something with error */ 572 } 573 } 574 575 /* 576 * Block device opened successfully, finish initializing the 577 * mount structure. 578 * 579 * From this point on we have to call hammer2_unmount() on failure. 580 */ 581 pmp = kmalloc(sizeof(*pmp), M_HAMMER2, M_WAITOK | M_ZERO); 582 583 kmalloc_create(&pmp->minode, "HAMMER2-inodes"); 584 kmalloc_create(&pmp->mmsg, "HAMMER2-pfsmsg"); 585 586 spin_init(&pmp->inum_spin); 587 RB_INIT(&pmp->inum_tree); 588 589 kdmsg_iocom_init(&pmp->iocom, pmp, 590 KDMSG_IOCOMF_AUTOCONN | 591 KDMSG_IOCOMF_AUTOSPAN | 592 KDMSG_IOCOMF_AUTOCIRC, 593 pmp->mmsg, hammer2_rcvdmsg); 594 595 ccms_domain_init(&pmp->ccms_dom); 596 ++hmp->pmp_count; 597 lockmgr(&hammer2_mntlk, LK_RELEASE); 598 kprintf("hammer2_mount hmp=%p pmp=%p pmpcnt=%d\n", 599 hmp, pmp, hmp->pmp_count); 600 601 mp->mnt_flag = MNT_LOCAL; 602 mp->mnt_kern_flag |= MNTK_ALL_MPSAFE; /* all entry pts are SMP */ 603 mp->mnt_kern_flag |= MNTK_THR_SYNC; /* new vsyncscan semantics */ 604 605 /* 606 * required mount structure initializations 607 */ 608 mp->mnt_stat.f_iosize = HAMMER2_PBUFSIZE; 609 mp->mnt_stat.f_bsize = HAMMER2_PBUFSIZE; 610 611 mp->mnt_vstat.f_frsize = HAMMER2_PBUFSIZE; 612 mp->mnt_vstat.f_bsize = HAMMER2_PBUFSIZE; 613 614 /* 615 * Optional fields 616 */ 617 mp->mnt_iosize_max = MAXPHYS; 618 mp->mnt_data = (qaddr_t)pmp; 619 pmp->mp = mp; 620 621 /* 622 * Lookup mount point under the media-localized super-root. 623 */ 624 parent = hammer2_inode_lock_ex(hmp->sroot); 625 lhc = hammer2_dirhash(label, strlen(label)); 626 rchain = hammer2_chain_lookup(&parent, &key_next, 627 lhc, lhc + HAMMER2_DIRHASH_LOMASK, 628 &cache_index, 0); 629 while (rchain) { 630 if (rchain->bref.type == HAMMER2_BREF_TYPE_INODE && 631 strcmp(label, rchain->data->ipdata.filename) == 0) { 632 break; 633 } 634 rchain = hammer2_chain_next(&parent, rchain, &key_next, 635 key_next, 636 lhc + HAMMER2_DIRHASH_LOMASK, 637 &cache_index, 0); 638 } 639 hammer2_inode_unlock_ex(hmp->sroot, parent); 640 641 if (rchain == NULL) { 642 kprintf("hammer2_mount: PFS label not found\n"); 643 hammer2_vfs_unmount_hmp1(mp, hmp); 644 hammer2_vfs_unmount_hmp2(mp, hmp); 645 hammer2_vfs_unmount(mp, MNT_FORCE); 646 return EINVAL; 647 } 648 if (rchain->flags & HAMMER2_CHAIN_MOUNTED) { 649 hammer2_chain_unlock(rchain); 650 kprintf("hammer2_mount: PFS label already mounted!\n"); 651 hammer2_vfs_unmount_hmp1(mp, hmp); 652 hammer2_vfs_unmount_hmp2(mp, hmp); 653 hammer2_vfs_unmount(mp, MNT_FORCE); 654 return EBUSY; 655 } 656 #if 0 657 if (rchain->flags & HAMMER2_CHAIN_RECYCLE) { 658 kprintf("hammer2_mount: PFS label currently recycling\n"); 659 hammer2_vfs_unmount_hmp1(mp, hmp); 660 hammer2_vfs_unmount_hmp2(mp, hmp); 661 hammer2_vfs_unmount(mp, MNT_FORCE); 662 return EBUSY; 663 } 664 #endif 665 /* 666 * After this point hammer2_vfs_unmount() has visibility on hmp 667 * and manual hmp1/hmp2 calls are not needed on fatal errors. 668 */ 669 670 atomic_set_int(&rchain->flags, HAMMER2_CHAIN_MOUNTED); 671 672 /* 673 * NOTE: *_get() integrates chain's lock into the inode lock. 674 */ 675 hammer2_chain_ref(rchain); /* for pmp->rchain */ 676 pmp->cluster.nchains = 1; 677 pmp->cluster.chains[0] = rchain; 678 pmp->iroot = hammer2_inode_get(pmp, NULL, rchain); 679 hammer2_inode_ref(pmp->iroot); /* ref for pmp->iroot */ 680 681 KKASSERT(rchain->pmp == NULL); /* tracking pmp for rchain */ 682 rchain->pmp = pmp; 683 684 hammer2_inode_unlock_ex(pmp->iroot, rchain); 685 686 kprintf("iroot %p\n", pmp->iroot); 687 688 /* 689 * The logical file buffer bio write thread handles things 690 * like physical block assignment and compression. 691 */ 692 mtx_init(&pmp->wthread_mtx); 693 bioq_init(&pmp->wthread_bioq); 694 pmp->wthread_destroy = 0; 695 lwkt_create(hammer2_write_thread, pmp, 696 &pmp->wthread_td, NULL, 0, -1, "hwrite-%s", label); 697 698 /* 699 * Ref the cluster management messaging descriptor. The mount 700 * program deals with the other end of the communications pipe. 701 */ 702 fp = holdfp(curproc->p_fd, info.cluster_fd, -1); 703 if (fp == NULL) { 704 kprintf("hammer2_mount: bad cluster_fd!\n"); 705 hammer2_vfs_unmount(mp, MNT_FORCE); 706 return EBADF; 707 } 708 hammer2_cluster_reconnect(pmp, fp); 709 710 /* 711 * Finish setup 712 */ 713 vfs_getnewfsid(mp); 714 vfs_add_vnodeops(mp, &hammer2_vnode_vops, &mp->mnt_vn_norm_ops); 715 vfs_add_vnodeops(mp, &hammer2_spec_vops, &mp->mnt_vn_spec_ops); 716 vfs_add_vnodeops(mp, &hammer2_fifo_vops, &mp->mnt_vn_fifo_ops); 717 718 copyinstr(info.volume, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); 719 bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); 720 bzero(mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname)); 721 copyinstr(path, mp->mnt_stat.f_mntonname, 722 sizeof(mp->mnt_stat.f_mntonname) - 1, 723 &size); 724 725 /* 726 * Initial statfs to prime mnt_stat. 727 */ 728 hammer2_vfs_statfs(mp, &mp->mnt_stat, cred); 729 730 return 0; 731 } 732 733 /* 734 * Handle bioq for strategy write 735 */ 736 static 737 void 738 hammer2_write_thread(void *arg) 739 { 740 hammer2_pfsmount_t *pmp; 741 struct bio *bio; 742 struct buf *bp; 743 hammer2_trans_t trans; 744 struct vnode *vp; 745 hammer2_inode_t *ip; 746 hammer2_chain_t *parent; 747 hammer2_chain_t **parentp; 748 hammer2_inode_data_t *ipdata; 749 hammer2_key_t lbase; 750 int lblksize; 751 int pblksize; 752 int error; 753 754 pmp = arg; 755 756 mtx_lock(&pmp->wthread_mtx); 757 while (pmp->wthread_destroy == 0) { 758 if (bioq_first(&pmp->wthread_bioq) == NULL) { 759 mtxsleep(&pmp->wthread_bioq, &pmp->wthread_mtx, 760 0, "h2bioqw", 0); 761 } 762 parent = NULL; 763 parentp = &parent; 764 765 hammer2_trans_init(&trans, pmp, NULL, HAMMER2_TRANS_BUFCACHE); 766 767 while ((bio = bioq_takefirst(&pmp->wthread_bioq)) != NULL) { 768 /* 769 * dummy bio for synchronization. The transaction 770 * must be reinitialized. 771 */ 772 if (bio->bio_buf == NULL) { 773 bio->bio_flags |= BIO_DONE; 774 wakeup(bio); 775 hammer2_trans_done(&trans); 776 hammer2_trans_init(&trans, pmp, NULL, 777 HAMMER2_TRANS_BUFCACHE); 778 continue; 779 } 780 781 /* 782 * else normal bio processing 783 */ 784 mtx_unlock(&pmp->wthread_mtx); 785 786 hammer2_lwinprog_drop(pmp); 787 788 error = 0; 789 bp = bio->bio_buf; 790 vp = bp->b_vp; 791 ip = VTOI(vp); 792 793 /* 794 * Inode is modified, flush size and mtime changes 795 * to ensure that the file size remains consistent 796 * with the buffers being flushed. 797 */ 798 parent = hammer2_inode_lock_ex(ip); 799 if (ip->flags & (HAMMER2_INODE_RESIZED | 800 HAMMER2_INODE_MTIME)) { 801 hammer2_inode_fsync(&trans, ip, parentp); 802 } 803 ipdata = hammer2_chain_modify_ip(&trans, ip, 804 parentp, 0); 805 lblksize = hammer2_calc_logical(ip, bio->bio_offset, 806 &lbase, NULL); 807 pblksize = hammer2_calc_physical(ip, lbase); 808 hammer2_write_file_core(bp, &trans, ip, ipdata, 809 parentp, 810 lbase, IO_ASYNC, 811 pblksize, &error); 812 hammer2_inode_unlock_ex(ip, parent); 813 if (error) { 814 kprintf("hammer2: error in buffer write\n"); 815 bp->b_flags |= B_ERROR; 816 bp->b_error = EIO; 817 } 818 biodone(bio); 819 mtx_lock(&pmp->wthread_mtx); 820 } 821 hammer2_trans_done(&trans); 822 } 823 pmp->wthread_destroy = -1; 824 wakeup(&pmp->wthread_destroy); 825 826 mtx_unlock(&pmp->wthread_mtx); 827 } 828 829 void 830 hammer2_bioq_sync(hammer2_pfsmount_t *pmp) 831 { 832 struct bio sync_bio; 833 834 bzero(&sync_bio, sizeof(sync_bio)); /* dummy with no bio_buf */ 835 mtx_lock(&pmp->wthread_mtx); 836 if (pmp->wthread_destroy == 0) { 837 if (TAILQ_EMPTY(&pmp->wthread_bioq.queue)) { 838 bioq_insert_tail(&pmp->wthread_bioq, &sync_bio); 839 wakeup(&pmp->wthread_bioq); 840 } else { 841 bioq_insert_tail(&pmp->wthread_bioq, &sync_bio); 842 } 843 while ((sync_bio.bio_flags & BIO_DONE) == 0) 844 mtxsleep(&sync_bio, &pmp->wthread_mtx, 0, "h2bioq", 0); 845 } 846 mtx_unlock(&pmp->wthread_mtx); 847 } 848 849 /* 850 * Return a chain suitable for I/O, creating the chain if necessary 851 * and assigning its physical block. 852 */ 853 static 854 hammer2_chain_t * 855 hammer2_assign_physical(hammer2_trans_t *trans, 856 hammer2_inode_t *ip, hammer2_chain_t **parentp, 857 hammer2_key_t lbase, int pblksize, int *errorp) 858 { 859 hammer2_chain_t *parent; 860 hammer2_chain_t *chain; 861 hammer2_off_t pbase; 862 hammer2_key_t key_dummy; 863 int pradix = hammer2_getradix(pblksize); 864 int cache_index = -1; 865 866 /* 867 * Locate the chain associated with lbase, return a locked chain. 868 * However, do not instantiate any data reference (which utilizes a 869 * device buffer) because we will be using direct IO via the 870 * logical buffer cache buffer. 871 */ 872 *errorp = 0; 873 KKASSERT(pblksize >= HAMMER2_MIN_ALLOC); 874 retry: 875 parent = *parentp; 876 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS); /* extra lock */ 877 chain = hammer2_chain_lookup(&parent, &key_dummy, 878 lbase, lbase, 879 &cache_index, HAMMER2_LOOKUP_NODATA); 880 881 if (chain == NULL) { 882 /* 883 * We found a hole, create a new chain entry. 884 * 885 * NOTE: DATA chains are created without device backing 886 * store (nor do we want any). 887 */ 888 *errorp = hammer2_chain_create(trans, &parent, &chain, 889 lbase, HAMMER2_PBUFRADIX, 890 HAMMER2_BREF_TYPE_DATA, 891 pblksize); 892 if (chain == NULL) { 893 hammer2_chain_lookup_done(parent); 894 panic("hammer2_chain_create: par=%p error=%d\n", 895 parent, *errorp); 896 goto retry; 897 } 898 899 pbase = chain->bref.data_off & ~HAMMER2_OFF_MASK_RADIX; 900 /*ip->delta_dcount += pblksize;*/ 901 } else { 902 switch (chain->bref.type) { 903 case HAMMER2_BREF_TYPE_INODE: 904 /* 905 * The data is embedded in the inode. The 906 * caller is responsible for marking the inode 907 * modified and copying the data to the embedded 908 * area. 909 */ 910 pbase = NOOFFSET; 911 break; 912 case HAMMER2_BREF_TYPE_DATA: 913 if (chain->bytes != pblksize) { 914 hammer2_chain_resize(trans, ip, 915 parent, &chain, 916 pradix, 917 HAMMER2_MODIFY_OPTDATA); 918 } 919 hammer2_chain_modify(trans, &chain, 920 HAMMER2_MODIFY_OPTDATA); 921 pbase = chain->bref.data_off & ~HAMMER2_OFF_MASK_RADIX; 922 break; 923 default: 924 panic("hammer2_assign_physical: bad type"); 925 /* NOT REACHED */ 926 pbase = NOOFFSET; 927 break; 928 } 929 } 930 931 /* 932 * Cleanup. If chain wound up being the inode (i.e. DIRECTDATA), 933 * we might have to replace *parentp. 934 */ 935 hammer2_chain_lookup_done(parent); 936 if (chain) { 937 if (*parentp != chain && 938 (*parentp)->core == chain->core) { 939 parent = *parentp; 940 *parentp = chain; /* eats lock */ 941 hammer2_chain_unlock(parent); 942 hammer2_chain_lock(chain, 0); /* need another */ 943 } 944 /* else chain already locked for return */ 945 } 946 return (chain); 947 } 948 949 /* 950 * From hammer2_vnops.c. 951 * The core write function which determines which path to take 952 * depending on compression settings. 953 */ 954 static 955 void 956 hammer2_write_file_core(struct buf *bp, hammer2_trans_t *trans, 957 hammer2_inode_t *ip, hammer2_inode_data_t *ipdata, 958 hammer2_chain_t **parentp, 959 hammer2_key_t lbase, int ioflag, int pblksize, 960 int *errorp) 961 { 962 hammer2_chain_t *chain; 963 964 switch(HAMMER2_DEC_COMP(ipdata->comp_algo)) { 965 case HAMMER2_COMP_NONE: 966 /* 967 * We have to assign physical storage to the buffer 968 * we intend to dirty or write now to avoid deadlocks 969 * in the strategy code later. 970 * 971 * This can return NOOFFSET for inode-embedded data. 972 * The strategy code will take care of it in that case. 973 */ 974 chain = hammer2_assign_physical(trans, ip, parentp, 975 lbase, pblksize, 976 errorp); 977 hammer2_write_bp(chain, bp, ioflag, pblksize, errorp); 978 if (chain) 979 hammer2_chain_unlock(chain); 980 break; 981 case HAMMER2_COMP_AUTOZERO: 982 /* 983 * Check for zero-fill only 984 */ 985 hammer2_zero_check_and_write(bp, trans, ip, 986 ipdata, parentp, lbase, 987 ioflag, pblksize, errorp); 988 break; 989 case HAMMER2_COMP_LZ4: 990 case HAMMER2_COMP_ZLIB: 991 default: 992 /* 993 * Check for zero-fill and attempt compression. 994 */ 995 hammer2_compress_and_write(bp, trans, ip, 996 ipdata, parentp, 997 lbase, ioflag, 998 pblksize, errorp, 999 ipdata->comp_algo); 1000 break; 1001 } 1002 ipdata = &ip->chain->data->ipdata; /* reload */ 1003 } 1004 1005 /* 1006 * From hammer2_vnops.c 1007 * Generic function that will perform the compression in compression 1008 * write path. The compression algorithm is determined by the settings 1009 * obtained from inode. 1010 */ 1011 static 1012 void 1013 hammer2_compress_and_write(struct buf *bp, hammer2_trans_t *trans, 1014 hammer2_inode_t *ip, hammer2_inode_data_t *ipdata, 1015 hammer2_chain_t **parentp, 1016 hammer2_key_t lbase, int ioflag, int pblksize, 1017 int *errorp, int comp_algo) 1018 { 1019 hammer2_chain_t *chain; 1020 int comp_size; 1021 int comp_block_size; 1022 char *comp_buffer; 1023 1024 if (test_block_zeros(bp->b_data, pblksize)) { 1025 zero_write(bp, trans, ip, ipdata, parentp, lbase, errorp); 1026 return; 1027 } 1028 1029 comp_size = 0; 1030 comp_buffer = NULL; 1031 1032 KKASSERT(pblksize / 2 <= 32768); 1033 1034 if (ip->comp_heuristic < 8 || (ip->comp_heuristic & 7) == 0) { 1035 z_stream strm_compress; 1036 int comp_level; 1037 int ret; 1038 1039 switch(HAMMER2_DEC_COMP(comp_algo)) { 1040 case HAMMER2_COMP_LZ4: 1041 comp_buffer = objcache_get(cache_buffer_write, 1042 M_INTWAIT); 1043 comp_size = LZ4_compress_limitedOutput( 1044 bp->b_data, 1045 &comp_buffer[sizeof(int)], 1046 pblksize, 1047 pblksize / 2 - sizeof(int)); 1048 /* 1049 * We need to prefix with the size, LZ4 1050 * doesn't do it for us. Add the related 1051 * overhead. 1052 */ 1053 *(int *)comp_buffer = comp_size; 1054 if (comp_size) 1055 comp_size += sizeof(int); 1056 break; 1057 case HAMMER2_COMP_ZLIB: 1058 comp_level = HAMMER2_DEC_LEVEL(comp_algo); 1059 if (comp_level == 0) 1060 comp_level = 6; /* default zlib compression */ 1061 else if (comp_level < 6) 1062 comp_level = 6; 1063 else if (comp_level > 9) 1064 comp_level = 9; 1065 ret = deflateInit(&strm_compress, comp_level); 1066 if (ret != Z_OK) { 1067 kprintf("HAMMER2 ZLIB: fatal error " 1068 "on deflateInit.\n"); 1069 } 1070 1071 comp_buffer = objcache_get(cache_buffer_write, 1072 M_INTWAIT); 1073 strm_compress.next_in = bp->b_data; 1074 strm_compress.avail_in = pblksize; 1075 strm_compress.next_out = comp_buffer; 1076 strm_compress.avail_out = pblksize / 2; 1077 ret = deflate(&strm_compress, Z_FINISH); 1078 if (ret == Z_STREAM_END) { 1079 comp_size = pblksize / 2 - 1080 strm_compress.avail_out; 1081 } else { 1082 comp_size = 0; 1083 } 1084 ret = deflateEnd(&strm_compress); 1085 break; 1086 default: 1087 kprintf("Error: Unknown compression method.\n"); 1088 kprintf("Comp_method = %d.\n", comp_algo); 1089 break; 1090 } 1091 } 1092 1093 if (comp_size == 0) { 1094 /* 1095 * compression failed or turned off 1096 */ 1097 comp_block_size = pblksize; /* safety */ 1098 if (++ip->comp_heuristic > 128) 1099 ip->comp_heuristic = 8; 1100 } else { 1101 /* 1102 * compression succeeded 1103 */ 1104 ip->comp_heuristic = 0; 1105 if (comp_size <= 1024) { 1106 comp_block_size = 1024; 1107 } else if (comp_size <= 2048) { 1108 comp_block_size = 2048; 1109 } else if (comp_size <= 4096) { 1110 comp_block_size = 4096; 1111 } else if (comp_size <= 8192) { 1112 comp_block_size = 8192; 1113 } else if (comp_size <= 16384) { 1114 comp_block_size = 16384; 1115 } else if (comp_size <= 32768) { 1116 comp_block_size = 32768; 1117 } else { 1118 panic("hammer2: WRITE PATH: " 1119 "Weird comp_size value."); 1120 /* NOT REACHED */ 1121 comp_block_size = pblksize; 1122 } 1123 } 1124 1125 chain = hammer2_assign_physical(trans, ip, parentp, 1126 lbase, comp_block_size, 1127 errorp); 1128 ipdata = &ip->chain->data->ipdata; /* RELOAD */ 1129 1130 if (*errorp) { 1131 kprintf("WRITE PATH: An error occurred while " 1132 "assigning physical space.\n"); 1133 KKASSERT(chain == NULL); 1134 } else { 1135 /* Get device offset */ 1136 hammer2_io_t *dio; 1137 char *bdata; 1138 int temp_check; 1139 1140 KKASSERT(chain->flags & HAMMER2_CHAIN_MODIFIED); 1141 1142 switch(chain->bref.type) { 1143 case HAMMER2_BREF_TYPE_INODE: 1144 KKASSERT(chain->data->ipdata.op_flags & 1145 HAMMER2_OPFLAG_DIRECTDATA); 1146 KKASSERT(bp->b_loffset == 0); 1147 bcopy(bp->b_data, chain->data->ipdata.u.data, 1148 HAMMER2_EMBEDDED_BYTES); 1149 break; 1150 case HAMMER2_BREF_TYPE_DATA: 1151 temp_check = HAMMER2_DEC_CHECK(chain->bref.methods); 1152 1153 /* 1154 * Optimize out the read-before-write 1155 * if possible. 1156 */ 1157 *errorp = hammer2_io_newnz(chain->hmp, 1158 chain->bref.data_off, 1159 chain->bytes, 1160 &dio); 1161 if (*errorp) { 1162 hammer2_io_brelse(&dio); 1163 kprintf("hammer2: WRITE PATH: " 1164 "dbp bread error\n"); 1165 break; 1166 } 1167 bdata = hammer2_io_data(dio, chain->bref.data_off); 1168 1169 /* 1170 * When loading the block make sure we don't 1171 * leave garbage after the compressed data. 1172 */ 1173 if (comp_size) { 1174 chain->bref.methods = 1175 HAMMER2_ENC_COMP(comp_algo) + 1176 HAMMER2_ENC_CHECK(temp_check); 1177 bcopy(comp_buffer, bdata, comp_size); 1178 if (comp_size != comp_block_size) { 1179 bzero(bdata + comp_size, 1180 comp_block_size - comp_size); 1181 } 1182 } else { 1183 chain->bref.methods = 1184 HAMMER2_ENC_COMP( 1185 HAMMER2_COMP_NONE) + 1186 HAMMER2_ENC_CHECK(temp_check); 1187 bcopy(bp->b_data, bdata, pblksize); 1188 } 1189 1190 /* 1191 * Device buffer is now valid, chain is no 1192 * longer in the initial state. 1193 */ 1194 atomic_clear_int(&chain->flags, HAMMER2_CHAIN_INITIAL); 1195 1196 /* Now write the related bdp. */ 1197 if (ioflag & IO_SYNC) { 1198 /* 1199 * Synchronous I/O requested. 1200 */ 1201 hammer2_io_bwrite(&dio); 1202 /* 1203 } else if ((ioflag & IO_DIRECT) && 1204 loff + n == pblksize) { 1205 hammer2_io_bdwrite(&dio); 1206 */ 1207 } else if (ioflag & IO_ASYNC) { 1208 hammer2_io_bawrite(&dio); 1209 } else { 1210 hammer2_io_bdwrite(&dio); 1211 } 1212 break; 1213 default: 1214 panic("hammer2_write_bp: bad chain type %d\n", 1215 chain->bref.type); 1216 /* NOT REACHED */ 1217 break; 1218 } 1219 1220 hammer2_chain_unlock(chain); 1221 } 1222 if (comp_buffer) 1223 objcache_put(cache_buffer_write, comp_buffer); 1224 } 1225 1226 /* 1227 * Function that performs zero-checking and writing without compression, 1228 * it corresponds to default zero-checking path. 1229 */ 1230 static 1231 void 1232 hammer2_zero_check_and_write(struct buf *bp, hammer2_trans_t *trans, 1233 hammer2_inode_t *ip, hammer2_inode_data_t *ipdata, 1234 hammer2_chain_t **parentp, 1235 hammer2_key_t lbase, int ioflag, int pblksize, int *errorp) 1236 { 1237 hammer2_chain_t *chain; 1238 1239 if (test_block_zeros(bp->b_data, pblksize)) { 1240 zero_write(bp, trans, ip, ipdata, parentp, lbase, errorp); 1241 } else { 1242 chain = hammer2_assign_physical(trans, ip, parentp, 1243 lbase, pblksize, errorp); 1244 hammer2_write_bp(chain, bp, ioflag, pblksize, errorp); 1245 if (chain) 1246 hammer2_chain_unlock(chain); 1247 } 1248 } 1249 1250 /* 1251 * A function to test whether a block of data contains only zeros, 1252 * returns TRUE (non-zero) if the block is all zeros. 1253 */ 1254 static 1255 int 1256 test_block_zeros(const char *buf, size_t bytes) 1257 { 1258 size_t i; 1259 1260 for (i = 0; i < bytes; i += sizeof(long)) { 1261 if (*(const long *)(buf + i) != 0) 1262 return (0); 1263 } 1264 return (1); 1265 } 1266 1267 /* 1268 * Function to "write" a block that contains only zeros. 1269 */ 1270 static 1271 void 1272 zero_write(struct buf *bp, hammer2_trans_t *trans, hammer2_inode_t *ip, 1273 hammer2_inode_data_t *ipdata, hammer2_chain_t **parentp, 1274 hammer2_key_t lbase, int *errorp __unused) 1275 { 1276 hammer2_chain_t *parent; 1277 hammer2_chain_t *chain; 1278 hammer2_key_t key_dummy; 1279 int cache_index = -1; 1280 1281 parent = hammer2_chain_lookup_init(*parentp, 0); 1282 1283 chain = hammer2_chain_lookup(&parent, &key_dummy, lbase, lbase, 1284 &cache_index, HAMMER2_LOOKUP_NODATA); 1285 if (chain) { 1286 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE) { 1287 bzero(chain->data->ipdata.u.data, 1288 HAMMER2_EMBEDDED_BYTES); 1289 } else { 1290 hammer2_chain_delete(trans, chain, 0); 1291 } 1292 hammer2_chain_unlock(chain); 1293 } 1294 hammer2_chain_lookup_done(parent); 1295 } 1296 1297 /* 1298 * Function to write the data as it is, without performing any sort of 1299 * compression. This function is used in path without compression and 1300 * default zero-checking path. 1301 */ 1302 static 1303 void 1304 hammer2_write_bp(hammer2_chain_t *chain, struct buf *bp, int ioflag, 1305 int pblksize, int *errorp) 1306 { 1307 hammer2_io_t *dio; 1308 char *bdata; 1309 int error; 1310 int temp_check = HAMMER2_DEC_CHECK(chain->bref.methods); 1311 1312 KKASSERT(chain->flags & HAMMER2_CHAIN_MODIFIED); 1313 1314 switch(chain->bref.type) { 1315 case HAMMER2_BREF_TYPE_INODE: 1316 KKASSERT(chain->data->ipdata.op_flags & 1317 HAMMER2_OPFLAG_DIRECTDATA); 1318 KKASSERT(bp->b_loffset == 0); 1319 bcopy(bp->b_data, chain->data->ipdata.u.data, 1320 HAMMER2_EMBEDDED_BYTES); 1321 error = 0; 1322 break; 1323 case HAMMER2_BREF_TYPE_DATA: 1324 error = hammer2_io_newnz(chain->hmp, chain->bref.data_off, 1325 chain->bytes, &dio); 1326 if (error) { 1327 hammer2_io_bqrelse(&dio); 1328 kprintf("hammer2: WRITE PATH: dbp bread error\n"); 1329 break; 1330 } 1331 bdata = hammer2_io_data(dio, chain->bref.data_off); 1332 1333 chain->bref.methods = HAMMER2_ENC_COMP(HAMMER2_COMP_NONE) + 1334 HAMMER2_ENC_CHECK(temp_check); 1335 bcopy(bp->b_data, bdata, chain->bytes); 1336 1337 /* 1338 * Device buffer is now valid, chain is no 1339 * longer in the initial state. 1340 */ 1341 atomic_clear_int(&chain->flags, HAMMER2_CHAIN_INITIAL); 1342 1343 if (ioflag & IO_SYNC) { 1344 /* 1345 * Synchronous I/O requested. 1346 */ 1347 hammer2_io_bwrite(&dio); 1348 /* 1349 } else if ((ioflag & IO_DIRECT) && loff + n == pblksize) { 1350 hammer2_io_bdwrite(&dio); 1351 */ 1352 } else if (ioflag & IO_ASYNC) { 1353 hammer2_io_bawrite(&dio); 1354 } else { 1355 hammer2_io_bdwrite(&dio); 1356 } 1357 break; 1358 default: 1359 panic("hammer2_write_bp: bad chain type %d\n", 1360 chain->bref.type); 1361 /* NOT REACHED */ 1362 error = 0; 1363 break; 1364 } 1365 *errorp = error; 1366 } 1367 1368 static 1369 int 1370 hammer2_remount(hammer2_mount_t *hmp, struct mount *mp, char *path, 1371 struct vnode *devvp, struct ucred *cred) 1372 { 1373 int error; 1374 1375 if (hmp->ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { 1376 error = hammer2_recovery(hmp); 1377 } else { 1378 error = 0; 1379 } 1380 return error; 1381 } 1382 1383 static 1384 int 1385 hammer2_vfs_unmount(struct mount *mp, int mntflags) 1386 { 1387 hammer2_pfsmount_t *pmp; 1388 hammer2_mount_t *hmp; 1389 hammer2_chain_t *rchain; 1390 int flags; 1391 int error = 0; 1392 int i; 1393 1394 pmp = MPTOPMP(mp); 1395 1396 if (pmp == NULL) 1397 return(0); 1398 1399 ccms_domain_uninit(&pmp->ccms_dom); 1400 kdmsg_iocom_uninit(&pmp->iocom); /* XXX chain dependency */ 1401 1402 lockmgr(&hammer2_mntlk, LK_EXCLUSIVE); 1403 1404 /* 1405 * If mount initialization proceeded far enough we must flush 1406 * its vnodes. 1407 */ 1408 if (mntflags & MNT_FORCE) 1409 flags = FORCECLOSE; 1410 else 1411 flags = 0; 1412 if (pmp->iroot) { 1413 error = vflush(mp, 0, flags); 1414 if (error) 1415 goto failed; 1416 } 1417 1418 if (pmp->wthread_td) { 1419 mtx_lock(&pmp->wthread_mtx); 1420 pmp->wthread_destroy = 1; 1421 wakeup(&pmp->wthread_bioq); 1422 while (pmp->wthread_destroy != -1) { 1423 mtxsleep(&pmp->wthread_destroy, 1424 &pmp->wthread_mtx, 0, 1425 "umount-sleep", 0); 1426 } 1427 mtx_unlock(&pmp->wthread_mtx); 1428 pmp->wthread_td = NULL; 1429 } 1430 1431 for (i = 0; i < pmp->cluster.nchains; ++i) { 1432 hmp = pmp->cluster.chains[i]->hmp; 1433 1434 hammer2_vfs_unmount_hmp1(mp, hmp); 1435 1436 /* 1437 * Cleanup the root and super-root chain elements 1438 * (which should be clean). 1439 */ 1440 if (pmp->iroot) { 1441 #if REPORT_REFS_ERRORS 1442 if (pmp->iroot->refs != 1) 1443 kprintf("PMP->IROOT %p REFS WRONG %d\n", 1444 pmp->iroot, pmp->iroot->refs); 1445 #else 1446 KKASSERT(pmp->iroot->refs == 1); 1447 #endif 1448 /* ref for pmp->iroot */ 1449 hammer2_inode_drop(pmp->iroot); 1450 pmp->iroot = NULL; 1451 } 1452 1453 rchain = pmp->cluster.chains[i]; 1454 if (rchain) { 1455 atomic_clear_int(&rchain->flags, HAMMER2_CHAIN_MOUNTED); 1456 #if REPORT_REFS_ERRORS 1457 if (rchain->refs != 1) 1458 kprintf("PMP->RCHAIN %p REFS WRONG %d\n", 1459 rchain, rchain->refs); 1460 #else 1461 KKASSERT(rchain->refs == 1); 1462 #endif 1463 hammer2_chain_drop(rchain); 1464 pmp->cluster.chains[i] = NULL; 1465 } 1466 1467 hammer2_vfs_unmount_hmp2(mp, hmp); 1468 } 1469 1470 pmp->mp = NULL; 1471 mp->mnt_data = NULL; 1472 1473 kmalloc_destroy(&pmp->mmsg); 1474 kmalloc_destroy(&pmp->minode); 1475 1476 kfree(pmp, M_HAMMER2); 1477 error = 0; 1478 1479 failed: 1480 lockmgr(&hammer2_mntlk, LK_RELEASE); 1481 1482 return (error); 1483 } 1484 1485 static 1486 void 1487 hammer2_vfs_unmount_hmp1(struct mount *mp, hammer2_mount_t *hmp) 1488 { 1489 hammer2_mount_exlock(hmp); 1490 --hmp->pmp_count; 1491 1492 kprintf("hammer2_unmount hmp=%p pmpcnt=%d\n", hmp, hmp->pmp_count); 1493 1494 /* 1495 * Flush any left over chains. The voldata lock is only used 1496 * to synchronize against HAMMER2_CHAIN_MODIFIED_AUX. 1497 * 1498 * Flush twice to ensure that the freemap is completely 1499 * synchronized. If we only do it once the next mount's 1500 * recovery scan will have to do some fixups (which isn't 1501 * bad, but we don't want it to have to do it except when 1502 * recovering from a crash). 1503 */ 1504 hammer2_voldata_lock(hmp); 1505 if (((hmp->vchain.flags | hmp->fchain.flags) & 1506 HAMMER2_CHAIN_MODIFIED) || 1507 hmp->vchain.core->update_hi > hmp->voldata.mirror_tid || 1508 hmp->fchain.core->update_hi > hmp->voldata.freemap_tid) { 1509 hammer2_voldata_unlock(hmp, 0); 1510 hammer2_vfs_sync(mp, MNT_WAIT); 1511 /*hammer2_vfs_sync(mp, MNT_WAIT);*/ 1512 } else { 1513 hammer2_voldata_unlock(hmp, 0); 1514 } 1515 if (hmp->pmp_count == 0) { 1516 if (((hmp->vchain.flags | hmp->fchain.flags) & 1517 HAMMER2_CHAIN_MODIFIED) || 1518 (hmp->vchain.core->update_hi > 1519 hmp->voldata.mirror_tid) || 1520 (hmp->fchain.core->update_hi > 1521 hmp->voldata.freemap_tid)) { 1522 kprintf("hammer2_unmount: chains left over " 1523 "after final sync\n"); 1524 kprintf(" vchain %08x update_hi %jx/%jx\n", 1525 hmp->vchain.flags, 1526 hmp->voldata.mirror_tid, 1527 hmp->vchain.core->update_hi); 1528 kprintf(" fchain %08x update_hi %jx/%jx\n", 1529 hmp->fchain.flags, 1530 hmp->voldata.freemap_tid, 1531 hmp->fchain.core->update_hi); 1532 1533 if (hammer2_debug & 0x0010) 1534 Debugger("entered debugger"); 1535 } 1536 } 1537 } 1538 1539 static 1540 void 1541 hammer2_vfs_unmount_hmp2(struct mount *mp, hammer2_mount_t *hmp) 1542 { 1543 struct vnode *devvp; 1544 int dumpcnt; 1545 int ronly = ((mp->mnt_flag & MNT_RDONLY) != 0); 1546 1547 /* 1548 * If no PFS's left drop the master hammer2_mount for the 1549 * device. 1550 */ 1551 if (hmp->pmp_count == 0) { 1552 if (hmp->sroot) { 1553 hammer2_inode_drop(hmp->sroot); 1554 hmp->sroot = NULL; 1555 } 1556 1557 /* 1558 * Finish up with the device vnode 1559 */ 1560 if ((devvp = hmp->devvp) != NULL) { 1561 vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); 1562 vinvalbuf(devvp, (ronly ? 0 : V_SAVE), 0, 0); 1563 hmp->devvp = NULL; 1564 VOP_CLOSE(devvp, 1565 (ronly ? FREAD : FREAD|FWRITE)); 1566 vn_unlock(devvp); 1567 vrele(devvp); 1568 devvp = NULL; 1569 } 1570 1571 /* 1572 * Final drop of embedded freemap root chain to 1573 * clean up fchain.core (fchain structure is not 1574 * flagged ALLOCATED so it is cleaned out and then 1575 * left to rot). 1576 */ 1577 hammer2_chain_drop(&hmp->fchain); 1578 1579 /* 1580 * Final drop of embedded volume root chain to clean 1581 * up vchain.core (vchain structure is not flagged 1582 * ALLOCATED so it is cleaned out and then left to 1583 * rot). 1584 */ 1585 dumpcnt = 50; 1586 hammer2_dump_chain(&hmp->vchain, 0, &dumpcnt); 1587 dumpcnt = 50; 1588 hammer2_dump_chain(&hmp->fchain, 0, &dumpcnt); 1589 hammer2_mount_unlock(hmp); 1590 hammer2_chain_drop(&hmp->vchain); 1591 1592 hammer2_io_cleanup(hmp, &hmp->iotree); 1593 if (hmp->iofree_count) { 1594 kprintf("io_cleanup: %d I/O's left hanging\n", 1595 hmp->iofree_count); 1596 } 1597 1598 TAILQ_REMOVE(&hammer2_mntlist, hmp, mntentry); 1599 kmalloc_destroy(&hmp->mchain); 1600 kfree(hmp, M_HAMMER2); 1601 } else { 1602 hammer2_mount_unlock(hmp); 1603 } 1604 } 1605 1606 static 1607 int 1608 hammer2_vfs_vget(struct mount *mp, struct vnode *dvp, 1609 ino_t ino, struct vnode **vpp) 1610 { 1611 kprintf("hammer2_vget\n"); 1612 return (EOPNOTSUPP); 1613 } 1614 1615 static 1616 int 1617 hammer2_vfs_root(struct mount *mp, struct vnode **vpp) 1618 { 1619 hammer2_pfsmount_t *pmp; 1620 hammer2_chain_t *parent; 1621 int error; 1622 struct vnode *vp; 1623 1624 pmp = MPTOPMP(mp); 1625 if (pmp->iroot == NULL) { 1626 *vpp = NULL; 1627 error = EINVAL; 1628 } else { 1629 parent = hammer2_inode_lock_sh(pmp->iroot); 1630 vp = hammer2_igetv(pmp->iroot, &error); 1631 hammer2_inode_unlock_sh(pmp->iroot, parent); 1632 *vpp = vp; 1633 if (vp == NULL) 1634 kprintf("vnodefail\n"); 1635 } 1636 1637 return (error); 1638 } 1639 1640 /* 1641 * Filesystem status 1642 * 1643 * XXX incorporate ipdata->inode_quota and data_quota 1644 */ 1645 static 1646 int 1647 hammer2_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 1648 { 1649 hammer2_pfsmount_t *pmp; 1650 hammer2_mount_t *hmp; 1651 1652 pmp = MPTOPMP(mp); 1653 KKASSERT(pmp->cluster.nchains >= 1); 1654 hmp = pmp->cluster.chains[0]->hmp; /* XXX */ 1655 1656 mp->mnt_stat.f_files = pmp->inode_count; 1657 mp->mnt_stat.f_ffree = 0; 1658 mp->mnt_stat.f_blocks = hmp->voldata.allocator_size / HAMMER2_PBUFSIZE; 1659 mp->mnt_stat.f_bfree = hmp->voldata.allocator_free / HAMMER2_PBUFSIZE; 1660 mp->mnt_stat.f_bavail = mp->mnt_stat.f_bfree; 1661 1662 *sbp = mp->mnt_stat; 1663 return (0); 1664 } 1665 1666 static 1667 int 1668 hammer2_vfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) 1669 { 1670 hammer2_pfsmount_t *pmp; 1671 hammer2_mount_t *hmp; 1672 1673 pmp = MPTOPMP(mp); 1674 KKASSERT(pmp->cluster.nchains >= 1); 1675 hmp = pmp->cluster.chains[0]->hmp; /* XXX */ 1676 1677 mp->mnt_vstat.f_bsize = HAMMER2_PBUFSIZE; 1678 mp->mnt_vstat.f_files = pmp->inode_count; 1679 mp->mnt_vstat.f_ffree = 0; 1680 mp->mnt_vstat.f_blocks = hmp->voldata.allocator_size / HAMMER2_PBUFSIZE; 1681 mp->mnt_vstat.f_bfree = hmp->voldata.allocator_free / HAMMER2_PBUFSIZE; 1682 mp->mnt_vstat.f_bavail = mp->mnt_vstat.f_bfree; 1683 1684 *sbp = mp->mnt_vstat; 1685 return (0); 1686 } 1687 1688 /* 1689 * Mount-time recovery (RW mounts) 1690 * 1691 * Updates to the free block table are allowed to lag flushes by one 1692 * transaction. In case of a crash, then on a fresh mount we must do an 1693 * incremental scan of transaction id voldata.mirror_tid and make sure the 1694 * related blocks have been marked allocated. 1695 * 1696 */ 1697 struct hammer2_recovery_elm { 1698 TAILQ_ENTRY(hammer2_recovery_elm) entry; 1699 hammer2_chain_t *chain; 1700 }; 1701 1702 TAILQ_HEAD(hammer2_recovery_list, hammer2_recovery_elm); 1703 1704 static int hammer2_recovery_scan(hammer2_trans_t *trans, hammer2_mount_t *hmp, 1705 hammer2_chain_t *parent, 1706 struct hammer2_recovery_list *list, int depth); 1707 1708 #define HAMMER2_RECOVERY_MAXDEPTH 10 1709 1710 static 1711 int 1712 hammer2_recovery(hammer2_mount_t *hmp) 1713 { 1714 hammer2_trans_t trans; 1715 struct hammer2_recovery_list list; 1716 struct hammer2_recovery_elm *elm; 1717 hammer2_chain_t *parent; 1718 int error; 1719 int cumulative_error = 0; 1720 1721 hammer2_trans_init(&trans, NULL, hmp, 0); 1722 1723 TAILQ_INIT(&list); 1724 parent = hammer2_chain_lookup_init(&hmp->vchain, 0); 1725 cumulative_error = hammer2_recovery_scan(&trans, hmp, parent, &list, 0); 1726 hammer2_chain_lookup_done(parent); 1727 1728 while ((elm = TAILQ_FIRST(&list)) != NULL) { 1729 TAILQ_REMOVE(&list, elm, entry); 1730 parent = elm->chain; 1731 kfree(elm, M_HAMMER2); 1732 1733 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS | 1734 HAMMER2_RESOLVE_NOREF); 1735 error = hammer2_recovery_scan(&trans, hmp, parent, &list, 0); 1736 hammer2_chain_unlock(parent); 1737 if (error) 1738 cumulative_error = error; 1739 } 1740 hammer2_trans_done(&trans); 1741 1742 return cumulative_error; 1743 } 1744 1745 static 1746 int 1747 hammer2_recovery_scan(hammer2_trans_t *trans, hammer2_mount_t *hmp, 1748 hammer2_chain_t *parent, 1749 struct hammer2_recovery_list *list, int depth) 1750 { 1751 hammer2_chain_t *chain; 1752 int cache_index; 1753 int cumulative_error = 0; 1754 int error; 1755 1756 /* 1757 * Defer operation if depth limit reached. 1758 */ 1759 if (depth >= HAMMER2_RECOVERY_MAXDEPTH) { 1760 struct hammer2_recovery_elm *elm; 1761 1762 elm = kmalloc(sizeof(*elm), M_HAMMER2, M_ZERO | M_WAITOK); 1763 elm->chain = parent; 1764 hammer2_chain_ref(parent); 1765 TAILQ_INSERT_TAIL(list, elm, entry); 1766 /* unlocked by caller */ 1767 1768 return(0); 1769 } 1770 1771 /* 1772 * Adjust freemap to ensure that the block(s) are marked allocated. 1773 */ 1774 if (parent->bref.type != HAMMER2_BREF_TYPE_VOLUME) { 1775 hammer2_freemap_adjust(trans, hmp, &parent->bref, 1776 HAMMER2_FREEMAP_DORECOVER); 1777 } 1778 1779 /* 1780 * Check type for recursive scan 1781 */ 1782 switch(parent->bref.type) { 1783 case HAMMER2_BREF_TYPE_VOLUME: 1784 /* data already instantiated */ 1785 break; 1786 case HAMMER2_BREF_TYPE_INODE: 1787 /* 1788 * Must instantiate data for DIRECTDATA test and also 1789 * for recursion. 1790 */ 1791 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS); 1792 hammer2_chain_unlock(parent); 1793 if (parent->data->ipdata.op_flags & HAMMER2_OPFLAG_DIRECTDATA) { 1794 /* not applicable to recovery scan */ 1795 return 0; 1796 } 1797 break; 1798 case HAMMER2_BREF_TYPE_INDIRECT: 1799 /* 1800 * Must instantiate data for recursion 1801 */ 1802 hammer2_chain_lock(parent, HAMMER2_RESOLVE_ALWAYS); 1803 hammer2_chain_unlock(parent); 1804 break; 1805 case HAMMER2_BREF_TYPE_DATA: 1806 case HAMMER2_BREF_TYPE_FREEMAP: 1807 case HAMMER2_BREF_TYPE_FREEMAP_NODE: 1808 case HAMMER2_BREF_TYPE_FREEMAP_LEAF: 1809 /* not applicable to recovery scan */ 1810 return 0; 1811 break; 1812 default: 1813 return EDOM; 1814 } 1815 1816 /* 1817 * Recursive scan of the last flushed transaction only. We are 1818 * doing this without pmp assignments so don't leave the chains 1819 * hanging around after we are done with them. 1820 */ 1821 cache_index = 0; 1822 chain = hammer2_chain_scan(parent, NULL, &cache_index, 1823 HAMMER2_LOOKUP_NODATA); 1824 while (chain) { 1825 atomic_set_int(&chain->flags, HAMMER2_CHAIN_RELEASE); 1826 if (chain->bref.mirror_tid >= hmp->voldata.mirror_tid) { 1827 error = hammer2_recovery_scan(trans, hmp, chain, 1828 list, depth + 1); 1829 if (error) 1830 cumulative_error = error; 1831 } 1832 chain = hammer2_chain_scan(parent, chain, &cache_index, 1833 HAMMER2_LOOKUP_NODATA); 1834 } 1835 1836 return cumulative_error; 1837 } 1838 1839 /* 1840 * Sync the entire filesystem; this is called from the filesystem syncer 1841 * process periodically and whenever a user calls sync(1) on the hammer 1842 * mountpoint. 1843 * 1844 * Currently is actually called from the syncer! \o/ 1845 * 1846 * This task will have to snapshot the state of the dirty inode chain. 1847 * From that, it will have to make sure all of the inodes on the dirty 1848 * chain have IO initiated. We make sure that io is initiated for the root 1849 * block. 1850 * 1851 * If waitfor is set, we wait for media to acknowledge the new rootblock. 1852 * 1853 * THINKS: side A vs side B, to have sync not stall all I/O? 1854 */ 1855 int 1856 hammer2_vfs_sync(struct mount *mp, int waitfor) 1857 { 1858 struct hammer2_sync_info info; 1859 hammer2_chain_t *chain; 1860 hammer2_pfsmount_t *pmp; 1861 hammer2_mount_t *hmp; 1862 int flags; 1863 int error; 1864 int total_error; 1865 int force_fchain; 1866 int i; 1867 1868 pmp = MPTOPMP(mp); 1869 1870 /* 1871 * We can't acquire locks on existing vnodes while in a transaction 1872 * without risking a deadlock. This assumes that vfsync() can be 1873 * called without the vnode locked (which it can in DragonFly). 1874 * Otherwise we'd have to implement a multi-pass or flag the lock 1875 * failures and retry. 1876 * 1877 * The reclamation code interlocks with the sync list's token 1878 * (by removing the vnode from the scan list) before unlocking 1879 * the inode, giving us time to ref the inode. 1880 */ 1881 /*flags = VMSC_GETVP;*/ 1882 flags = 0; 1883 if (waitfor & MNT_LAZY) 1884 flags |= VMSC_ONEPASS; 1885 1886 /* 1887 * Initialize a normal transaction and sync everything out, then 1888 * wait for pending I/O to finish (so it gets a transaction id 1889 * that the meta-data flush will catch). 1890 */ 1891 hammer2_trans_init(&info.trans, pmp, NULL, 0); 1892 info.error = 0; 1893 info.waitfor = MNT_NOWAIT; 1894 vsyncscan(mp, flags | VMSC_NOWAIT, hammer2_sync_scan2, &info); 1895 1896 if (info.error == 0 && (waitfor & MNT_WAIT)) { 1897 info.waitfor = waitfor; 1898 vsyncscan(mp, flags, hammer2_sync_scan2, &info); 1899 1900 } 1901 hammer2_trans_done(&info.trans); 1902 hammer2_bioq_sync(info.trans.pmp); 1903 1904 /* 1905 * Start the flush transaction and flush all meta-data. 1906 */ 1907 hammer2_trans_init(&info.trans, pmp, NULL, HAMMER2_TRANS_ISFLUSH); 1908 1909 total_error = 0; 1910 for (i = 0; i < pmp->cluster.nchains; ++i) { 1911 hmp = pmp->cluster.chains[i]->hmp; 1912 1913 /* 1914 * Media mounts have two 'roots', vchain for the topology 1915 * and fchain for the free block table. Flush both. 1916 * 1917 * Note that the topology and free block table are handled 1918 * independently, so the free block table can wind up being 1919 * ahead of the topology. We depend on the bulk free scan 1920 * code to deal with any loose ends. 1921 */ 1922 #if 1 1923 hammer2_chain_lock(&hmp->fchain, HAMMER2_RESOLVE_ALWAYS); 1924 if ((hmp->fchain.flags & HAMMER2_CHAIN_MODIFIED) || 1925 hmp->fchain.core->update_hi > hmp->voldata.freemap_tid) { 1926 /* this will also modify vchain as a side effect */ 1927 chain = &hmp->fchain; 1928 hammer2_chain_flush(&info.trans, &chain); 1929 KKASSERT(chain == &hmp->fchain); 1930 } 1931 hammer2_chain_unlock(&hmp->fchain); 1932 #endif 1933 1934 hammer2_chain_lock(&hmp->vchain, HAMMER2_RESOLVE_ALWAYS); 1935 if ((hmp->vchain.flags & HAMMER2_CHAIN_MODIFIED) || 1936 hmp->vchain.core->update_hi > hmp->voldata.mirror_tid) { 1937 chain = &hmp->vchain; 1938 hammer2_chain_flush(&info.trans, &chain); 1939 KKASSERT(chain == &hmp->vchain); 1940 force_fchain = 1; 1941 } else { 1942 force_fchain = 0; 1943 } 1944 hammer2_chain_unlock(&hmp->vchain); 1945 1946 #if 0 1947 hammer2_chain_lock(&hmp->fchain, HAMMER2_RESOLVE_ALWAYS); 1948 if ((hmp->fchain.flags & HAMMER2_CHAIN_MODIFIED) || 1949 hmp->fchain.core->update_hi > hmp->voldata.freemap_tid || 1950 force_fchain) { 1951 /* this will also modify vchain as a side effect */ 1952 chain = &hmp->fchain; 1953 hammer2_chain_flush(&info.trans, &chain); 1954 KKASSERT(chain == &hmp->fchain); 1955 } 1956 hammer2_chain_unlock(&hmp->fchain); 1957 #endif 1958 1959 error = 0; 1960 1961 /* 1962 * We can't safely flush the volume header until we have 1963 * flushed any device buffers which have built up. 1964 * 1965 * XXX this isn't being incremental 1966 */ 1967 vn_lock(hmp->devvp, LK_EXCLUSIVE | LK_RETRY); 1968 error = VOP_FSYNC(hmp->devvp, MNT_WAIT, 0); 1969 vn_unlock(hmp->devvp); 1970 1971 /* 1972 * The flush code sets CHAIN_VOLUMESYNC to indicate that the 1973 * volume header needs synchronization via hmp->volsync. 1974 * 1975 * XXX synchronize the flag & data with only this flush XXX 1976 */ 1977 if (error == 0 && 1978 (hmp->vchain.flags & HAMMER2_CHAIN_VOLUMESYNC)) { 1979 struct buf *bp; 1980 1981 /* 1982 * Synchronize the disk before flushing the volume 1983 * header. 1984 */ 1985 bp = getpbuf(NULL); 1986 bp->b_bio1.bio_offset = 0; 1987 bp->b_bufsize = 0; 1988 bp->b_bcount = 0; 1989 bp->b_cmd = BUF_CMD_FLUSH; 1990 bp->b_bio1.bio_done = biodone_sync; 1991 bp->b_bio1.bio_flags |= BIO_SYNC; 1992 vn_strategy(hmp->devvp, &bp->b_bio1); 1993 biowait(&bp->b_bio1, "h2vol"); 1994 relpbuf(bp, NULL); 1995 1996 /* 1997 * Then we can safely flush the version of the 1998 * volume header synchronized by the flush code. 1999 */ 2000 i = hmp->volhdrno + 1; 2001 if (i >= HAMMER2_NUM_VOLHDRS) 2002 i = 0; 2003 if (i * HAMMER2_ZONE_BYTES64 + HAMMER2_SEGSIZE > 2004 hmp->volsync.volu_size) { 2005 i = 0; 2006 } 2007 kprintf("sync volhdr %d %jd\n", 2008 i, (intmax_t)hmp->volsync.volu_size); 2009 bp = getblk(hmp->devvp, i * HAMMER2_ZONE_BYTES64, 2010 HAMMER2_PBUFSIZE, 0, 0); 2011 atomic_clear_int(&hmp->vchain.flags, 2012 HAMMER2_CHAIN_VOLUMESYNC); 2013 bcopy(&hmp->volsync, bp->b_data, HAMMER2_PBUFSIZE); 2014 bawrite(bp); 2015 hmp->volhdrno = i; 2016 } 2017 if (error) 2018 total_error = error; 2019 } 2020 hammer2_trans_done(&info.trans); 2021 2022 return (total_error); 2023 } 2024 2025 /* 2026 * Sync passes. 2027 * 2028 * NOTE: We don't test update_lo/update_hi or MOVED here because the fsync 2029 * code won't flush on those flags. The syncer code above will do a 2030 * general meta-data flush globally that will catch these flags. 2031 */ 2032 2033 static int 2034 hammer2_sync_scan2(struct mount *mp, struct vnode *vp, void *data) 2035 { 2036 struct hammer2_sync_info *info = data; 2037 hammer2_inode_t *ip; 2038 int error; 2039 2040 /* 2041 * 2042 */ 2043 ip = VTOI(vp); 2044 if (ip == NULL) 2045 return(0); 2046 if (vp->v_type == VNON || vp->v_type == VBAD) { 2047 vclrisdirty(vp); 2048 return(0); 2049 } 2050 if ((ip->flags & HAMMER2_INODE_MODIFIED) == 0 && 2051 RB_EMPTY(&vp->v_rbdirty_tree)) { 2052 vclrisdirty(vp); 2053 return(0); 2054 } 2055 2056 /* 2057 * VOP_FSYNC will start a new transaction so replicate some code 2058 * here to do it inline (see hammer2_vop_fsync()). 2059 * 2060 * WARNING: The vfsync interacts with the buffer cache and might 2061 * block, we can't hold the inode lock at that time. 2062 * However, we MUST ref ip before blocking to ensure that 2063 * it isn't ripped out from under us (since we do not 2064 * hold a lock on the vnode). 2065 */ 2066 hammer2_inode_ref(ip); 2067 atomic_clear_int(&ip->flags, HAMMER2_INODE_MODIFIED); 2068 if (vp) 2069 vfsync(vp, MNT_NOWAIT, 1, NULL, NULL); 2070 2071 #if 0 2072 /* 2073 * XXX this interferes with flush operations mainly because the 2074 * same transaction id is being used by asynchronous buffer 2075 * operations above and can be reordered after the flush 2076 * below. 2077 */ 2078 parent = hammer2_inode_lock_ex(ip); 2079 hammer2_chain_flush(&info->trans, &parent); 2080 hammer2_inode_unlock_ex(ip, parent); 2081 #endif 2082 hammer2_inode_drop(ip); 2083 error = 0; 2084 #if 0 2085 error = VOP_FSYNC(vp, MNT_NOWAIT, 0); 2086 #endif 2087 if (error) 2088 info->error = error; 2089 return(0); 2090 } 2091 2092 static 2093 int 2094 hammer2_vfs_vptofh(struct vnode *vp, struct fid *fhp) 2095 { 2096 return (0); 2097 } 2098 2099 static 2100 int 2101 hammer2_vfs_fhtovp(struct mount *mp, struct vnode *rootvp, 2102 struct fid *fhp, struct vnode **vpp) 2103 { 2104 return (0); 2105 } 2106 2107 static 2108 int 2109 hammer2_vfs_checkexp(struct mount *mp, struct sockaddr *nam, 2110 int *exflagsp, struct ucred **credanonp) 2111 { 2112 return (0); 2113 } 2114 2115 /* 2116 * Support code for hammer2_mount(). Read, verify, and install the volume 2117 * header into the HMP 2118 * 2119 * XXX read four volhdrs and use the one with the highest TID whos CRC 2120 * matches. 2121 * 2122 * XXX check iCRCs. 2123 * 2124 * XXX For filesystems w/ less than 4 volhdrs, make sure to not write to 2125 * nonexistant locations. 2126 * 2127 * XXX Record selected volhdr and ring updates to each of 4 volhdrs 2128 */ 2129 static 2130 int 2131 hammer2_install_volume_header(hammer2_mount_t *hmp) 2132 { 2133 hammer2_volume_data_t *vd; 2134 struct buf *bp; 2135 hammer2_crc32_t crc0, crc, bcrc0, bcrc; 2136 int error_reported; 2137 int error; 2138 int valid; 2139 int i; 2140 2141 error_reported = 0; 2142 error = 0; 2143 valid = 0; 2144 bp = NULL; 2145 2146 /* 2147 * There are up to 4 copies of the volume header (syncs iterate 2148 * between them so there is no single master). We don't trust the 2149 * volu_size field so we don't know precisely how large the filesystem 2150 * is, so depend on the OS to return an error if we go beyond the 2151 * block device's EOF. 2152 */ 2153 for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) { 2154 error = bread(hmp->devvp, i * HAMMER2_ZONE_BYTES64, 2155 HAMMER2_VOLUME_BYTES, &bp); 2156 if (error) { 2157 brelse(bp); 2158 bp = NULL; 2159 continue; 2160 } 2161 2162 vd = (struct hammer2_volume_data *) bp->b_data; 2163 if ((vd->magic != HAMMER2_VOLUME_ID_HBO) && 2164 (vd->magic != HAMMER2_VOLUME_ID_ABO)) { 2165 brelse(bp); 2166 bp = NULL; 2167 continue; 2168 } 2169 2170 if (vd->magic == HAMMER2_VOLUME_ID_ABO) { 2171 /* XXX: Reversed-endianness filesystem */ 2172 kprintf("hammer2: reverse-endian filesystem detected"); 2173 brelse(bp); 2174 bp = NULL; 2175 continue; 2176 } 2177 2178 crc = vd->icrc_sects[HAMMER2_VOL_ICRC_SECT0]; 2179 crc0 = hammer2_icrc32(bp->b_data + HAMMER2_VOLUME_ICRC0_OFF, 2180 HAMMER2_VOLUME_ICRC0_SIZE); 2181 bcrc = vd->icrc_sects[HAMMER2_VOL_ICRC_SECT1]; 2182 bcrc0 = hammer2_icrc32(bp->b_data + HAMMER2_VOLUME_ICRC1_OFF, 2183 HAMMER2_VOLUME_ICRC1_SIZE); 2184 if ((crc0 != crc) || (bcrc0 != bcrc)) { 2185 kprintf("hammer2 volume header crc " 2186 "mismatch copy #%d %08x/%08x\n", 2187 i, crc0, crc); 2188 error_reported = 1; 2189 brelse(bp); 2190 bp = NULL; 2191 continue; 2192 } 2193 if (valid == 0 || hmp->voldata.mirror_tid < vd->mirror_tid) { 2194 valid = 1; 2195 hmp->voldata = *vd; 2196 hmp->volhdrno = i; 2197 } 2198 brelse(bp); 2199 bp = NULL; 2200 } 2201 if (valid) { 2202 hmp->volsync = hmp->voldata; 2203 error = 0; 2204 if (error_reported || bootverbose || 1) { /* 1/DEBUG */ 2205 kprintf("hammer2: using volume header #%d\n", 2206 hmp->volhdrno); 2207 } 2208 } else { 2209 error = EINVAL; 2210 kprintf("hammer2: no valid volume headers found!\n"); 2211 } 2212 return (error); 2213 } 2214 2215 /* 2216 * Reconnect using the passed file pointer. The caller must ref the 2217 * fp for us. 2218 */ 2219 void 2220 hammer2_cluster_reconnect(hammer2_pfsmount_t *pmp, struct file *fp) 2221 { 2222 hammer2_inode_data_t *ipdata; 2223 hammer2_chain_t *parent; 2224 hammer2_mount_t *hmp; 2225 size_t name_len; 2226 2227 hmp = pmp->cluster.chains[0]->hmp; /* XXX */ 2228 2229 /* 2230 * Closes old comm descriptor, kills threads, cleans up 2231 * states, then installs the new descriptor and creates 2232 * new threads. 2233 */ 2234 kdmsg_iocom_reconnect(&pmp->iocom, fp, "hammer2"); 2235 2236 /* 2237 * Setup LNK_CONN fields for autoinitiated state machine 2238 */ 2239 parent = hammer2_inode_lock_ex(pmp->iroot); 2240 ipdata = &parent->data->ipdata; 2241 pmp->iocom.auto_lnk_conn.pfs_clid = ipdata->pfs_clid; 2242 pmp->iocom.auto_lnk_conn.pfs_fsid = ipdata->pfs_fsid; 2243 pmp->iocom.auto_lnk_conn.pfs_type = ipdata->pfs_type; 2244 pmp->iocom.auto_lnk_conn.proto_version = DMSG_SPAN_PROTO_1; 2245 pmp->iocom.auto_lnk_conn.peer_type = hmp->voldata.peer_type; 2246 2247 /* 2248 * Filter adjustment. Clients do not need visibility into other 2249 * clients (otherwise millions of clients would present a serious 2250 * problem). The fs_label also serves to restrict the namespace. 2251 */ 2252 pmp->iocom.auto_lnk_conn.peer_mask = 1LLU << HAMMER2_PEER_HAMMER2; 2253 pmp->iocom.auto_lnk_conn.pfs_mask = (uint64_t)-1; 2254 switch (ipdata->pfs_type) { 2255 case DMSG_PFSTYPE_CLIENT: 2256 pmp->iocom.auto_lnk_conn.peer_mask &= 2257 ~(1LLU << DMSG_PFSTYPE_CLIENT); 2258 break; 2259 default: 2260 break; 2261 } 2262 2263 name_len = ipdata->name_len; 2264 if (name_len >= sizeof(pmp->iocom.auto_lnk_conn.fs_label)) 2265 name_len = sizeof(pmp->iocom.auto_lnk_conn.fs_label) - 1; 2266 bcopy(ipdata->filename, 2267 pmp->iocom.auto_lnk_conn.fs_label, 2268 name_len); 2269 pmp->iocom.auto_lnk_conn.fs_label[name_len] = 0; 2270 2271 /* 2272 * Setup LNK_SPAN fields for autoinitiated state machine 2273 */ 2274 pmp->iocom.auto_lnk_span.pfs_clid = ipdata->pfs_clid; 2275 pmp->iocom.auto_lnk_span.pfs_fsid = ipdata->pfs_fsid; 2276 pmp->iocom.auto_lnk_span.pfs_type = ipdata->pfs_type; 2277 pmp->iocom.auto_lnk_span.peer_type = hmp->voldata.peer_type; 2278 pmp->iocom.auto_lnk_span.proto_version = DMSG_SPAN_PROTO_1; 2279 name_len = ipdata->name_len; 2280 if (name_len >= sizeof(pmp->iocom.auto_lnk_span.fs_label)) 2281 name_len = sizeof(pmp->iocom.auto_lnk_span.fs_label) - 1; 2282 bcopy(ipdata->filename, 2283 pmp->iocom.auto_lnk_span.fs_label, 2284 name_len); 2285 pmp->iocom.auto_lnk_span.fs_label[name_len] = 0; 2286 hammer2_inode_unlock_ex(pmp->iroot, parent); 2287 2288 kdmsg_iocom_autoinitiate(&pmp->iocom, hammer2_autodmsg); 2289 } 2290 2291 static int 2292 hammer2_rcvdmsg(kdmsg_msg_t *msg) 2293 { 2294 switch(msg->any.head.cmd & DMSGF_TRANSMASK) { 2295 case DMSG_DBG_SHELL: 2296 /* 2297 * (non-transaction) 2298 * Execute shell command (not supported atm) 2299 */ 2300 kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP); 2301 break; 2302 case DMSG_DBG_SHELL | DMSGF_REPLY: 2303 /* 2304 * (non-transaction) 2305 */ 2306 if (msg->aux_data) { 2307 msg->aux_data[msg->aux_size - 1] = 0; 2308 kprintf("HAMMER2 DBG: %s\n", msg->aux_data); 2309 } 2310 break; 2311 default: 2312 /* 2313 * Unsupported message received. We only need to 2314 * reply if it's a transaction in order to close our end. 2315 * Ignore any one-way messages are any further messages 2316 * associated with the transaction. 2317 * 2318 * NOTE: This case also includes DMSG_LNK_ERROR messages 2319 * which might be one-way, replying to those would 2320 * cause an infinite ping-pong. 2321 */ 2322 if (msg->any.head.cmd & DMSGF_CREATE) 2323 kdmsg_msg_reply(msg, DMSG_ERR_NOSUPP); 2324 break; 2325 } 2326 return(0); 2327 } 2328 2329 /* 2330 * This function is called after KDMSG has automatically handled processing 2331 * of a LNK layer message (typically CONN, SPAN, or CIRC). 2332 * 2333 * We tag off the LNK_CONN to trigger our LNK_VOLCONF messages which 2334 * advertises all available hammer2 super-root volumes. 2335 */ 2336 static void 2337 hammer2_autodmsg(kdmsg_msg_t *msg) 2338 { 2339 hammer2_pfsmount_t *pmp = msg->iocom->handle; 2340 hammer2_mount_t *hmp = pmp->cluster.chains[0]->hmp; /* XXX */ 2341 int copyid; 2342 2343 /* 2344 * We only care about replies to our LNK_CONN auto-request. kdmsg 2345 * has already processed the reply, we use this calback as a shim 2346 * to know when we can advertise available super-root volumes. 2347 */ 2348 if ((msg->any.head.cmd & DMSGF_TRANSMASK) != 2349 (DMSG_LNK_CONN | DMSGF_CREATE | DMSGF_REPLY) || 2350 msg->state == NULL) { 2351 return; 2352 } 2353 2354 kprintf("LNK_CONN REPLY RECEIVED CMD %08x\n", msg->any.head.cmd); 2355 2356 if (msg->any.head.cmd & DMSGF_CREATE) { 2357 kprintf("HAMMER2: VOLDATA DUMP\n"); 2358 2359 /* 2360 * Dump the configuration stored in the volume header 2361 */ 2362 hammer2_voldata_lock(hmp); 2363 for (copyid = 0; copyid < HAMMER2_COPYID_COUNT; ++copyid) { 2364 if (hmp->voldata.copyinfo[copyid].copyid == 0) 2365 continue; 2366 hammer2_volconf_update(pmp, copyid); 2367 } 2368 hammer2_voldata_unlock(hmp, 0); 2369 } 2370 if ((msg->any.head.cmd & DMSGF_DELETE) && 2371 msg->state && (msg->state->txcmd & DMSGF_DELETE) == 0) { 2372 kprintf("HAMMER2: CONN WAS TERMINATED\n"); 2373 } 2374 } 2375 2376 /* 2377 * Volume configuration updates are passed onto the userland service 2378 * daemon via the open LNK_CONN transaction. 2379 */ 2380 void 2381 hammer2_volconf_update(hammer2_pfsmount_t *pmp, int index) 2382 { 2383 hammer2_mount_t *hmp = pmp->cluster.chains[0]->hmp; /* XXX */ 2384 kdmsg_msg_t *msg; 2385 2386 /* XXX interlock against connection state termination */ 2387 kprintf("volconf update %p\n", pmp->iocom.conn_state); 2388 if (pmp->iocom.conn_state) { 2389 kprintf("TRANSMIT VOLCONF VIA OPEN CONN TRANSACTION\n"); 2390 msg = kdmsg_msg_alloc_state(pmp->iocom.conn_state, 2391 DMSG_LNK_VOLCONF, NULL, NULL); 2392 msg->any.lnk_volconf.copy = hmp->voldata.copyinfo[index]; 2393 msg->any.lnk_volconf.mediaid = hmp->voldata.fsid; 2394 msg->any.lnk_volconf.index = index; 2395 kdmsg_msg_write(msg); 2396 } 2397 } 2398 2399 /* 2400 * This handles hysteresis on regular file flushes. Because the BIOs are 2401 * routed to a thread it is possible for an excessive number to build up 2402 * and cause long front-end stalls long before the runningbuffspace limit 2403 * is hit, so we implement hammer2_flush_pipe to control the 2404 * hysteresis. 2405 * 2406 * This is a particular problem when compression is used. 2407 */ 2408 void 2409 hammer2_lwinprog_ref(hammer2_pfsmount_t *pmp) 2410 { 2411 atomic_add_int(&pmp->count_lwinprog, 1); 2412 } 2413 2414 void 2415 hammer2_lwinprog_drop(hammer2_pfsmount_t *pmp) 2416 { 2417 int lwinprog; 2418 2419 lwinprog = atomic_fetchadd_int(&pmp->count_lwinprog, -1); 2420 if ((lwinprog & HAMMER2_LWINPROG_WAITING) && 2421 (lwinprog & HAMMER2_LWINPROG_MASK) <= hammer2_flush_pipe * 2 / 3) { 2422 atomic_clear_int(&pmp->count_lwinprog, 2423 HAMMER2_LWINPROG_WAITING); 2424 wakeup(&pmp->count_lwinprog); 2425 } 2426 } 2427 2428 void 2429 hammer2_lwinprog_wait(hammer2_pfsmount_t *pmp) 2430 { 2431 int lwinprog; 2432 2433 for (;;) { 2434 lwinprog = pmp->count_lwinprog; 2435 cpu_ccfence(); 2436 if ((lwinprog & HAMMER2_LWINPROG_MASK) < hammer2_flush_pipe) 2437 break; 2438 tsleep_interlock(&pmp->count_lwinprog, 0); 2439 atomic_set_int(&pmp->count_lwinprog, HAMMER2_LWINPROG_WAITING); 2440 lwinprog = pmp->count_lwinprog; 2441 if ((lwinprog & HAMMER2_LWINPROG_MASK) < hammer2_flush_pipe) 2442 break; 2443 tsleep(&pmp->count_lwinprog, PINTERLOCKED, "h2wpipe", hz); 2444 } 2445 } 2446 2447 void 2448 hammer2_dump_chain(hammer2_chain_t *chain, int tab, int *countp) 2449 { 2450 hammer2_chain_layer_t *layer; 2451 hammer2_chain_t *scan; 2452 hammer2_chain_t *first_parent; 2453 2454 --*countp; 2455 if (*countp == 0) { 2456 kprintf("%*.*s...\n", tab, tab, ""); 2457 return; 2458 } 2459 if (*countp < 0) 2460 return; 2461 first_parent = chain->core ? TAILQ_FIRST(&chain->core->ownerq) : NULL; 2462 kprintf("%*.*schain %p.%d %016jx/%d mir=%016jx\n", 2463 tab, tab, "", 2464 chain, chain->bref.type, 2465 chain->bref.key, chain->bref.keybits, 2466 chain->bref.mirror_tid); 2467 2468 kprintf("%*.*s [%08x] (%s) dt=%016jx refs=%d\n", 2469 tab, tab, "", 2470 chain->flags, 2471 ((chain->bref.type == HAMMER2_BREF_TYPE_INODE && 2472 chain->data) ? (char *)chain->data->ipdata.filename : "?"), 2473 chain->delete_tid, 2474 chain->refs); 2475 2476 kprintf("%*.*s core %p [%08x] lo=%08jx hi=%08jx fp=%p np=%p", 2477 tab, tab, "", 2478 chain->core, (chain->core ? chain->core->flags : 0), 2479 (chain->core ? chain->core->update_lo : -1), 2480 (chain->core ? chain->core->update_hi : -1), 2481 first_parent, 2482 (first_parent ? TAILQ_NEXT(chain, core_entry) : NULL)); 2483 2484 if (first_parent) 2485 kprintf(" [fpflags %08x fprefs %d\n", 2486 first_parent->flags, 2487 first_parent->refs); 2488 if (chain->core == NULL || TAILQ_EMPTY(&chain->core->layerq)) 2489 kprintf("\n"); 2490 else 2491 kprintf(" {\n"); 2492 if (chain->core) { 2493 TAILQ_FOREACH(layer, &chain->core->layerq, entry) { 2494 RB_FOREACH(scan, hammer2_chain_tree, &layer->rbtree) { 2495 hammer2_dump_chain(scan, tab + 4, countp); 2496 } 2497 } 2498 } 2499 if (chain->core && !TAILQ_EMPTY(&chain->core->layerq)) { 2500 if (chain->bref.type == HAMMER2_BREF_TYPE_INODE && chain->data) 2501 kprintf("%*.*s}(%s)\n", tab, tab, "", 2502 chain->data->ipdata.filename); 2503 else 2504 kprintf("%*.*s}\n", tab, tab, ""); 2505 } 2506 } 2507