4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/systm.h>
27 #include <sys/types.h>
28 #include <sys/vnode.h>
30 #include <sys/errno.h>
31 #include <sys/fssnap_if.h>
32 #include <sys/fs/ufs_inode.h>
33 #include <sys/fs/ufs_filio.h>
34 #include <sys/sysmacros.h>
35 #include <sys/modctl.h>
36 #include <sys/fs/ufs_log.h>
37 #include <sys/fs/ufs_bio.h>
38 #include <sys/fs/ufs_fsdir.h>
39 #include <sys/debug.h>
40 #include <sys/atomic.h>
42 #include <sys/inttypes.h>
44 #include <sys/mntent.h>
46 #include <sys/param.h>
47 #include <sys/kstat.h>
48 #include <sys/cmn_err.h>
51 #define LUFS_GENID_PRIME UINT64_C(4294967291)
52 #define LUFS_GENID_BASE UINT64_C(311)
53 #define LUFS_NEXT_ID(id) ((uint32_t)(((id) * LUFS_GENID_BASE) % \
56 extern kmutex_t ufs_scan_lock
;
58 static kmutex_t log_mutex
; /* general purpose log layer lock */
59 kmutex_t ml_scan
; /* Scan thread syncronization */
60 kcondvar_t ml_scan_cv
; /* Scan thread syncronization */
62 struct kmem_cache
*lufs_sv
;
63 struct kmem_cache
*lufs_bp
;
66 uint_t ldl_maxlogsize
= LDL_MAXLOGSIZE
;
67 uint_t ldl_minlogsize
= LDL_MINLOGSIZE
;
68 uint_t ldl_softlogcap
= LDL_SOFTLOGCAP
;
69 uint32_t ldl_divisor
= LDL_DIVISOR
;
70 uint32_t ldl_mintransfer
= LDL_MINTRANSFER
;
71 uint32_t ldl_maxtransfer
= LDL_MAXTRANSFER
;
72 uint32_t ldl_minbufsize
= LDL_MINBUFSIZE
;
73 uint32_t ldl_cgsizereq
= 0;
75 /* Generation of header ids */
76 static kmutex_t genid_mutex
;
77 static uint32_t last_loghead_ident
= UINT32_C(0);
80 * Logging delta and roll statistics
83 kstat_named_t ds_superblock_deltas
;
84 kstat_named_t ds_bitmap_deltas
;
85 kstat_named_t ds_suminfo_deltas
;
86 kstat_named_t ds_allocblk_deltas
;
87 kstat_named_t ds_ab0_deltas
;
88 kstat_named_t ds_dir_deltas
;
89 kstat_named_t ds_inode_deltas
;
90 kstat_named_t ds_fbiwrite_deltas
;
91 kstat_named_t ds_quota_deltas
;
92 kstat_named_t ds_shadow_deltas
;
94 kstat_named_t ds_superblock_rolled
;
95 kstat_named_t ds_bitmap_rolled
;
96 kstat_named_t ds_suminfo_rolled
;
97 kstat_named_t ds_allocblk_rolled
;
98 kstat_named_t ds_ab0_rolled
;
99 kstat_named_t ds_dir_rolled
;
100 kstat_named_t ds_inode_rolled
;
101 kstat_named_t ds_fbiwrite_rolled
;
102 kstat_named_t ds_quota_rolled
;
103 kstat_named_t ds_shadow_rolled
;
105 { "superblock_deltas", KSTAT_DATA_UINT64
},
106 { "bitmap_deltas", KSTAT_DATA_UINT64
},
107 { "suminfo_deltas", KSTAT_DATA_UINT64
},
108 { "allocblk_deltas", KSTAT_DATA_UINT64
},
109 { "ab0_deltas", KSTAT_DATA_UINT64
},
110 { "dir_deltas", KSTAT_DATA_UINT64
},
111 { "inode_deltas", KSTAT_DATA_UINT64
},
112 { "fbiwrite_deltas", KSTAT_DATA_UINT64
},
113 { "quota_deltas", KSTAT_DATA_UINT64
},
114 { "shadow_deltas", KSTAT_DATA_UINT64
},
116 { "superblock_rolled", KSTAT_DATA_UINT64
},
117 { "bitmap_rolled", KSTAT_DATA_UINT64
},
118 { "suminfo_rolled", KSTAT_DATA_UINT64
},
119 { "allocblk_rolled", KSTAT_DATA_UINT64
},
120 { "ab0_rolled", KSTAT_DATA_UINT64
},
121 { "dir_rolled", KSTAT_DATA_UINT64
},
122 { "inode_rolled", KSTAT_DATA_UINT64
},
123 { "fbiwrite_rolled", KSTAT_DATA_UINT64
},
124 { "quota_rolled", KSTAT_DATA_UINT64
},
125 { "shadow_rolled", KSTAT_DATA_UINT64
}
128 uint64_t delta_stats
[DT_MAX
];
129 uint64_t roll_stats
[DT_MAX
];
132 * General logging kstats
134 struct logstats logstats
= {
135 { "master_reads", KSTAT_DATA_UINT64
},
136 { "master_writes", KSTAT_DATA_UINT64
},
137 { "log_reads_inmem", KSTAT_DATA_UINT64
},
138 { "log_reads", KSTAT_DATA_UINT64
},
139 { "log_writes", KSTAT_DATA_UINT64
},
140 { "log_master_reads", KSTAT_DATA_UINT64
},
141 { "log_roll_reads", KSTAT_DATA_UINT64
},
142 { "log_roll_writes", KSTAT_DATA_UINT64
}
146 trans_not_done(struct buf
*cb
)
153 trans_wait_panic(struct buf
*cb
)
155 while ((cb
->b_flags
& B_DONE
) == 0)
160 trans_not_wait(struct buf
*cb
)
163 * In case of panic, busy wait for completion
166 trans_wait_panic(cb
);
170 return (geterror(cb
));
174 trans_wait(struct buf
*cb
)
177 * In case of panic, busy wait for completion and run md daemon queues
180 trans_wait_panic(cb
);
181 return (biowait(cb
));
185 setsum(int32_t *sp
, int32_t *lp
, int nb
)
190 nb
/= sizeof (int32_t);
197 checksum(int32_t *sp
, int32_t *lp
, int nb
)
210 lufs_unsnarf(ufsvfs_t
*ufsvfsp
)
215 ul
= ufsvfsp
->vfs_log
;
222 * Wait for a pending top_issue_sync which is
223 * dispatched (via taskq_dispatch()) but hasnt completed yet.
226 mutex_enter(&mtm
->mtm_lock
);
228 while (mtm
->mtm_taskq_sync_count
!= 0) {
229 cv_wait(&mtm
->mtm_cv
, &mtm
->mtm_lock
);
232 mutex_exit(&mtm
->mtm_lock
);
234 /* Roll committed transactions */
237 /* Kill the roll thread */
238 logmap_kill_roll(ul
);
240 /* release saved alloction info */
242 kmem_free(ul
->un_ebp
, ul
->un_nbeb
);
244 /* release circular bufs */
245 free_cirbuf(&ul
->un_rdbuf
);
246 free_cirbuf(&ul
->un_wrbuf
);
250 ul
->un_logmap
= map_put(ul
->un_logmap
);
252 ul
->un_deltamap
= map_put(ul
->un_deltamap
);
254 ul
->un_matamap
= map_put(ul
->un_matamap
);
256 mutex_destroy(&ul
->un_log_mutex
);
257 mutex_destroy(&ul
->un_state_mutex
);
259 /* release state buffer MUST BE LAST!! (contains our ondisk data) */
262 kmem_free(ul
, sizeof (*ul
));
264 ufsvfsp
->vfs_log
= NULL
;
268 lufs_snarf(ufsvfs_t
*ufsvfsp
, struct fs
*fs
, int ronly
)
273 ic_extent_block_t
*nebp
;
275 daddr_t bno
; /* in disk blocks */
278 /* LINTED: warning: logical expression always true: op "||" */
279 ASSERT(sizeof (ml_odunit_t
) < DEV_BSIZE
);
282 * Get the allocation table
283 * During a remount the superblock pointed to by the ufsvfsp
284 * is out of date. Hence the need for the ``new'' superblock
285 * pointer, fs, passed in as a parameter.
287 bp
= UFS_BREAD(ufsvfsp
, ufsvfsp
->vfs_dev
, logbtodb(fs
, fs
->fs_logbno
),
289 if (bp
->b_flags
& B_ERROR
) {
293 ebp
= (void *)bp
->b_un
.b_addr
;
294 if (!checksum(&ebp
->chksum
, (int32_t *)bp
->b_un
.b_addr
,
301 * It is possible to get log blocks with all zeros.
302 * We should also check for nextents to be zero in such case.
304 if (ebp
->type
!= LUFS_EXTENTS
|| ebp
->nextents
== 0) {
309 * Put allocation into memory. This requires conversion between
310 * on the ondisk format of the extent (type extent_t) and the
311 * in-core format of the extent (type ic_extent_t). The
312 * difference is the in-core form of the extent block stores
313 * the physical offset of the extent in disk blocks, which
314 * can require more than a 32-bit field.
316 nb
= (size_t)(sizeof (ic_extent_block_t
) +
317 ((ebp
->nextents
- 1) * sizeof (ic_extent_t
)));
318 nebp
= kmem_alloc(nb
, KM_SLEEP
);
319 nebp
->ic_nextents
= ebp
->nextents
;
320 nebp
->ic_nbytes
= ebp
->nbytes
;
321 nebp
->ic_nextbno
= ebp
->nextbno
;
322 for (i
= 0; i
< ebp
->nextents
; i
++) {
323 nebp
->ic_extents
[i
].ic_lbno
= ebp
->extents
[i
].lbno
;
324 nebp
->ic_extents
[i
].ic_nbno
= ebp
->extents
[i
].nbno
;
325 nebp
->ic_extents
[i
].ic_pbno
=
326 logbtodb(fs
, ebp
->extents
[i
].pbno
);
333 bno
= nebp
->ic_extents
[0].ic_pbno
;
334 bp
= UFS_BREAD(ufsvfsp
, ufsvfsp
->vfs_dev
, bno
, DEV_BSIZE
);
335 if (bp
->b_flags
& B_ERROR
) {
337 bp
= UFS_BREAD(ufsvfsp
, ufsvfsp
->vfs_dev
, bno
+ 1, DEV_BSIZE
);
338 if (bp
->b_flags
& B_ERROR
) {
346 * Put ondisk struct into an anonymous buffer
347 * This buffer will contain the memory for the ml_odunit struct
349 tbp
= ngeteblk(dbtob(LS_SECTORS
));
350 tbp
->b_edev
= bp
->b_edev
;
351 tbp
->b_dev
= bp
->b_dev
;
353 bcopy(bp
->b_un
.b_addr
, tbp
->b_un
.b_addr
, DEV_BSIZE
);
354 bcopy(bp
->b_un
.b_addr
, tbp
->b_un
.b_addr
+ DEV_BSIZE
, DEV_BSIZE
);
355 bp
->b_flags
|= (B_STALE
| B_AGE
);
360 * Verify the log state
362 * read/only mounts w/bad logs are allowed. umount will
363 * eventually roll the bad log until the first IO error.
364 * fsck will then repair the file system.
366 * read/write mounts with bad logs are not allowed.
369 ul
= (ml_unit_t
*)kmem_zalloc(sizeof (*ul
), KM_SLEEP
);
370 bcopy(bp
->b_un
.b_addr
, &ul
->un_ondisk
, sizeof (ml_odunit_t
));
371 if ((ul
->un_chksum
!= ul
->un_head_ident
+ ul
->un_tail_ident
) ||
372 (ul
->un_version
!= LUFS_VERSION_LATEST
) ||
373 (!ronly
&& ul
->un_badlog
)) {
374 kmem_free(ul
, sizeof (*ul
));
380 * Initialize the incore-only fields
383 ul
->un_flags
|= LDL_NOROLL
;
385 ul
->un_ufsvfs
= ufsvfsp
;
386 ul
->un_dev
= ufsvfsp
->vfs_dev
;
389 ul
->un_maxresv
= btodb(ul
->un_logsize
) * LDL_USABLE_BSIZE
;
390 ul
->un_deltamap
= map_get(ul
, deltamaptype
, DELTAMAP_NHASH
);
391 ul
->un_logmap
= map_get(ul
, logmaptype
, LOGMAP_NHASH
);
392 if (ul
->un_debug
& MT_MATAMAP
)
393 ul
->un_matamap
= map_get(ul
, matamaptype
, DELTAMAP_NHASH
);
394 mutex_init(&ul
->un_log_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
395 mutex_init(&ul
->un_state_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
398 * Aquire the ufs_scan_lock before linking the mtm data
399 * structure so that we keep ufs_sync() and ufs_update() away
400 * when they execute the ufs_scan_inodes() run while we're in
401 * progress of enabling/disabling logging.
403 mutex_enter(&ufs_scan_lock
);
404 ufsvfsp
->vfs_log
= ul
;
406 /* remember the state of the log before the log scan */
408 mutex_exit(&ufs_scan_lock
);
413 * If this is a read/only mount; ignore the error.
414 * At a later time umount/fsck will repair the fs.
417 if (ul
->un_flags
& LDL_ERROR
) {
420 * Aquire the ufs_scan_lock before de-linking
421 * the mtm data structure so that we keep ufs_sync()
422 * and ufs_update() away when they execute the
423 * ufs_scan_inodes() run while we're in progress of
424 * enabling/disabling logging.
426 mutex_enter(&ufs_scan_lock
);
427 lufs_unsnarf(ufsvfsp
);
428 mutex_exit(&ufs_scan_lock
);
431 ul
->un_flags
&= ~LDL_ERROR
;
434 logmap_start_roll(ul
);
439 lufs_hd_genid(const ml_unit_t
*up
)
443 mutex_enter(&genid_mutex
);
446 * The formula below implements an exponential, modular sequence.
448 * ID(N) = (SEED * (BASE^N)) % PRIME
450 * The numbers will be pseudo random. They depend on SEED, BASE, PRIME,
451 * but will sweep through almost all of the range 1....PRIME-1.
452 * Most importantly they will not repeat for PRIME-2 (4294967289)
453 * repetitions. If they would repeat that could possibly cause hangs,
454 * panics at mount/umount and failed mount operations.
456 id
= LUFS_NEXT_ID(last_loghead_ident
);
458 /* Checking if new identity used already */
459 if (up
!= NULL
&& up
->un_head_ident
== id
) {
460 DTRACE_PROBE1(head_ident_collision
, uint32_t, id
);
463 * The following preserves the algorithm for the fix for
464 * "panic: free: freeing free frag, dev:0x2000000018, blk:34605,
465 * cg:26, ino:148071,".
466 * If the header identities un_head_ident are equal to the
467 * present element in the sequence, the next element of the
468 * sequence is returned instead.
470 id
= LUFS_NEXT_ID(id
);
473 last_loghead_ident
= id
;
475 mutex_exit(&genid_mutex
);
481 lufs_genid_init(void)
486 mutex_init(&genid_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
488 /* Seed the algorithm */
494 seed
= (tv
.tv_nsec
<< 3);
497 last_loghead_ident
= (uint32_t)(seed
% LUFS_GENID_PRIME
);
498 } while (last_loghead_ident
== UINT32_C(0));
508 ml_odunit_t
*ud
, *ud2
;
511 /* LINTED: warning: logical expression always true: op "||" */
512 ASSERT(sizeof (ml_odunit_t
) < DEV_BSIZE
);
513 ASSERT(nb
>= ldl_minlogsize
);
515 bp
= UFS_GETBLK(ufsvfsp
, ufsvfsp
->vfs_dev
, bno
, dbtob(LS_SECTORS
));
516 bzero(bp
->b_un
.b_addr
, bp
->b_bcount
);
518 ud
= (void *)bp
->b_un
.b_addr
;
519 ud
->od_version
= LUFS_VERSION_LATEST
;
520 ud
->od_maxtransfer
= MIN(ufsvfsp
->vfs_iotransz
, ldl_maxtransfer
);
521 if (ud
->od_maxtransfer
< ldl_mintransfer
)
522 ud
->od_maxtransfer
= ldl_mintransfer
;
523 ud
->od_devbsize
= DEV_BSIZE
;
525 ud
->od_requestsize
= flp
->nbytes_actual
;
526 ud
->od_statesize
= dbtob(LS_SECTORS
);
527 ud
->od_logsize
= nb
- ud
->od_statesize
;
529 ud
->od_statebno
= INT32_C(0);
531 ud
->od_head_ident
= lufs_hd_genid(NULL
);
532 ud
->od_tail_ident
= ud
->od_head_ident
;
533 ud
->od_chksum
= ud
->od_head_ident
+ ud
->od_tail_ident
;
535 ud
->od_bol_lof
= dbtob(ud
->od_statebno
) + ud
->od_statesize
;
536 ud
->od_eol_lof
= ud
->od_bol_lof
+ ud
->od_logsize
;
537 ud
->od_head_lof
= ud
->od_bol_lof
;
538 ud
->od_tail_lof
= ud
->od_bol_lof
;
540 ASSERT(lufs_initialize_debug(ud
));
542 ud2
= (void *)(bp
->b_un
.b_addr
+ DEV_BSIZE
);
543 bcopy(ud
, ud2
, sizeof (*ud
));
545 UFS_BWRITE2(ufsvfsp
, bp
);
546 if (bp
->b_flags
& B_ERROR
) {
557 * Assumes the file system is write locked and is not logging
560 lufs_free(struct ufsvfs
*ufsvfsp
)
566 struct fs
*fs
= ufsvfsp
->vfs_fs
;
576 if (fs
->fs_logbno
== 0)
580 * Mark the file system as FSACTIVE and no log but honor the
581 * current value of fs_reclaim. The reclaim thread could have
582 * been active when lufs_disable() was called and if fs_reclaim
583 * is reset to zero here it could lead to lost inodes.
585 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= curthread
;
586 mutex_enter(&ufsvfsp
->vfs_lock
);
587 clean
= fs
->fs_clean
;
588 logbno
= fs
->fs_logbno
;
589 fs
->fs_clean
= FSACTIVE
;
590 fs
->fs_logbno
= INT32_C(0);
591 ufs_sbwrite(ufsvfsp
);
592 mutex_exit(&ufsvfsp
->vfs_lock
);
593 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= (kthread_id_t
)-1;
594 if (ufsvfsp
->vfs_bufp
->b_flags
& B_ERROR
) {
596 fs
->fs_clean
= clean
;
597 fs
->fs_logbno
= logbno
;
602 * fetch the allocation block
603 * superblock -> one block of extents -> log data
605 bp
= UFS_BREAD(ufsvfsp
, ufsvfsp
->vfs_dev
, logbtodb(fs
, logbno
),
607 if (bp
->b_flags
& B_ERROR
) {
613 * Free up the allocated space (dummy inode needed for free())
615 ip
= ufs_alloc_inode(ufsvfsp
, UFSROOTINO
);
616 ebp
= (void *)bp
->b_un
.b_addr
;
617 for (i
= 0, ep
= &ebp
->extents
[0]; i
< ebp
->nextents
; ++i
, ++ep
) {
618 fno
= logbtofrag(fs
, ep
->pbno
);
619 nfno
= dbtofsb(fs
, ep
->nbno
);
620 for (j
= 0; j
< nfno
; j
+= fs
->fs_frag
, fno
+= fs
->fs_frag
)
621 free(ip
, fno
, fs
->fs_bsize
, 0);
623 free(ip
, logbtofrag(fs
, logbno
), fs
->fs_bsize
, 0);
628 * Push the metadata dirtied during the allocations
630 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= curthread
;
631 sbupdate(ufsvfsp
->vfs_vfs
);
632 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= (kthread_id_t
)-1;
633 bflush(ufsvfsp
->vfs_dev
);
634 error
= bfinval(ufsvfsp
->vfs_dev
, 0);
639 * Free the dummy inode
647 * Free up all resources
658 * Assumes the file system is write locked and is not logging
661 lufs_alloc(struct ufsvfs
*ufsvfsp
, struct fiolog
*flp
, size_t minb
, cred_t
*cr
)
667 struct fs
*fs
= ufsvfsp
->vfs_fs
;
668 daddr_t fno
; /* in frags */
669 daddr_t bno
; /* in disk blocks */
670 int32_t logbno
= INT32_C(0); /* will be fs_logbno */
671 struct inode
*ip
= NULL
;
672 size_t nb
= flp
->nbytes_actual
;
676 * Mark the file system as FSACTIVE
678 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= curthread
;
679 mutex_enter(&ufsvfsp
->vfs_lock
);
680 fs
->fs_clean
= FSACTIVE
;
681 ufs_sbwrite(ufsvfsp
);
682 mutex_exit(&ufsvfsp
->vfs_lock
);
683 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= (kthread_id_t
)-1;
686 * Allocate the allocation block (need dummy shadow inode;
687 * we use a shadow inode so the quota sub-system ignores
688 * the block allocations.)
689 * superblock -> one block of extents -> log data
691 ip
= ufs_alloc_inode(ufsvfsp
, UFSROOTINO
);
692 ip
->i_mode
= IFSHAD
; /* make the dummy a shadow inode */
693 rw_enter(&ip
->i_contents
, RW_WRITER
);
694 fno
= contigpref(ufsvfsp
, nb
+ fs
->fs_bsize
, minb
);
695 error
= alloc(ip
, fno
, fs
->fs_bsize
, &fno
, cr
);
698 bno
= fsbtodb(fs
, fno
);
700 bp
= UFS_BREAD(ufsvfsp
, ufsvfsp
->vfs_dev
, bno
, fs
->fs_bsize
);
701 if (bp
->b_flags
& B_ERROR
) {
706 ebp
= (void *)bp
->b_un
.b_addr
;
707 ebp
->type
= LUFS_EXTENTS
;
708 ebp
->nextbno
= UINT32_C(0);
709 ebp
->nextents
= UINT32_C(0);
710 ebp
->chksum
= INT32_C(0);
711 if (fs
->fs_magic
== FS_MAGIC
)
714 logbno
= dbtofsb(fs
, bno
);
717 * Initialize the first extent
719 ep
= &ebp
->extents
[0];
720 error
= alloc(ip
, fno
+ fs
->fs_frag
, fs
->fs_bsize
, &fno
, cr
);
723 bno
= fsbtodb(fs
, fno
);
725 ep
->lbno
= UINT32_C(0);
726 if (fs
->fs_magic
== FS_MAGIC
)
727 ep
->pbno
= (uint32_t)bno
;
729 ep
->pbno
= (uint32_t)fno
;
730 ep
->nbno
= (uint32_t)fsbtodb(fs
, fs
->fs_frag
);
731 ebp
->nextents
= UINT32_C(1);
736 error
= alloc(ip
, fno
+ fs
->fs_frag
, fs
->fs_bsize
, &fno
, cr
);
743 bno
= fsbtodb(fs
, fno
);
744 if ((daddr_t
)((logbtodb(fs
, ep
->pbno
) + ep
->nbno
) == bno
))
745 ep
->nbno
+= (uint32_t)(fsbtodb(fs
, fs
->fs_frag
));
748 if ((caddr_t
)(nep
+ 1) >
749 (bp
->b_un
.b_addr
+ fs
->fs_bsize
)) {
750 free(ip
, fno
, fs
->fs_bsize
, 0);
753 nep
->lbno
= ep
->lbno
+ ep
->nbno
;
754 if (fs
->fs_magic
== FS_MAGIC
)
755 nep
->pbno
= (uint32_t)bno
;
757 nep
->pbno
= (uint32_t)fno
;
758 nep
->nbno
= (uint32_t)(fsbtodb(fs
, fs
->fs_frag
));
766 if (tb
< minb
) { /* Failed to reach minimum log size */
771 ebp
->nbytes
= (uint32_t)tb
;
772 setsum(&ebp
->chksum
, (int32_t *)bp
->b_un
.b_addr
, fs
->fs_bsize
);
773 UFS_BWRITE2(ufsvfsp
, bp
);
774 if (bp
->b_flags
& B_ERROR
) {
779 * Initialize the first two sectors of the log
781 error
= lufs_initialize(ufsvfsp
, logbtodb(fs
, ebp
->extents
[0].pbno
),
787 * We are done initializing the allocation block and the log
793 * Update the superblock and push the dirty metadata
795 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= curthread
;
796 sbupdate(ufsvfsp
->vfs_vfs
);
797 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= (kthread_id_t
)-1;
798 bflush(ufsvfsp
->vfs_dev
);
799 error
= bfinval(ufsvfsp
->vfs_dev
, 1);
802 if (ufsvfsp
->vfs_bufp
->b_flags
& B_ERROR
) {
808 * Everything is safely on disk; update log space pointer in sb
810 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= curthread
;
811 mutex_enter(&ufsvfsp
->vfs_lock
);
812 fs
->fs_logbno
= (uint32_t)logbno
;
813 ufs_sbwrite(ufsvfsp
);
814 mutex_exit(&ufsvfsp
->vfs_lock
);
815 ufsvfsp
->vfs_ulockfs
.ul_sbowner
= (kthread_id_t
)-1;
818 * Free the dummy inode
820 rw_exit(&ip
->i_contents
);
823 /* inform user of real log size */
824 flp
->nbytes_actual
= tb
;
834 fs
->fs_logbno
= logbno
;
835 (void) lufs_free(ufsvfsp
);
838 rw_exit(&ip
->i_contents
);
848 lufs_disable(vnode_t
*vp
, struct fiolog
*flp
)
851 inode_t
*ip
= VTOI(vp
);
852 ufsvfs_t
*ufsvfsp
= ip
->i_ufsvfs
;
853 struct fs
*fs
= ufsvfsp
->vfs_fs
;
857 flp
->error
= FIOLOG_ENONE
;
860 * Logging is already disabled; done
862 if (fs
->fs_logbno
== 0 || ufsvfsp
->vfs_log
== NULL
)
866 * Readonly file system
869 flp
->error
= FIOLOG_EROFS
;
874 * File system must be write locked to disable logging
876 error
= ufs_fiolfss(vp
, &lf
);
880 if (!LOCKFS_IS_ULOCK(&lf
)) {
881 flp
->error
= FIOLOG_EULOCK
;
884 lf
.lf_lock
= LOCKFS_WLOCK
;
886 lf
.lf_comment
= NULL
;
887 error
= ufs_fiolfs(vp
, &lf
, 1);
889 flp
->error
= FIOLOG_EWLOCK
;
893 if (ufsvfsp
->vfs_log
== NULL
|| fs
->fs_logbno
== 0)
897 * WE ARE COMMITTED TO DISABLING LOGGING PAST THIS POINT
902 * Suspend the reclaim thread and force the delete thread to exit.
903 * When a nologging mount has completed there may still be
904 * work for reclaim to do so just suspend this thread until
905 * it's [deadlock-] safe for it to continue. The delete
906 * thread won't be needed as ufs_iinactive() calls
907 * ufs_delete() when logging is disabled.
908 * Freeze and drain reader ops.
909 * Commit any outstanding reader transactions (ufs_flush).
910 * Set the ``unmounted'' bit in the ufstrans struct.
911 * If debug, remove metadata from matamap.
912 * Disable matamap processing.
913 * NULL the trans ops table.
914 * Free all of the incore structs related to logging.
917 ufs_thread_suspend(&ufsvfsp
->vfs_reclaim
);
918 ufs_thread_exit(&ufsvfsp
->vfs_delete
);
920 vfs_lock_wait(ufsvfsp
->vfs_vfs
);
921 ulp
= &ufsvfsp
->vfs_ulockfs
;
922 mutex_enter(&ulp
->ul_lock
);
923 atomic_inc_ulong(&ufs_quiesce_pend
);
924 (void) ufs_quiesce(ulp
);
926 (void) ufs_flush(ufsvfsp
->vfs_vfs
);
928 TRANS_MATA_UMOUNT(ufsvfsp
);
929 ufsvfsp
->vfs_domatamap
= 0;
932 * Free all of the incore structs
933 * Aquire the ufs_scan_lock before de-linking the mtm data
934 * structure so that we keep ufs_sync() and ufs_update() away
935 * when they execute the ufs_scan_inodes() run while we're in
936 * progress of enabling/disabling logging.
938 mutex_enter(&ufs_scan_lock
);
939 (void) lufs_unsnarf(ufsvfsp
);
940 mutex_exit(&ufs_scan_lock
);
942 atomic_dec_ulong(&ufs_quiesce_pend
);
943 mutex_exit(&ulp
->ul_lock
);
944 vfs_setmntopt(ufsvfsp
->vfs_vfs
, MNTOPT_NOLOGGING
, NULL
, 0);
945 vfs_unlock(ufsvfsp
->vfs_vfs
);
947 fs
->fs_rolled
= FS_ALL_ROLLED
;
948 ufsvfsp
->vfs_nolog_si
= 0;
951 * Free the log space and mark the superblock as FSACTIVE
953 (void) lufs_free(ufsvfsp
);
956 * Allow the reclaim thread to continue.
958 ufs_thread_continue(&ufsvfsp
->vfs_reclaim
);
961 * Unlock the file system
963 lf
.lf_lock
= LOCKFS_ULOCK
;
965 error
= ufs_fiolfs(vp
, &lf
, 1);
967 flp
->error
= FIOLOG_ENOULOCK
;
972 lf
.lf_lock
= LOCKFS_ULOCK
;
974 (void) ufs_fiolfs(vp
, &lf
, 1);
982 lufs_enable(struct vnode
*vp
, struct fiolog
*flp
, cred_t
*cr
)
986 inode_t
*ip
= VTOI(vp
);
987 ufsvfs_t
*ufsvfsp
= ip
->i_ufsvfs
;
992 vfs_t
*vfsp
= ufsvfsp
->vfs_vfs
;
993 uint64_t tmp_nbytes_actual
;
994 uint64_t cg_minlogsize
;
996 static int minlogsizewarn
= 0;
997 static int maxlogsizewarn
= 0;
1000 * Check if logging is already enabled
1002 if (ufsvfsp
->vfs_log
) {
1003 flp
->error
= FIOLOG_ETRANS
;
1004 /* for root ensure logging option is set */
1005 vfs_setmntopt(vfsp
, MNTOPT_LOGGING
, NULL
, 0);
1008 fs
= ufsvfsp
->vfs_fs
;
1011 * Come back here to recheck if we had to disable the log.
1016 flp
->error
= FIOLOG_ENONE
;
1019 * The size of the ufs log is determined using the following rules:
1021 * 1) If no size is requested the log size is calculated as a
1022 * ratio of the total file system size. By default this is
1023 * 1MB of log per 1GB of file system. This calculation is then
1024 * capped at the log size specified by ldl_softlogcap.
1025 * 2) The log size requested may then be increased based on the
1026 * number of cylinder groups contained in the file system.
1027 * To prevent a hang the log has to be large enough to contain a
1028 * single transaction that alters every cylinder group in the file
1029 * system. This is calculated as cg_minlogsize.
1030 * 3) Finally a check is made that the log size requested is within
1031 * the limits of ldl_minlogsize and ldl_maxlogsize.
1035 * Adjust requested log size
1037 flp
->nbytes_actual
= flp
->nbytes_requested
;
1038 if (flp
->nbytes_actual
== 0) {
1040 (((uint64_t)fs
->fs_size
) / ldl_divisor
) << fs
->fs_fshift
;
1041 flp
->nbytes_actual
= (uint_t
)MIN(tmp_nbytes_actual
, INT_MAX
);
1043 * The 1MB per 1GB log size allocation only applies up to
1044 * ldl_softlogcap size of log.
1046 flp
->nbytes_actual
= MIN(flp
->nbytes_actual
, ldl_softlogcap
);
1049 cgsize
= ldl_cgsizereq
? ldl_cgsizereq
: LDL_CGSIZEREQ(fs
);
1052 * Determine the log size required based on the number of cylinder
1053 * groups in the file system. The log has to be at least this size
1054 * to prevent possible hangs due to log space exhaustion.
1056 cg_minlogsize
= cgsize
* fs
->fs_ncg
;
1059 * Ensure that the minimum log size isn't so small that it could lead
1060 * to a full log hang.
1062 if (ldl_minlogsize
< LDL_MINLOGSIZE
) {
1063 ldl_minlogsize
= LDL_MINLOGSIZE
;
1064 if (!minlogsizewarn
) {
1065 cmn_err(CE_WARN
, "ldl_minlogsize too small, increasing "
1066 "to 0x%x", LDL_MINLOGSIZE
);
1072 * Ensure that the maximum log size isn't greater than INT_MAX as the
1073 * logical log offset fields would overflow.
1075 if (ldl_maxlogsize
> INT_MAX
) {
1076 ldl_maxlogsize
= INT_MAX
;
1077 if (!maxlogsizewarn
) {
1078 cmn_err(CE_WARN
, "ldl_maxlogsize too large, reducing "
1079 "to 0x%x", INT_MAX
);
1084 if (cg_minlogsize
> ldl_maxlogsize
) {
1086 "%s: reducing calculated log size from 0x%x to "
1087 "ldl_maxlogsize (0x%x).", fs
->fs_fsmnt
, (int)cg_minlogsize
,
1091 cg_minlogsize
= MAX(cg_minlogsize
, ldl_minlogsize
);
1092 cg_minlogsize
= MIN(cg_minlogsize
, ldl_maxlogsize
);
1094 flp
->nbytes_actual
= MAX(flp
->nbytes_actual
, cg_minlogsize
);
1095 flp
->nbytes_actual
= MAX(flp
->nbytes_actual
, ldl_minlogsize
);
1096 flp
->nbytes_actual
= MIN(flp
->nbytes_actual
, ldl_maxlogsize
);
1097 flp
->nbytes_actual
= blkroundup(fs
, flp
->nbytes_actual
);
1100 * logging is enabled and the log is the right size; done
1102 ul
= ufsvfsp
->vfs_log
;
1103 if (ul
&& fs
->fs_logbno
&& (flp
->nbytes_actual
== ul
->un_requestsize
))
1107 * Readonly file system
1110 flp
->error
= FIOLOG_EROFS
;
1115 * File system must be write locked to enable logging
1117 error
= ufs_fiolfss(vp
, &lf
);
1121 if (!LOCKFS_IS_ULOCK(&lf
)) {
1122 flp
->error
= FIOLOG_EULOCK
;
1125 lf
.lf_lock
= LOCKFS_WLOCK
;
1127 lf
.lf_comment
= NULL
;
1128 error
= ufs_fiolfs(vp
, &lf
, 1);
1130 flp
->error
= FIOLOG_EWLOCK
;
1135 * Grab appropriate locks to synchronize with the rest
1138 vfs_lock_wait(vfsp
);
1139 ulp
= &ufsvfsp
->vfs_ulockfs
;
1140 mutex_enter(&ulp
->ul_lock
);
1143 * File system must be fairly consistent to enable logging
1145 if (fs
->fs_clean
!= FSLOG
&&
1146 fs
->fs_clean
!= FSACTIVE
&&
1147 fs
->fs_clean
!= FSSTABLE
&&
1148 fs
->fs_clean
!= FSCLEAN
) {
1149 flp
->error
= FIOLOG_ECLEAN
;
1154 * A write-locked file system is only active if there are
1155 * open deleted files; so remember to set FS_RECLAIM later.
1157 if (fs
->fs_clean
== FSACTIVE
)
1158 reclaim
= FS_RECLAIM
;
1161 * Logging is already enabled; must be changing the log's size
1163 if (fs
->fs_logbno
&& ufsvfsp
->vfs_log
) {
1165 * Before we can disable logging, we must give up our
1166 * lock. As a consequence of unlocking and disabling the
1167 * log, the fs structure may change. Because of this, when
1168 * disabling is complete, we will go back to recheck to
1169 * repeat all of the checks that we performed to get to
1170 * this point. Disabling sets fs->fs_logbno to 0, so this
1171 * will not put us into an infinite loop.
1173 mutex_exit(&ulp
->ul_lock
);
1176 lf
.lf_lock
= LOCKFS_ULOCK
;
1178 error
= ufs_fiolfs(vp
, &lf
, 1);
1180 flp
->error
= FIOLOG_ENOULOCK
;
1183 error
= lufs_disable(vp
, flp
);
1184 if (error
|| (flp
->error
!= FIOLOG_ENONE
))
1189 error
= lufs_alloc(ufsvfsp
, flp
, cg_minlogsize
, cr
);
1194 * Create all of the incore structs
1196 error
= lufs_snarf(ufsvfsp
, fs
, 0);
1201 * DON'T ``GOTO ERROUT'' PAST THIS POINT
1205 * Pretend we were just mounted with logging enabled
1206 * Get the ops vector
1207 * If debug, record metadata locations with log subsystem
1208 * Start the delete thread
1209 * Start the reclaim thread, if necessary
1211 vfs_setmntopt(vfsp
, MNTOPT_LOGGING
, NULL
, 0);
1213 TRANS_DOMATAMAP(ufsvfsp
);
1214 TRANS_MATA_MOUNT(ufsvfsp
);
1215 TRANS_MATA_SI(ufsvfsp
, fs
);
1216 ufs_thread_start(&ufsvfsp
->vfs_delete
, ufs_thread_delete
, vfsp
);
1217 if (fs
->fs_reclaim
& (FS_RECLAIM
|FS_RECLAIMING
)) {
1218 fs
->fs_reclaim
&= ~FS_RECLAIM
;
1219 fs
->fs_reclaim
|= FS_RECLAIMING
;
1220 ufs_thread_start(&ufsvfsp
->vfs_reclaim
,
1221 ufs_thread_reclaim
, vfsp
);
1223 fs
->fs_reclaim
|= reclaim
;
1225 mutex_exit(&ulp
->ul_lock
);
1229 * Unlock the file system
1231 lf
.lf_lock
= LOCKFS_ULOCK
;
1233 error
= ufs_fiolfs(vp
, &lf
, 1);
1235 flp
->error
= FIOLOG_ENOULOCK
;
1240 * There's nothing in the log yet (we've just allocated it)
1241 * so directly write out the super block.
1242 * Note, we have to force this sb out to disk
1243 * (not just to the log) so that if we crash we know we are logging
1245 mutex_enter(&ufsvfsp
->vfs_lock
);
1246 fs
->fs_clean
= FSLOG
;
1247 fs
->fs_rolled
= FS_NEED_ROLL
; /* Mark the fs as unrolled */
1248 UFS_BWRITE2(NULL
, ufsvfsp
->vfs_bufp
);
1249 mutex_exit(&ufsvfsp
->vfs_lock
);
1255 * Aquire the ufs_scan_lock before de-linking the mtm data
1256 * structure so that we keep ufs_sync() and ufs_update() away
1257 * when they execute the ufs_scan_inodes() run while we're in
1258 * progress of enabling/disabling logging.
1260 mutex_enter(&ufs_scan_lock
);
1261 (void) lufs_unsnarf(ufsvfsp
);
1262 mutex_exit(&ufs_scan_lock
);
1264 (void) lufs_free(ufsvfsp
);
1266 mutex_exit(&ulp
->ul_lock
);
1269 lf
.lf_lock
= LOCKFS_ULOCK
;
1271 (void) ufs_fiolfs(vp
, &lf
, 1);
1276 lufs_read_strategy(ml_unit_t
*ul
, buf_t
*bp
)
1278 mt_map_t
*logmap
= ul
->un_logmap
;
1279 offset_t mof
= ldbtob(bp
->b_blkno
);
1280 off_t nb
= bp
->b_bcount
;
1287 * get a linked list of overlapping deltas
1288 * returns with &mtm->mtm_rwlock held
1290 entire_range
= logmap_list_get(logmap
, mof
, nb
, &age
);
1293 * no overlapping deltas were found; read master
1296 rw_exit(&logmap
->mtm_rwlock
);
1297 if (ul
->un_flags
& LDL_ERROR
) {
1298 bp
->b_flags
|= B_ERROR
;
1302 ul
->un_ufsvfs
->vfs_iotstamp
= ddi_get_lbolt();
1303 logstats
.ls_lreads
.value
.ui64
++;
1304 (void) bdev_strategy(bp
);
1305 lwp_stat_update(LWP_STAT_INBLK
, 1);
1310 va
= bp_mapin_common(bp
, VM_SLEEP
);
1312 * if necessary, sync read the data from master
1313 * errors are returned in bp
1315 if (!entire_range
) {
1316 saviodone
= bp
->b_iodone
;
1317 bp
->b_iodone
= trans_not_done
;
1318 logstats
.ls_mreads
.value
.ui64
++;
1319 (void) bdev_strategy(bp
);
1320 lwp_stat_update(LWP_STAT_INBLK
, 1);
1321 if (trans_not_wait(bp
))
1322 ldl_seterror(ul
, "Error reading master");
1323 bp
->b_iodone
= saviodone
;
1327 * sync read the data from the log
1328 * errors are returned inline
1330 if (ldl_read(ul
, va
, mof
, nb
, age
)) {
1331 bp
->b_flags
|= B_ERROR
;
1338 logmap_list_put(logmap
, age
);
1343 if (ul
->un_flags
& LDL_ERROR
) {
1344 bp
->b_flags
|= B_ERROR
;
1351 lufs_write_strategy(ml_unit_t
*ul
, buf_t
*bp
)
1353 offset_t mof
= ldbtob(bp
->b_blkno
);
1354 off_t nb
= bp
->b_bcount
;
1358 ASSERT((nb
& DEV_BMASK
) == 0);
1359 ul
->un_logmap
->mtm_ref
= 1;
1362 * if there are deltas, move into log
1364 me
= deltamap_remove(ul
->un_deltamap
, mof
, nb
);
1367 va
= bp_mapin_common(bp
, VM_SLEEP
);
1369 ASSERT(((ul
->un_debug
& MT_WRITE_CHECK
) == 0) ||
1370 (ul
->un_matamap
== NULL
)||
1371 matamap_within(ul
->un_matamap
, mof
, nb
));
1376 if (ufs_crb_enable
) {
1377 logmap_add_buf(ul
, va
, mof
, me
,
1378 bp
->b_un
.b_addr
, nb
);
1380 logmap_add(ul
, va
, mof
, me
);
1383 if (ul
->un_flags
& LDL_ERROR
) {
1384 bp
->b_flags
|= B_ERROR
;
1390 if (ul
->un_flags
& LDL_ERROR
) {
1391 bp
->b_flags
|= B_ERROR
;
1398 * Check that we are not updating metadata, or if so then via B_PHYS.
1400 ASSERT((ul
->un_matamap
== NULL
) ||
1401 !(matamap_overlap(ul
->un_matamap
, mof
, nb
) &&
1402 ((bp
->b_flags
& B_PHYS
) == 0)));
1404 ul
->un_ufsvfs
->vfs_iotstamp
= ddi_get_lbolt();
1405 logstats
.ls_lwrites
.value
.ui64
++;
1407 /* If snapshots are enabled, write through the snapshot driver */
1408 if (ul
->un_ufsvfs
->vfs_snapshot
)
1409 fssnap_strategy(&ul
->un_ufsvfs
->vfs_snapshot
, bp
);
1411 (void) bdev_strategy(bp
);
1413 lwp_stat_update(LWP_STAT_OUBLK
, 1);
1417 lufs_strategy(ml_unit_t
*ul
, buf_t
*bp
)
1419 if (bp
->b_flags
& B_READ
)
1420 lufs_read_strategy(ul
, bp
);
1422 lufs_write_strategy(ul
, bp
);
1427 delta_stats_update(kstat_t
*ksp
, int rw
)
1429 if (rw
== KSTAT_WRITE
) {
1430 delta_stats
[DT_SB
] = dkstats
.ds_superblock_deltas
.value
.ui64
;
1431 delta_stats
[DT_CG
] = dkstats
.ds_bitmap_deltas
.value
.ui64
;
1432 delta_stats
[DT_SI
] = dkstats
.ds_suminfo_deltas
.value
.ui64
;
1433 delta_stats
[DT_AB
] = dkstats
.ds_allocblk_deltas
.value
.ui64
;
1434 delta_stats
[DT_ABZERO
] = dkstats
.ds_ab0_deltas
.value
.ui64
;
1435 delta_stats
[DT_DIR
] = dkstats
.ds_dir_deltas
.value
.ui64
;
1436 delta_stats
[DT_INODE
] = dkstats
.ds_inode_deltas
.value
.ui64
;
1437 delta_stats
[DT_FBI
] = dkstats
.ds_fbiwrite_deltas
.value
.ui64
;
1438 delta_stats
[DT_QR
] = dkstats
.ds_quota_deltas
.value
.ui64
;
1439 delta_stats
[DT_SHAD
] = dkstats
.ds_shadow_deltas
.value
.ui64
;
1441 roll_stats
[DT_SB
] = dkstats
.ds_superblock_rolled
.value
.ui64
;
1442 roll_stats
[DT_CG
] = dkstats
.ds_bitmap_rolled
.value
.ui64
;
1443 roll_stats
[DT_SI
] = dkstats
.ds_suminfo_rolled
.value
.ui64
;
1444 roll_stats
[DT_AB
] = dkstats
.ds_allocblk_rolled
.value
.ui64
;
1445 roll_stats
[DT_ABZERO
] = dkstats
.ds_ab0_rolled
.value
.ui64
;
1446 roll_stats
[DT_DIR
] = dkstats
.ds_dir_rolled
.value
.ui64
;
1447 roll_stats
[DT_INODE
] = dkstats
.ds_inode_rolled
.value
.ui64
;
1448 roll_stats
[DT_FBI
] = dkstats
.ds_fbiwrite_rolled
.value
.ui64
;
1449 roll_stats
[DT_QR
] = dkstats
.ds_quota_rolled
.value
.ui64
;
1450 roll_stats
[DT_SHAD
] = dkstats
.ds_shadow_rolled
.value
.ui64
;
1452 dkstats
.ds_superblock_deltas
.value
.ui64
= delta_stats
[DT_SB
];
1453 dkstats
.ds_bitmap_deltas
.value
.ui64
= delta_stats
[DT_CG
];
1454 dkstats
.ds_suminfo_deltas
.value
.ui64
= delta_stats
[DT_SI
];
1455 dkstats
.ds_allocblk_deltas
.value
.ui64
= delta_stats
[DT_AB
];
1456 dkstats
.ds_ab0_deltas
.value
.ui64
= delta_stats
[DT_ABZERO
];
1457 dkstats
.ds_dir_deltas
.value
.ui64
= delta_stats
[DT_DIR
];
1458 dkstats
.ds_inode_deltas
.value
.ui64
= delta_stats
[DT_INODE
];
1459 dkstats
.ds_fbiwrite_deltas
.value
.ui64
= delta_stats
[DT_FBI
];
1460 dkstats
.ds_quota_deltas
.value
.ui64
= delta_stats
[DT_QR
];
1461 dkstats
.ds_shadow_deltas
.value
.ui64
= delta_stats
[DT_SHAD
];
1463 dkstats
.ds_superblock_rolled
.value
.ui64
= roll_stats
[DT_SB
];
1464 dkstats
.ds_bitmap_rolled
.value
.ui64
= roll_stats
[DT_CG
];
1465 dkstats
.ds_suminfo_rolled
.value
.ui64
= roll_stats
[DT_SI
];
1466 dkstats
.ds_allocblk_rolled
.value
.ui64
= roll_stats
[DT_AB
];
1467 dkstats
.ds_ab0_rolled
.value
.ui64
= roll_stats
[DT_ABZERO
];
1468 dkstats
.ds_dir_rolled
.value
.ui64
= roll_stats
[DT_DIR
];
1469 dkstats
.ds_inode_rolled
.value
.ui64
= roll_stats
[DT_INODE
];
1470 dkstats
.ds_fbiwrite_rolled
.value
.ui64
= roll_stats
[DT_FBI
];
1471 dkstats
.ds_quota_rolled
.value
.ui64
= roll_stats
[DT_QR
];
1472 dkstats
.ds_shadow_rolled
.value
.ui64
= roll_stats
[DT_SHAD
];
1477 extern size_t ufs_crb_limit
;
1478 extern int ufs_max_crb_divisor
;
1485 /* Create kmem caches */
1486 lufs_sv
= kmem_cache_create("lufs_save", sizeof (lufs_save_t
), 0,
1487 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
1488 lufs_bp
= kmem_cache_create("lufs_bufs", sizeof (lufs_buf_t
), 0,
1489 NULL
, NULL
, NULL
, NULL
, NULL
, 0);
1491 mutex_init(&log_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
1495 if (bio_lufs_strategy
== NULL
)
1496 bio_lufs_strategy
= (void (*) (void *, buf_t
*)) lufs_strategy
;
1499 * Initialise general logging and delta kstats
1501 ksp
= kstat_create("ufs_log", 0, "logstats", "ufs", KSTAT_TYPE_NAMED
,
1502 sizeof (logstats
) / sizeof (kstat_named_t
), KSTAT_FLAG_VIRTUAL
);
1504 ksp
->ks_data
= (void *) &logstats
;
1508 ksp
= kstat_create("ufs_log", 0, "deltastats", "ufs", KSTAT_TYPE_NAMED
,
1509 sizeof (dkstats
) / sizeof (kstat_named_t
), KSTAT_FLAG_VIRTUAL
);
1511 ksp
->ks_data
= (void *) &dkstats
;
1512 ksp
->ks_update
= delta_stats_update
;
1516 /* Initialize generation of logging ids */
1520 * Set up the maximum amount of kmem that the crbs (system wide)
1523 ufs_crb_limit
= kmem_maxavail() / ufs_max_crb_divisor
;