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