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