1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/systm.h> 30 #include <sys/types.h> 31 #include <sys/vnode.h> 32 #include <sys/buf.h> 33 #include <sys/errno.h> 34 #include <sys/fssnap_if.h> 35 #include <sys/fs/ufs_inode.h> 36 #include <sys/fs/ufs_filio.h> 37 #include <sys/sysmacros.h> 38 #include <sys/modctl.h> 39 #include <sys/fs/ufs_log.h> 40 #include <sys/fs/ufs_bio.h> 41 #include <sys/fs/ufs_fsdir.h> 42 #include <sys/debug.h> 43 #include <sys/atomic.h> 44 #include <sys/kmem.h> 45 #include <sys/inttypes.h> 46 #include <sys/vfs.h> 47 #include <sys/mntent.h> 48 #include <sys/conf.h> 49 #include <sys/param.h> 50 #include <sys/kstat.h> 51 #include <sys/cmn_err.h> 52 53 extern kmutex_t ufs_scan_lock; 54 55 static kmutex_t log_mutex; /* general purpose log layer lock */ 56 kmutex_t ml_scan; /* Scan thread syncronization */ 57 kcondvar_t ml_scan_cv; /* Scan thread syncronization */ 58 59 struct kmem_cache *lufs_sv; 60 struct kmem_cache *lufs_bp; 61 62 /* Tunables */ 63 uint_t ldl_maxlogsize = LDL_MAXLOGSIZE; 64 uint_t ldl_minlogsize = LDL_MINLOGSIZE; 65 uint32_t ldl_divisor = LDL_DIVISOR; 66 uint32_t ldl_mintransfer = LDL_MINTRANSFER; 67 uint32_t ldl_maxtransfer = LDL_MAXTRANSFER; 68 uint32_t ldl_minbufsize = LDL_MINBUFSIZE; 69 70 uint32_t last_loghead_ident = 0; 71 72 /* 73 * Logging delta and roll statistics 74 */ 75 struct delta_kstats { 76 kstat_named_t ds_superblock_deltas; 77 kstat_named_t ds_bitmap_deltas; 78 kstat_named_t ds_suminfo_deltas; 79 kstat_named_t ds_allocblk_deltas; 80 kstat_named_t ds_ab0_deltas; 81 kstat_named_t ds_dir_deltas; 82 kstat_named_t ds_inode_deltas; 83 kstat_named_t ds_fbiwrite_deltas; 84 kstat_named_t ds_quota_deltas; 85 kstat_named_t ds_shadow_deltas; 86 87 kstat_named_t ds_superblock_rolled; 88 kstat_named_t ds_bitmap_rolled; 89 kstat_named_t ds_suminfo_rolled; 90 kstat_named_t ds_allocblk_rolled; 91 kstat_named_t ds_ab0_rolled; 92 kstat_named_t ds_dir_rolled; 93 kstat_named_t ds_inode_rolled; 94 kstat_named_t ds_fbiwrite_rolled; 95 kstat_named_t ds_quota_rolled; 96 kstat_named_t ds_shadow_rolled; 97 } dkstats = { 98 { "superblock_deltas", KSTAT_DATA_UINT64 }, 99 { "bitmap_deltas", KSTAT_DATA_UINT64 }, 100 { "suminfo_deltas", KSTAT_DATA_UINT64 }, 101 { "allocblk_deltas", KSTAT_DATA_UINT64 }, 102 { "ab0_deltas", KSTAT_DATA_UINT64 }, 103 { "dir_deltas", KSTAT_DATA_UINT64 }, 104 { "inode_deltas", KSTAT_DATA_UINT64 }, 105 { "fbiwrite_deltas", KSTAT_DATA_UINT64 }, 106 { "quota_deltas", KSTAT_DATA_UINT64 }, 107 { "shadow_deltas", KSTAT_DATA_UINT64 }, 108 109 { "superblock_rolled", KSTAT_DATA_UINT64 }, 110 { "bitmap_rolled", KSTAT_DATA_UINT64 }, 111 { "suminfo_rolled", KSTAT_DATA_UINT64 }, 112 { "allocblk_rolled", KSTAT_DATA_UINT64 }, 113 { "ab0_rolled", KSTAT_DATA_UINT64 }, 114 { "dir_rolled", KSTAT_DATA_UINT64 }, 115 { "inode_rolled", KSTAT_DATA_UINT64 }, 116 { "fbiwrite_rolled", KSTAT_DATA_UINT64 }, 117 { "quota_rolled", KSTAT_DATA_UINT64 }, 118 { "shadow_rolled", KSTAT_DATA_UINT64 } 119 }; 120 121 uint64_t delta_stats[DT_MAX]; 122 uint64_t roll_stats[DT_MAX]; 123 124 /* 125 * General logging kstats 126 */ 127 struct logstats logstats = { 128 { "master_reads", KSTAT_DATA_UINT64 }, 129 { "master_writes", KSTAT_DATA_UINT64 }, 130 { "log_reads_inmem", KSTAT_DATA_UINT64 }, 131 { "log_reads", KSTAT_DATA_UINT64 }, 132 { "log_writes", KSTAT_DATA_UINT64 }, 133 { "log_master_reads", KSTAT_DATA_UINT64 }, 134 { "log_roll_reads", KSTAT_DATA_UINT64 }, 135 { "log_roll_writes", KSTAT_DATA_UINT64 } 136 }; 137 138 int 139 trans_not_done(struct buf *cb) 140 { 141 sema_v(&cb->b_io); 142 return (0); 143 } 144 145 static void 146 trans_wait_panic(struct buf *cb) 147 { 148 while ((cb->b_flags & B_DONE) == 0) 149 drv_usecwait(10); 150 } 151 152 int 153 trans_not_wait(struct buf *cb) 154 { 155 /* 156 * In case of panic, busy wait for completion 157 */ 158 if (panicstr) 159 trans_wait_panic(cb); 160 else 161 sema_p(&cb->b_io); 162 163 return (geterror(cb)); 164 } 165 166 int 167 trans_wait(struct buf *cb) 168 { 169 /* 170 * In case of panic, busy wait for completion and run md daemon queues 171 */ 172 if (panicstr) 173 trans_wait_panic(cb); 174 return (biowait(cb)); 175 } 176 177 static void 178 setsum(int32_t *sp, int32_t *lp, int nb) 179 { 180 int32_t csum = 0; 181 182 *sp = 0; 183 nb /= sizeof (int32_t); 184 while (nb--) 185 csum += *lp++; 186 *sp = csum; 187 } 188 189 static int 190 checksum(int32_t *sp, int32_t *lp, int nb) 191 { 192 int32_t ssum = *sp; 193 194 setsum(sp, lp, nb); 195 if (ssum != *sp) { 196 *sp = ssum; 197 return (0); 198 } 199 return (1); 200 } 201 202 void 203 lufs_unsnarf(ufsvfs_t *ufsvfsp) 204 { 205 ml_unit_t *ul; 206 mt_map_t *mtm; 207 208 ul = ufsvfsp->vfs_log; 209 if (ul == NULL) 210 return; 211 212 mtm = ul->un_logmap; 213 214 /* 215 * Wait for a pending top_issue_sync which is 216 * dispatched (via taskq_dispatch()) but hasnt completed yet. 217 */ 218 219 mutex_enter(&mtm->mtm_lock); 220 221 while (mtm->mtm_taskq_sync_count != 0) { 222 cv_wait(&mtm->mtm_cv, &mtm->mtm_lock); 223 } 224 225 mutex_exit(&mtm->mtm_lock); 226 227 /* Roll committed transactions */ 228 logmap_roll_dev(ul); 229 230 /* Kill the roll thread */ 231 logmap_kill_roll(ul); 232 233 /* release saved alloction info */ 234 if (ul->un_ebp) 235 kmem_free(ul->un_ebp, ul->un_nbeb); 236 237 /* release circular bufs */ 238 free_cirbuf(&ul->un_rdbuf); 239 free_cirbuf(&ul->un_wrbuf); 240 241 /* release maps */ 242 if (ul->un_logmap) 243 ul->un_logmap = map_put(ul->un_logmap); 244 if (ul->un_deltamap) 245 ul->un_deltamap = map_put(ul->un_deltamap); 246 if (ul->un_matamap) 247 ul->un_matamap = map_put(ul->un_matamap); 248 249 mutex_destroy(&ul->un_log_mutex); 250 mutex_destroy(&ul->un_state_mutex); 251 252 /* release state buffer MUST BE LAST!! (contains our ondisk data) */ 253 if (ul->un_bp) 254 brelse(ul->un_bp); 255 kmem_free(ul, sizeof (*ul)); 256 257 ufsvfsp->vfs_log = NULL; 258 } 259 260 int 261 lufs_snarf(ufsvfs_t *ufsvfsp, struct fs *fs, int ronly) 262 { 263 buf_t *bp, *tbp; 264 ml_unit_t *ul; 265 extent_block_t *ebp; 266 ic_extent_block_t *nebp; 267 size_t nb; 268 daddr_t bno; /* in disk blocks */ 269 int i; 270 271 /* LINTED: warning: logical expression always true: op "||" */ 272 ASSERT(sizeof (ml_odunit_t) < DEV_BSIZE); 273 274 /* 275 * Get the allocation table 276 * During a remount the superblock pointed to by the ufsvfsp 277 * is out of date. Hence the need for the ``new'' superblock 278 * pointer, fs, passed in as a parameter. 279 */ 280 bp = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, logbtodb(fs, fs->fs_logbno), 281 fs->fs_bsize); 282 if (bp->b_flags & B_ERROR) { 283 brelse(bp); 284 return (EIO); 285 } 286 ebp = (void *)bp->b_un.b_addr; 287 if (!checksum(&ebp->chksum, (int32_t *)bp->b_un.b_addr, 288 fs->fs_bsize)) { 289 brelse(bp); 290 return (ENODEV); 291 } 292 293 /* 294 * It is possible to get log blocks with all zeros. 295 * We should also check for nextents to be zero in such case. 296 */ 297 if (ebp->type != LUFS_EXTENTS || ebp->nextents == 0) { 298 brelse(bp); 299 return (EDOM); 300 } 301 /* 302 * Put allocation into memory. This requires conversion between 303 * on the ondisk format of the extent (type extent_t) and the 304 * in-core format of the extent (type ic_extent_t). The 305 * difference is the in-core form of the extent block stores 306 * the physical offset of the extent in disk blocks, which 307 * can require more than a 32-bit field. 308 */ 309 nb = (size_t)(sizeof (ic_extent_block_t) + 310 ((ebp->nextents - 1) * sizeof (ic_extent_t))); 311 nebp = kmem_alloc(nb, KM_SLEEP); 312 nebp->ic_nextents = ebp->nextents; 313 nebp->ic_nbytes = ebp->nbytes; 314 nebp->ic_nextbno = ebp->nextbno; 315 for (i = 0; i < ebp->nextents; i++) { 316 nebp->ic_extents[i].ic_lbno = ebp->extents[i].lbno; 317 nebp->ic_extents[i].ic_nbno = ebp->extents[i].nbno; 318 nebp->ic_extents[i].ic_pbno = 319 logbtodb(fs, ebp->extents[i].pbno); 320 } 321 brelse(bp); 322 323 /* 324 * Get the log state 325 */ 326 bno = nebp->ic_extents[0].ic_pbno; 327 bp = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, bno, DEV_BSIZE); 328 if (bp->b_flags & B_ERROR) { 329 brelse(bp); 330 bp = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, bno + 1, DEV_BSIZE); 331 if (bp->b_flags & B_ERROR) { 332 brelse(bp); 333 kmem_free(nebp, nb); 334 return (EIO); 335 } 336 } 337 338 /* 339 * Put ondisk struct into an anonymous buffer 340 * This buffer will contain the memory for the ml_odunit struct 341 */ 342 tbp = ngeteblk(dbtob(LS_SECTORS)); 343 tbp->b_edev = bp->b_edev; 344 tbp->b_dev = bp->b_dev; 345 tbp->b_blkno = bno; 346 bcopy(bp->b_un.b_addr, tbp->b_un.b_addr, DEV_BSIZE); 347 bcopy(bp->b_un.b_addr, tbp->b_un.b_addr + DEV_BSIZE, DEV_BSIZE); 348 bp->b_flags |= (B_STALE | B_AGE); 349 brelse(bp); 350 bp = tbp; 351 352 /* 353 * Verify the log state 354 * 355 * read/only mounts w/bad logs are allowed. umount will 356 * eventually roll the bad log until the first IO error. 357 * fsck will then repair the file system. 358 * 359 * read/write mounts with bad logs are not allowed. 360 * 361 */ 362 ul = (ml_unit_t *)kmem_zalloc(sizeof (*ul), KM_SLEEP); 363 bcopy(bp->b_un.b_addr, &ul->un_ondisk, sizeof (ml_odunit_t)); 364 if ((ul->un_chksum != ul->un_head_ident + ul->un_tail_ident) || 365 (ul->un_version != LUFS_VERSION_LATEST) || 366 (!ronly && ul->un_badlog)) { 367 kmem_free(ul, sizeof (*ul)); 368 brelse(bp); 369 kmem_free(nebp, nb); 370 return (EIO); 371 } 372 /* 373 * Initialize the incore-only fields 374 */ 375 if (ronly) 376 ul->un_flags |= LDL_NOROLL; 377 ul->un_bp = bp; 378 ul->un_ufsvfs = ufsvfsp; 379 ul->un_dev = ufsvfsp->vfs_dev; 380 ul->un_ebp = nebp; 381 ul->un_nbeb = nb; 382 ul->un_maxresv = btodb(ul->un_logsize) * LDL_USABLE_BSIZE; 383 ul->un_deltamap = map_get(ul, deltamaptype, DELTAMAP_NHASH); 384 ul->un_logmap = map_get(ul, logmaptype, LOGMAP_NHASH); 385 if (ul->un_debug & MT_MATAMAP) 386 ul->un_matamap = map_get(ul, matamaptype, DELTAMAP_NHASH); 387 mutex_init(&ul->un_log_mutex, NULL, MUTEX_DEFAULT, NULL); 388 mutex_init(&ul->un_state_mutex, NULL, MUTEX_DEFAULT, NULL); 389 390 /* 391 * Aquire the ufs_scan_lock before linking the mtm data 392 * structure so that we keep ufs_sync() and ufs_update() away 393 * when they execute the ufs_scan_inodes() run while we're in 394 * progress of enabling/disabling logging. 395 */ 396 mutex_enter(&ufs_scan_lock); 397 ufsvfsp->vfs_log = ul; 398 399 /* remember the state of the log before the log scan */ 400 logmap_logscan(ul); 401 mutex_exit(&ufs_scan_lock); 402 403 /* 404 * Error during scan 405 * 406 * If this is a read/only mount; ignore the error. 407 * At a later time umount/fsck will repair the fs. 408 * 409 */ 410 if (ul->un_flags & LDL_ERROR) { 411 if (!ronly) { 412 /* 413 * Aquire the ufs_scan_lock before de-linking 414 * the mtm data structure so that we keep ufs_sync() 415 * and ufs_update() away when they execute the 416 * ufs_scan_inodes() run while we're in progress of 417 * enabling/disabling logging. 418 */ 419 mutex_enter(&ufs_scan_lock); 420 lufs_unsnarf(ufsvfsp); 421 mutex_exit(&ufs_scan_lock); 422 return (EIO); 423 } 424 ul->un_flags &= ~LDL_ERROR; 425 } 426 if (!ronly) 427 logmap_start_roll(ul); 428 return (0); 429 } 430 431 static int 432 lufs_initialize( 433 ufsvfs_t *ufsvfsp, 434 daddr_t bno, 435 size_t nb, 436 struct fiolog *flp) 437 { 438 ml_odunit_t *ud, *ud2; 439 buf_t *bp; 440 struct timeval tv; 441 442 /* LINTED: warning: logical expression always true: op "||" */ 443 ASSERT(sizeof (ml_odunit_t) < DEV_BSIZE); 444 ASSERT(nb >= ldl_minlogsize); 445 446 bp = UFS_GETBLK(ufsvfsp, ufsvfsp->vfs_dev, bno, dbtob(LS_SECTORS)); 447 bzero(bp->b_un.b_addr, bp->b_bcount); 448 449 ud = (void *)bp->b_un.b_addr; 450 ud->od_version = LUFS_VERSION_LATEST; 451 ud->od_maxtransfer = MIN(ufsvfsp->vfs_iotransz, ldl_maxtransfer); 452 if (ud->od_maxtransfer < ldl_mintransfer) 453 ud->od_maxtransfer = ldl_mintransfer; 454 ud->od_devbsize = DEV_BSIZE; 455 456 ud->od_requestsize = flp->nbytes_actual; 457 ud->od_statesize = dbtob(LS_SECTORS); 458 ud->od_logsize = nb - ud->od_statesize; 459 460 ud->od_statebno = INT32_C(0); 461 462 uniqtime(&tv); 463 if (tv.tv_usec == last_loghead_ident) { 464 tv.tv_usec++; 465 } 466 last_loghead_ident = tv.tv_usec; 467 ud->od_head_ident = tv.tv_usec; 468 ud->od_tail_ident = ud->od_head_ident; 469 ud->od_chksum = ud->od_head_ident + ud->od_tail_ident; 470 471 ud->od_bol_lof = dbtob(ud->od_statebno) + ud->od_statesize; 472 ud->od_eol_lof = ud->od_bol_lof + ud->od_logsize; 473 ud->od_head_lof = ud->od_bol_lof; 474 ud->od_tail_lof = ud->od_bol_lof; 475 476 ASSERT(lufs_initialize_debug(ud)); 477 478 ud2 = (void *)(bp->b_un.b_addr + DEV_BSIZE); 479 bcopy(ud, ud2, sizeof (*ud)); 480 481 UFS_BWRITE2(ufsvfsp, bp); 482 if (bp->b_flags & B_ERROR) { 483 brelse(bp); 484 return (EIO); 485 } 486 brelse(bp); 487 488 return (0); 489 } 490 491 /* 492 * Free log space 493 * Assumes the file system is write locked and is not logging 494 */ 495 static int 496 lufs_free(struct ufsvfs *ufsvfsp) 497 { 498 int error = 0, i, j; 499 buf_t *bp = NULL; 500 extent_t *ep; 501 extent_block_t *ebp; 502 struct fs *fs = ufsvfsp->vfs_fs; 503 daddr_t fno; 504 int32_t logbno; 505 long nfno; 506 inode_t *ip = NULL; 507 char clean; 508 509 /* 510 * Nothing to free 511 */ 512 if (fs->fs_logbno == 0) 513 return (0); 514 515 /* 516 * Mark the file system as FSACTIVE and no log but honor the 517 * current value of fs_reclaim. The reclaim thread could have 518 * been active when lufs_disable() was called and if fs_reclaim 519 * is reset to zero here it could lead to lost inodes. 520 */ 521 ufsvfsp->vfs_ulockfs.ul_sbowner = curthread; 522 mutex_enter(&ufsvfsp->vfs_lock); 523 clean = fs->fs_clean; 524 logbno = fs->fs_logbno; 525 fs->fs_clean = FSACTIVE; 526 fs->fs_logbno = INT32_C(0); 527 ufs_sbwrite(ufsvfsp); 528 mutex_exit(&ufsvfsp->vfs_lock); 529 ufsvfsp->vfs_ulockfs.ul_sbowner = (kthread_id_t)-1; 530 if (ufsvfsp->vfs_bufp->b_flags & B_ERROR) { 531 error = EIO; 532 fs->fs_clean = clean; 533 fs->fs_logbno = logbno; 534 goto errout; 535 } 536 537 /* 538 * fetch the allocation block 539 * superblock -> one block of extents -> log data 540 */ 541 bp = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, logbtodb(fs, logbno), 542 fs->fs_bsize); 543 if (bp->b_flags & B_ERROR) { 544 error = EIO; 545 goto errout; 546 } 547 548 /* 549 * Free up the allocated space (dummy inode needed for free()) 550 */ 551 ip = ufs_alloc_inode(ufsvfsp, UFSROOTINO); 552 ebp = (void *)bp->b_un.b_addr; 553 for (i = 0, ep = &ebp->extents[0]; i < ebp->nextents; ++i, ++ep) { 554 fno = logbtofrag(fs, ep->pbno); 555 nfno = dbtofsb(fs, ep->nbno); 556 for (j = 0; j < nfno; j += fs->fs_frag, fno += fs->fs_frag) 557 free(ip, fno, fs->fs_bsize, 0); 558 } 559 free(ip, logbtofrag(fs, logbno), fs->fs_bsize, 0); 560 brelse(bp); 561 bp = NULL; 562 563 /* 564 * Push the metadata dirtied during the allocations 565 */ 566 ufsvfsp->vfs_ulockfs.ul_sbowner = curthread; 567 sbupdate(ufsvfsp->vfs_vfs); 568 ufsvfsp->vfs_ulockfs.ul_sbowner = (kthread_id_t)-1; 569 bflush(ufsvfsp->vfs_dev); 570 error = bfinval(ufsvfsp->vfs_dev, 0); 571 if (error) 572 goto errout; 573 574 /* 575 * Free the dummy inode 576 */ 577 ufs_free_inode(ip); 578 579 return (0); 580 581 errout: 582 /* 583 * Free up all resources 584 */ 585 if (bp) 586 brelse(bp); 587 if (ip) 588 ufs_free_inode(ip); 589 return (error); 590 } 591 592 /* 593 * Allocate log space 594 * Assumes the file system is write locked and is not logging 595 */ 596 static int 597 lufs_alloc(struct ufsvfs *ufsvfsp, struct fiolog *flp, cred_t *cr) 598 { 599 int error = 0; 600 buf_t *bp = NULL; 601 extent_t *ep, *nep; 602 extent_block_t *ebp; 603 struct fs *fs = ufsvfsp->vfs_fs; 604 daddr_t fno; /* in frags */ 605 daddr_t bno; /* in disk blocks */ 606 int32_t logbno = INT32_C(0); /* will be fs_logbno */ 607 struct inode *ip = NULL; 608 size_t nb = flp->nbytes_actual; 609 size_t tb = 0; 610 611 /* 612 * Mark the file system as FSACTIVE 613 */ 614 ufsvfsp->vfs_ulockfs.ul_sbowner = curthread; 615 mutex_enter(&ufsvfsp->vfs_lock); 616 fs->fs_clean = FSACTIVE; 617 ufs_sbwrite(ufsvfsp); 618 mutex_exit(&ufsvfsp->vfs_lock); 619 ufsvfsp->vfs_ulockfs.ul_sbowner = (kthread_id_t)-1; 620 621 /* 622 * Allocate the allocation block (need dummy shadow inode; 623 * we use a shadow inode so the quota sub-system ignores 624 * the block allocations.) 625 * superblock -> one block of extents -> log data 626 */ 627 ip = ufs_alloc_inode(ufsvfsp, UFSROOTINO); 628 ip->i_mode = IFSHAD; /* make the dummy a shadow inode */ 629 rw_enter(&ip->i_contents, RW_WRITER); 630 fno = contigpref(ufsvfsp, nb + fs->fs_bsize); 631 error = alloc(ip, fno, fs->fs_bsize, &fno, cr); 632 if (error) 633 goto errout; 634 bno = fsbtodb(fs, fno); 635 636 bp = UFS_BREAD(ufsvfsp, ufsvfsp->vfs_dev, bno, fs->fs_bsize); 637 if (bp->b_flags & B_ERROR) { 638 error = EIO; 639 goto errout; 640 } 641 642 ebp = (void *)bp->b_un.b_addr; 643 ebp->type = LUFS_EXTENTS; 644 ebp->nextbno = UINT32_C(0); 645 ebp->nextents = UINT32_C(0); 646 ebp->chksum = INT32_C(0); 647 if (fs->fs_magic == FS_MAGIC) 648 logbno = bno; 649 else 650 logbno = dbtofsb(fs, bno); 651 652 /* 653 * Initialize the first extent 654 */ 655 ep = &ebp->extents[0]; 656 error = alloc(ip, fno + fs->fs_frag, fs->fs_bsize, &fno, cr); 657 if (error) 658 goto errout; 659 bno = fsbtodb(fs, fno); 660 661 ep->lbno = UINT32_C(0); 662 if (fs->fs_magic == FS_MAGIC) 663 ep->pbno = (uint32_t)bno; 664 else 665 ep->pbno = (uint32_t)fno; 666 ep->nbno = (uint32_t)fsbtodb(fs, fs->fs_frag); 667 ebp->nextents = UINT32_C(1); 668 tb = fs->fs_bsize; 669 nb -= fs->fs_bsize; 670 671 while (nb) { 672 error = alloc(ip, fno + fs->fs_frag, fs->fs_bsize, &fno, cr); 673 if (error) { 674 if (tb < ldl_minlogsize) 675 goto errout; 676 error = 0; 677 break; 678 } 679 bno = fsbtodb(fs, fno); 680 if ((daddr_t)((logbtodb(fs, ep->pbno) + ep->nbno) == bno)) 681 ep->nbno += (uint32_t)(fsbtodb(fs, fs->fs_frag)); 682 else { 683 nep = ep + 1; 684 if ((caddr_t)(nep + 1) > 685 (bp->b_un.b_addr + fs->fs_bsize)) { 686 free(ip, fno, fs->fs_bsize, 0); 687 break; 688 } 689 nep->lbno = ep->lbno + ep->nbno; 690 if (fs->fs_magic == FS_MAGIC) 691 nep->pbno = (uint32_t)bno; 692 else 693 nep->pbno = (uint32_t)fno; 694 nep->nbno = (uint32_t)(fsbtodb(fs, fs->fs_frag)); 695 ebp->nextents++; 696 ep = nep; 697 } 698 tb += fs->fs_bsize; 699 nb -= fs->fs_bsize; 700 } 701 ebp->nbytes = (uint32_t)tb; 702 setsum(&ebp->chksum, (int32_t *)bp->b_un.b_addr, fs->fs_bsize); 703 UFS_BWRITE2(ufsvfsp, bp); 704 if (bp->b_flags & B_ERROR) { 705 error = EIO; 706 goto errout; 707 } 708 /* 709 * Initialize the first two sectors of the log 710 */ 711 error = lufs_initialize(ufsvfsp, logbtodb(fs, ebp->extents[0].pbno), 712 tb, flp); 713 if (error) 714 goto errout; 715 716 /* 717 * We are done initializing the allocation block and the log 718 */ 719 brelse(bp); 720 bp = NULL; 721 722 /* 723 * Update the superblock and push the dirty metadata 724 */ 725 ufsvfsp->vfs_ulockfs.ul_sbowner = curthread; 726 sbupdate(ufsvfsp->vfs_vfs); 727 ufsvfsp->vfs_ulockfs.ul_sbowner = (kthread_id_t)-1; 728 bflush(ufsvfsp->vfs_dev); 729 error = bfinval(ufsvfsp->vfs_dev, 1); 730 if (error) 731 goto errout; 732 if (ufsvfsp->vfs_bufp->b_flags & B_ERROR) { 733 error = EIO; 734 goto errout; 735 } 736 737 /* 738 * Everything is safely on disk; update log space pointer in sb 739 */ 740 ufsvfsp->vfs_ulockfs.ul_sbowner = curthread; 741 mutex_enter(&ufsvfsp->vfs_lock); 742 fs->fs_logbno = (uint32_t)logbno; 743 ufs_sbwrite(ufsvfsp); 744 mutex_exit(&ufsvfsp->vfs_lock); 745 ufsvfsp->vfs_ulockfs.ul_sbowner = (kthread_id_t)-1; 746 747 /* 748 * Free the dummy inode 749 */ 750 rw_exit(&ip->i_contents); 751 ufs_free_inode(ip); 752 753 /* inform user of real log size */ 754 flp->nbytes_actual = tb; 755 return (0); 756 757 errout: 758 /* 759 * Free all resources 760 */ 761 if (bp) 762 brelse(bp); 763 if (logbno) { 764 fs->fs_logbno = logbno; 765 (void) lufs_free(ufsvfsp); 766 } 767 if (ip) { 768 rw_exit(&ip->i_contents); 769 ufs_free_inode(ip); 770 } 771 return (error); 772 } 773 774 /* 775 * Disable logging 776 */ 777 int 778 lufs_disable(vnode_t *vp, struct fiolog *flp) 779 { 780 int error = 0; 781 inode_t *ip = VTOI(vp); 782 ufsvfs_t *ufsvfsp = ip->i_ufsvfs; 783 struct fs *fs = ufsvfsp->vfs_fs; 784 struct lockfs lf; 785 struct ulockfs *ulp; 786 787 flp->error = FIOLOG_ENONE; 788 789 /* 790 * Logging is already disabled; done 791 */ 792 if (fs->fs_logbno == 0 || ufsvfsp->vfs_log == NULL) 793 return (0); 794 795 /* 796 * Readonly file system 797 */ 798 if (fs->fs_ronly) { 799 flp->error = FIOLOG_EROFS; 800 return (0); 801 } 802 803 /* 804 * File system must be write locked to disable logging 805 */ 806 error = ufs_fiolfss(vp, &lf); 807 if (error) { 808 return (error); 809 } 810 if (!LOCKFS_IS_ULOCK(&lf)) { 811 flp->error = FIOLOG_EULOCK; 812 return (0); 813 } 814 lf.lf_lock = LOCKFS_WLOCK; 815 lf.lf_flags = 0; 816 lf.lf_comment = NULL; 817 error = ufs_fiolfs(vp, &lf, 1); 818 if (error) { 819 flp->error = FIOLOG_EWLOCK; 820 return (0); 821 } 822 823 if (ufsvfsp->vfs_log == NULL || fs->fs_logbno == 0) 824 goto errout; 825 826 /* 827 * WE ARE COMMITTED TO DISABLING LOGGING PAST THIS POINT 828 */ 829 830 /* 831 * Disable logging: 832 * Suspend the reclaim thread and force the delete thread to exit. 833 * When a nologging mount has completed there may still be 834 * work for reclaim to do so just suspend this thread until 835 * it's [deadlock-] safe for it to continue. The delete 836 * thread won't be needed as ufs_iinactive() calls 837 * ufs_delete() when logging is disabled. 838 * Freeze and drain reader ops. 839 * Commit any outstanding reader transactions (ufs_flush). 840 * Set the ``unmounted'' bit in the ufstrans struct. 841 * If debug, remove metadata from matamap. 842 * Disable matamap processing. 843 * NULL the trans ops table. 844 * Free all of the incore structs related to logging. 845 * Allow reader ops. 846 */ 847 ufs_thread_suspend(&ufsvfsp->vfs_reclaim); 848 ufs_thread_exit(&ufsvfsp->vfs_delete); 849 850 vfs_lock_wait(ufsvfsp->vfs_vfs); 851 ulp = &ufsvfsp->vfs_ulockfs; 852 mutex_enter(&ulp->ul_lock); 853 atomic_add_long(&ufs_quiesce_pend, 1); 854 (void) ufs_quiesce(ulp); 855 856 (void) ufs_flush(ufsvfsp->vfs_vfs); 857 858 TRANS_MATA_UMOUNT(ufsvfsp); 859 ufsvfsp->vfs_domatamap = 0; 860 861 /* 862 * Free all of the incore structs 863 * Aquire the ufs_scan_lock before de-linking the mtm data 864 * structure so that we keep ufs_sync() and ufs_update() away 865 * when they execute the ufs_scan_inodes() run while we're in 866 * progress of enabling/disabling logging. 867 */ 868 mutex_enter(&ufs_scan_lock); 869 (void) lufs_unsnarf(ufsvfsp); 870 mutex_exit(&ufs_scan_lock); 871 872 atomic_add_long(&ufs_quiesce_pend, -1); 873 mutex_exit(&ulp->ul_lock); 874 vfs_setmntopt(ufsvfsp->vfs_vfs, MNTOPT_NOLOGGING, NULL, 0); 875 vfs_unlock(ufsvfsp->vfs_vfs); 876 877 fs->fs_rolled = FS_ALL_ROLLED; 878 ufsvfsp->vfs_nolog_si = 0; 879 880 /* 881 * Free the log space and mark the superblock as FSACTIVE 882 */ 883 (void) lufs_free(ufsvfsp); 884 885 /* 886 * Allow the reclaim thread to continue. 887 */ 888 ufs_thread_continue(&ufsvfsp->vfs_reclaim); 889 890 /* 891 * Unlock the file system 892 */ 893 lf.lf_lock = LOCKFS_ULOCK; 894 lf.lf_flags = 0; 895 error = ufs_fiolfs(vp, &lf, 1); 896 if (error) 897 flp->error = FIOLOG_ENOULOCK; 898 899 return (0); 900 901 errout: 902 lf.lf_lock = LOCKFS_ULOCK; 903 lf.lf_flags = 0; 904 (void) ufs_fiolfs(vp, &lf, 1); 905 return (error); 906 } 907 908 /* 909 * Enable logging 910 */ 911 int 912 lufs_enable(struct vnode *vp, struct fiolog *flp, cred_t *cr) 913 { 914 int error; 915 int reclaim; 916 inode_t *ip = VTOI(vp); 917 ufsvfs_t *ufsvfsp = ip->i_ufsvfs; 918 struct fs *fs; 919 ml_unit_t *ul; 920 struct lockfs lf; 921 struct ulockfs *ulp; 922 vfs_t *vfsp = ufsvfsp->vfs_vfs; 923 uint64_t tmp_nbytes_actual; 924 925 /* 926 * Check if logging is already enabled 927 */ 928 if (ufsvfsp->vfs_log) { 929 flp->error = FIOLOG_ETRANS; 930 /* for root ensure logging option is set */ 931 vfs_setmntopt(vfsp, MNTOPT_LOGGING, NULL, 0); 932 return (0); 933 } 934 fs = ufsvfsp->vfs_fs; 935 936 /* 937 * Come back here to recheck if we had to disable the log. 938 */ 939 recheck: 940 error = 0; 941 reclaim = 0; 942 flp->error = FIOLOG_ENONE; 943 944 /* 945 * Adjust requested log size 946 */ 947 flp->nbytes_actual = flp->nbytes_requested; 948 if (flp->nbytes_actual == 0) { 949 tmp_nbytes_actual = 950 (((uint64_t)fs->fs_size) / ldl_divisor) << fs->fs_fshift; 951 flp->nbytes_actual = (uint_t)MIN(tmp_nbytes_actual, INT_MAX); 952 } 953 flp->nbytes_actual = MAX(flp->nbytes_actual, ldl_minlogsize); 954 flp->nbytes_actual = MIN(flp->nbytes_actual, ldl_maxlogsize); 955 flp->nbytes_actual = blkroundup(fs, flp->nbytes_actual); 956 957 /* 958 * logging is enabled and the log is the right size; done 959 */ 960 ul = ufsvfsp->vfs_log; 961 if (ul && fs->fs_logbno && (flp->nbytes_actual == ul->un_requestsize)) 962 return (0); 963 964 /* 965 * Readonly file system 966 */ 967 if (fs->fs_ronly) { 968 flp->error = FIOLOG_EROFS; 969 return (0); 970 } 971 972 /* 973 * File system must be write locked to enable logging 974 */ 975 error = ufs_fiolfss(vp, &lf); 976 if (error) { 977 return (error); 978 } 979 if (!LOCKFS_IS_ULOCK(&lf)) { 980 flp->error = FIOLOG_EULOCK; 981 return (0); 982 } 983 lf.lf_lock = LOCKFS_WLOCK; 984 lf.lf_flags = 0; 985 lf.lf_comment = NULL; 986 error = ufs_fiolfs(vp, &lf, 1); 987 if (error) { 988 flp->error = FIOLOG_EWLOCK; 989 return (0); 990 } 991 992 /* 993 * Grab appropriate locks to synchronize with the rest 994 * of the system 995 */ 996 vfs_lock_wait(vfsp); 997 ulp = &ufsvfsp->vfs_ulockfs; 998 mutex_enter(&ulp->ul_lock); 999 1000 /* 1001 * File system must be fairly consistent to enable logging 1002 */ 1003 if (fs->fs_clean != FSLOG && 1004 fs->fs_clean != FSACTIVE && 1005 fs->fs_clean != FSSTABLE && 1006 fs->fs_clean != FSCLEAN) { 1007 flp->error = FIOLOG_ECLEAN; 1008 goto unlockout; 1009 } 1010 1011 /* 1012 * A write-locked file system is only active if there are 1013 * open deleted files; so remember to set FS_RECLAIM later. 1014 */ 1015 if (fs->fs_clean == FSACTIVE) 1016 reclaim = FS_RECLAIM; 1017 1018 /* 1019 * Logging is already enabled; must be changing the log's size 1020 */ 1021 if (fs->fs_logbno && ufsvfsp->vfs_log) { 1022 /* 1023 * Before we can disable logging, we must give up our 1024 * lock. As a consequence of unlocking and disabling the 1025 * log, the fs structure may change. Because of this, when 1026 * disabling is complete, we will go back to recheck to 1027 * repeat all of the checks that we performed to get to 1028 * this point. Disabling sets fs->fs_logbno to 0, so this 1029 * will not put us into an infinite loop. 1030 */ 1031 mutex_exit(&ulp->ul_lock); 1032 vfs_unlock(vfsp); 1033 1034 lf.lf_lock = LOCKFS_ULOCK; 1035 lf.lf_flags = 0; 1036 error = ufs_fiolfs(vp, &lf, 1); 1037 if (error) { 1038 flp->error = FIOLOG_ENOULOCK; 1039 return (0); 1040 } 1041 error = lufs_disable(vp, flp); 1042 if (error || (flp->error != FIOLOG_ENONE)) 1043 return (0); 1044 goto recheck; 1045 } 1046 1047 error = lufs_alloc(ufsvfsp, flp, cr); 1048 if (error) 1049 goto errout; 1050 1051 /* 1052 * Create all of the incore structs 1053 */ 1054 error = lufs_snarf(ufsvfsp, fs, 0); 1055 if (error) 1056 goto errout; 1057 1058 /* 1059 * DON'T ``GOTO ERROUT'' PAST THIS POINT 1060 */ 1061 1062 /* 1063 * Pretend we were just mounted with logging enabled 1064 * Get the ops vector 1065 * If debug, record metadata locations with log subsystem 1066 * Start the delete thread 1067 * Start the reclaim thread, if necessary 1068 */ 1069 vfs_setmntopt(vfsp, MNTOPT_LOGGING, NULL, 0); 1070 1071 TRANS_DOMATAMAP(ufsvfsp); 1072 TRANS_MATA_MOUNT(ufsvfsp); 1073 TRANS_MATA_SI(ufsvfsp, fs); 1074 ufs_thread_start(&ufsvfsp->vfs_delete, ufs_thread_delete, vfsp); 1075 if (fs->fs_reclaim & (FS_RECLAIM|FS_RECLAIMING)) { 1076 fs->fs_reclaim &= ~FS_RECLAIM; 1077 fs->fs_reclaim |= FS_RECLAIMING; 1078 ufs_thread_start(&ufsvfsp->vfs_reclaim, 1079 ufs_thread_reclaim, vfsp); 1080 } else 1081 fs->fs_reclaim |= reclaim; 1082 1083 mutex_exit(&ulp->ul_lock); 1084 vfs_unlock(vfsp); 1085 1086 /* 1087 * Unlock the file system 1088 */ 1089 lf.lf_lock = LOCKFS_ULOCK; 1090 lf.lf_flags = 0; 1091 error = ufs_fiolfs(vp, &lf, 1); 1092 if (error) { 1093 flp->error = FIOLOG_ENOULOCK; 1094 return (0); 1095 } 1096 1097 /* 1098 * There's nothing in the log yet (we've just allocated it) 1099 * so directly write out the super block. 1100 * Note, we have to force this sb out to disk 1101 * (not just to the log) so that if we crash we know we are logging 1102 */ 1103 mutex_enter(&ufsvfsp->vfs_lock); 1104 fs->fs_clean = FSLOG; 1105 fs->fs_rolled = FS_NEED_ROLL; /* Mark the fs as unrolled */ 1106 UFS_BWRITE2(NULL, ufsvfsp->vfs_bufp); 1107 mutex_exit(&ufsvfsp->vfs_lock); 1108 1109 return (0); 1110 1111 errout: 1112 /* 1113 * Aquire the ufs_scan_lock before de-linking the mtm data 1114 * structure so that we keep ufs_sync() and ufs_update() away 1115 * when they execute the ufs_scan_inodes() run while we're in 1116 * progress of enabling/disabling logging. 1117 */ 1118 mutex_enter(&ufs_scan_lock); 1119 (void) lufs_unsnarf(ufsvfsp); 1120 mutex_exit(&ufs_scan_lock); 1121 1122 (void) lufs_free(ufsvfsp); 1123 unlockout: 1124 mutex_exit(&ulp->ul_lock); 1125 vfs_unlock(vfsp); 1126 1127 lf.lf_lock = LOCKFS_ULOCK; 1128 lf.lf_flags = 0; 1129 (void) ufs_fiolfs(vp, &lf, 1); 1130 return (error); 1131 } 1132 1133 void 1134 lufs_read_strategy(ml_unit_t *ul, buf_t *bp) 1135 { 1136 mt_map_t *logmap = ul->un_logmap; 1137 offset_t mof = ldbtob(bp->b_blkno); 1138 off_t nb = bp->b_bcount; 1139 mapentry_t *age; 1140 char *va; 1141 int (*saviodone)(); 1142 int entire_range; 1143 1144 /* 1145 * get a linked list of overlapping deltas 1146 * returns with &mtm->mtm_rwlock held 1147 */ 1148 entire_range = logmap_list_get(logmap, mof, nb, &age); 1149 1150 /* 1151 * no overlapping deltas were found; read master 1152 */ 1153 if (age == NULL) { 1154 rw_exit(&logmap->mtm_rwlock); 1155 if (ul->un_flags & LDL_ERROR) { 1156 bp->b_flags |= B_ERROR; 1157 bp->b_error = EIO; 1158 biodone(bp); 1159 } else { 1160 ul->un_ufsvfs->vfs_iotstamp = lbolt; 1161 logstats.ls_lreads.value.ui64++; 1162 (void) bdev_strategy(bp); 1163 lwp_stat_update(LWP_STAT_INBLK, 1); 1164 } 1165 return; 1166 } 1167 1168 va = bp_mapin_common(bp, VM_SLEEP); 1169 /* 1170 * if necessary, sync read the data from master 1171 * errors are returned in bp 1172 */ 1173 if (!entire_range) { 1174 saviodone = bp->b_iodone; 1175 bp->b_iodone = trans_not_done; 1176 logstats.ls_mreads.value.ui64++; 1177 (void) bdev_strategy(bp); 1178 lwp_stat_update(LWP_STAT_INBLK, 1); 1179 if (trans_not_wait(bp)) 1180 ldl_seterror(ul, "Error reading master"); 1181 bp->b_iodone = saviodone; 1182 } 1183 1184 /* 1185 * sync read the data from the log 1186 * errors are returned inline 1187 */ 1188 if (ldl_read(ul, va, mof, nb, age)) { 1189 bp->b_flags |= B_ERROR; 1190 bp->b_error = EIO; 1191 } 1192 1193 /* 1194 * unlist the deltas 1195 */ 1196 logmap_list_put(logmap, age); 1197 1198 /* 1199 * all done 1200 */ 1201 if (ul->un_flags & LDL_ERROR) { 1202 bp->b_flags |= B_ERROR; 1203 bp->b_error = EIO; 1204 } 1205 biodone(bp); 1206 } 1207 1208 void 1209 lufs_write_strategy(ml_unit_t *ul, buf_t *bp) 1210 { 1211 offset_t mof = ldbtob(bp->b_blkno); 1212 off_t nb = bp->b_bcount; 1213 char *va; 1214 mapentry_t *me; 1215 1216 ASSERT((nb & DEV_BMASK) == 0); 1217 ul->un_logmap->mtm_ref = 1; 1218 1219 /* 1220 * if there are deltas, move into log 1221 */ 1222 me = deltamap_remove(ul->un_deltamap, mof, nb); 1223 if (me) { 1224 1225 va = bp_mapin_common(bp, VM_SLEEP); 1226 1227 ASSERT(((ul->un_debug & MT_WRITE_CHECK) == 0) || 1228 (ul->un_matamap == NULL)|| 1229 matamap_within(ul->un_matamap, mof, nb)); 1230 1231 /* 1232 * move to logmap 1233 */ 1234 if (ufs_crb_enable) { 1235 logmap_add_buf(ul, va, mof, me, 1236 bp->b_un.b_addr, nb); 1237 } else { 1238 logmap_add(ul, va, mof, me); 1239 } 1240 1241 if (ul->un_flags & LDL_ERROR) { 1242 bp->b_flags |= B_ERROR; 1243 bp->b_error = EIO; 1244 } 1245 biodone(bp); 1246 return; 1247 } 1248 if (ul->un_flags & LDL_ERROR) { 1249 bp->b_flags |= B_ERROR; 1250 bp->b_error = EIO; 1251 biodone(bp); 1252 return; 1253 } 1254 1255 /* 1256 * Check that we are not updating metadata, or if so then via B_PHYS. 1257 */ 1258 ASSERT((ul->un_matamap == NULL) || 1259 !(matamap_overlap(ul->un_matamap, mof, nb) && 1260 ((bp->b_flags & B_PHYS) == 0))); 1261 1262 ul->un_ufsvfs->vfs_iotstamp = lbolt; 1263 logstats.ls_lwrites.value.ui64++; 1264 1265 /* If snapshots are enabled, write through the snapshot driver */ 1266 if (ul->un_ufsvfs->vfs_snapshot) 1267 fssnap_strategy(&ul->un_ufsvfs->vfs_snapshot, bp); 1268 else 1269 (void) bdev_strategy(bp); 1270 1271 lwp_stat_update(LWP_STAT_OUBLK, 1); 1272 } 1273 1274 void 1275 lufs_strategy(ml_unit_t *ul, buf_t *bp) 1276 { 1277 if (bp->b_flags & B_READ) 1278 lufs_read_strategy(ul, bp); 1279 else 1280 lufs_write_strategy(ul, bp); 1281 } 1282 1283 /* ARGSUSED */ 1284 static int 1285 delta_stats_update(kstat_t *ksp, int rw) 1286 { 1287 if (rw == KSTAT_WRITE) { 1288 delta_stats[DT_SB] = dkstats.ds_superblock_deltas.value.ui64; 1289 delta_stats[DT_CG] = dkstats.ds_bitmap_deltas.value.ui64; 1290 delta_stats[DT_SI] = dkstats.ds_suminfo_deltas.value.ui64; 1291 delta_stats[DT_AB] = dkstats.ds_allocblk_deltas.value.ui64; 1292 delta_stats[DT_ABZERO] = dkstats.ds_ab0_deltas.value.ui64; 1293 delta_stats[DT_DIR] = dkstats.ds_dir_deltas.value.ui64; 1294 delta_stats[DT_INODE] = dkstats.ds_inode_deltas.value.ui64; 1295 delta_stats[DT_FBI] = dkstats.ds_fbiwrite_deltas.value.ui64; 1296 delta_stats[DT_QR] = dkstats.ds_quota_deltas.value.ui64; 1297 delta_stats[DT_SHAD] = dkstats.ds_shadow_deltas.value.ui64; 1298 1299 roll_stats[DT_SB] = dkstats.ds_superblock_rolled.value.ui64; 1300 roll_stats[DT_CG] = dkstats.ds_bitmap_rolled.value.ui64; 1301 roll_stats[DT_SI] = dkstats.ds_suminfo_rolled.value.ui64; 1302 roll_stats[DT_AB] = dkstats.ds_allocblk_rolled.value.ui64; 1303 roll_stats[DT_ABZERO] = dkstats.ds_ab0_rolled.value.ui64; 1304 roll_stats[DT_DIR] = dkstats.ds_dir_rolled.value.ui64; 1305 roll_stats[DT_INODE] = dkstats.ds_inode_rolled.value.ui64; 1306 roll_stats[DT_FBI] = dkstats.ds_fbiwrite_rolled.value.ui64; 1307 roll_stats[DT_QR] = dkstats.ds_quota_rolled.value.ui64; 1308 roll_stats[DT_SHAD] = dkstats.ds_shadow_rolled.value.ui64; 1309 } else { 1310 dkstats.ds_superblock_deltas.value.ui64 = delta_stats[DT_SB]; 1311 dkstats.ds_bitmap_deltas.value.ui64 = delta_stats[DT_CG]; 1312 dkstats.ds_suminfo_deltas.value.ui64 = delta_stats[DT_SI]; 1313 dkstats.ds_allocblk_deltas.value.ui64 = delta_stats[DT_AB]; 1314 dkstats.ds_ab0_deltas.value.ui64 = delta_stats[DT_ABZERO]; 1315 dkstats.ds_dir_deltas.value.ui64 = delta_stats[DT_DIR]; 1316 dkstats.ds_inode_deltas.value.ui64 = delta_stats[DT_INODE]; 1317 dkstats.ds_fbiwrite_deltas.value.ui64 = delta_stats[DT_FBI]; 1318 dkstats.ds_quota_deltas.value.ui64 = delta_stats[DT_QR]; 1319 dkstats.ds_shadow_deltas.value.ui64 = delta_stats[DT_SHAD]; 1320 1321 dkstats.ds_superblock_rolled.value.ui64 = roll_stats[DT_SB]; 1322 dkstats.ds_bitmap_rolled.value.ui64 = roll_stats[DT_CG]; 1323 dkstats.ds_suminfo_rolled.value.ui64 = roll_stats[DT_SI]; 1324 dkstats.ds_allocblk_rolled.value.ui64 = roll_stats[DT_AB]; 1325 dkstats.ds_ab0_rolled.value.ui64 = roll_stats[DT_ABZERO]; 1326 dkstats.ds_dir_rolled.value.ui64 = roll_stats[DT_DIR]; 1327 dkstats.ds_inode_rolled.value.ui64 = roll_stats[DT_INODE]; 1328 dkstats.ds_fbiwrite_rolled.value.ui64 = roll_stats[DT_FBI]; 1329 dkstats.ds_quota_rolled.value.ui64 = roll_stats[DT_QR]; 1330 dkstats.ds_shadow_rolled.value.ui64 = roll_stats[DT_SHAD]; 1331 } 1332 return (0); 1333 } 1334 1335 extern size_t ufs_crb_limit; 1336 extern int ufs_max_crb_divisor; 1337 1338 void 1339 lufs_init(void) 1340 { 1341 kstat_t *ksp; 1342 1343 /* Create kmem caches */ 1344 lufs_sv = kmem_cache_create("lufs_save", sizeof (lufs_save_t), 0, 1345 NULL, NULL, NULL, NULL, NULL, 0); 1346 lufs_bp = kmem_cache_create("lufs_bufs", sizeof (lufs_buf_t), 0, 1347 NULL, NULL, NULL, NULL, NULL, 0); 1348 1349 mutex_init(&log_mutex, NULL, MUTEX_DEFAULT, NULL); 1350 1351 _init_top(); 1352 1353 if (&bio_lufs_strategy != NULL) 1354 bio_lufs_strategy = (void (*) (void *, buf_t *)) lufs_strategy; 1355 1356 /* 1357 * Initialise general logging and delta kstats 1358 */ 1359 ksp = kstat_create("ufs_log", 0, "logstats", "ufs", KSTAT_TYPE_NAMED, 1360 sizeof (logstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 1361 if (ksp) { 1362 ksp->ks_data = (void *) &logstats; 1363 kstat_install(ksp); 1364 } 1365 1366 ksp = kstat_create("ufs_log", 0, "deltastats", "ufs", KSTAT_TYPE_NAMED, 1367 sizeof (dkstats) / sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 1368 if (ksp) { 1369 ksp->ks_data = (void *) &dkstats; 1370 ksp->ks_update = delta_stats_update; 1371 kstat_install(ksp); 1372 } 1373 1374 /* 1375 * Set up the maximum amount of kmem that the crbs (system wide) 1376 * can use. 1377 */ 1378 ufs_crb_limit = kmem_maxavail() / ufs_max_crb_divisor; 1379 } 1380