| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vfs_wapbl.c,v 1.86 2016/11/10 20:56:32 jdolecek Exp $ */ | | 1 | /* $NetBSD: vfs_wapbl.c,v 1.87 2017/03/05 13:57:29 jdolecek Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2003, 2008, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2003, 2008, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Wasabi Systems, Inc. | | 8 | * by Wasabi Systems, Inc. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -26,27 +26,27 @@ | | | @@ -26,27 +26,27 @@ |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * This implements file system independent write ahead filesystem logging. | | 33 | * This implements file system independent write ahead filesystem logging. |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #define WAPBL_INTERNAL | | 36 | #define WAPBL_INTERNAL |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | __KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.86 2016/11/10 20:56:32 jdolecek Exp $"); | | 39 | __KERNEL_RCSID(0, "$NetBSD: vfs_wapbl.c,v 1.87 2017/03/05 13:57:29 jdolecek Exp $"); |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/bitops.h> | | 42 | #include <sys/bitops.h> |
43 | #include <sys/time.h> | | 43 | #include <sys/time.h> |
44 | #include <sys/wapbl.h> | | 44 | #include <sys/wapbl.h> |
45 | #include <sys/wapbl_replay.h> | | 45 | #include <sys/wapbl_replay.h> |
46 | | | 46 | |
47 | #ifdef _KERNEL | | 47 | #ifdef _KERNEL |
48 | | | 48 | |
49 | #include <sys/atomic.h> | | 49 | #include <sys/atomic.h> |
50 | #include <sys/conf.h> | | 50 | #include <sys/conf.h> |
51 | #include <sys/file.h> | | 51 | #include <sys/file.h> |
52 | #include <sys/kauth.h> | | 52 | #include <sys/kauth.h> |
| @@ -166,34 +166,41 @@ struct wapbl { | | | @@ -166,34 +166,41 @@ struct wapbl { |
166 | */ | | 166 | */ |
167 | | | 167 | |
168 | struct wapbl_wc_header *wl_wc_header; /* l */ | | 168 | struct wapbl_wc_header *wl_wc_header; /* l */ |
169 | void *wl_wc_scratch; /* l: scratch space (XXX: por que?!?) */ | | 169 | void *wl_wc_scratch; /* l: scratch space (XXX: por que?!?) */ |
170 | | | 170 | |
171 | kmutex_t wl_mtx; /* u: short-term lock */ | | 171 | kmutex_t wl_mtx; /* u: short-term lock */ |
172 | krwlock_t wl_rwlock; /* u: File system transaction lock */ | | 172 | krwlock_t wl_rwlock; /* u: File system transaction lock */ |
173 | | | 173 | |
174 | /* | | 174 | /* |
175 | * Must be held while accessing | | 175 | * Must be held while accessing |
176 | * wl_count or wl_bufs or head or tail | | 176 | * wl_count or wl_bufs or head or tail |
177 | */ | | 177 | */ |
178 | | | 178 | |
| | | 179 | #if _KERNEL |
179 | /* | | 180 | /* |
180 | * Callback called from within the flush routine to flush any extra | | 181 | * Callback called from within the flush routine to flush any extra |
181 | * bits. Note that flush may be skipped without calling this if | | 182 | * bits. Note that flush may be skipped without calling this if |
182 | * there are no outstanding buffers in the transaction. | | 183 | * there are no outstanding buffers in the transaction. |
183 | */ | | 184 | */ |
184 | #if _KERNEL | | | |
185 | wapbl_flush_fn_t wl_flush; /* r */ | | 185 | wapbl_flush_fn_t wl_flush; /* r */ |
186 | wapbl_flush_fn_t wl_flush_abort;/* r */ | | 186 | wapbl_flush_fn_t wl_flush_abort;/* r */ |
| | | 187 | |
| | | 188 | /* Event counters */ |
| | | 189 | char wl_ev_group[EVCNT_STRING_MAX]; /* r */ |
| | | 190 | struct evcnt wl_ev_commit; /* l */ |
| | | 191 | struct evcnt wl_ev_journalwrite; /* l */ |
| | | 192 | struct evcnt wl_ev_metawrite; /* lm */ |
| | | 193 | struct evcnt wl_ev_cacheflush; /* l */ |
187 | #endif | | 194 | #endif |
188 | | | 195 | |
189 | size_t wl_bufbytes; /* m: Byte count of pages in wl_bufs */ | | 196 | size_t wl_bufbytes; /* m: Byte count of pages in wl_bufs */ |
190 | size_t wl_bufcount; /* m: Count of buffers in wl_bufs */ | | 197 | size_t wl_bufcount; /* m: Count of buffers in wl_bufs */ |
191 | size_t wl_bcount; /* m: Total bcount of wl_bufs */ | | 198 | size_t wl_bcount; /* m: Total bcount of wl_bufs */ |
192 | | | 199 | |
193 | LIST_HEAD(, buf) wl_bufs; /* m: Buffers in current transaction */ | | 200 | LIST_HEAD(, buf) wl_bufs; /* m: Buffers in current transaction */ |
194 | | | 201 | |
195 | kcondvar_t wl_reclaimable_cv; /* m (obviously) */ | | 202 | kcondvar_t wl_reclaimable_cv; /* m (obviously) */ |
196 | size_t wl_reclaimable_bytes; /* m: Amount of space available for | | 203 | size_t wl_reclaimable_bytes; /* m: Amount of space available for |
197 | reclamation by truncate */ | | 204 | reclamation by truncate */ |
198 | int wl_error_count; /* m: # of wl_entries with errors */ | | 205 | int wl_error_count; /* m: # of wl_entries with errors */ |
199 | size_t wl_reserved_bytes; /* never truncate log smaller than this */ | | 206 | size_t wl_reserved_bytes; /* never truncate log smaller than this */ |
| @@ -260,26 +267,29 @@ struct wapbl_ino { | | | @@ -260,26 +267,29 @@ struct wapbl_ino { |
260 | mode_t wi_mode; | | 267 | mode_t wi_mode; |
261 | }; | | 268 | }; |
262 | | | 269 | |
263 | static void wapbl_inodetrk_init(struct wapbl *wl, u_int size); | | 270 | static void wapbl_inodetrk_init(struct wapbl *wl, u_int size); |
264 | static void wapbl_inodetrk_free(struct wapbl *wl); | | 271 | static void wapbl_inodetrk_free(struct wapbl *wl); |
265 | static struct wapbl_ino *wapbl_inodetrk_get(struct wapbl *wl, ino_t ino); | | 272 | static struct wapbl_ino *wapbl_inodetrk_get(struct wapbl *wl, ino_t ino); |
266 | | | 273 | |
267 | static size_t wapbl_transaction_len(struct wapbl *wl); | | 274 | static size_t wapbl_transaction_len(struct wapbl *wl); |
268 | static inline size_t wapbl_transaction_inodes_len(struct wapbl *wl); | | 275 | static inline size_t wapbl_transaction_inodes_len(struct wapbl *wl); |
269 | | | 276 | |
270 | static void wapbl_deallocation_free(struct wapbl *, struct wapbl_dealloc *, | | 277 | static void wapbl_deallocation_free(struct wapbl *, struct wapbl_dealloc *, |
271 | bool); | | 278 | bool); |
272 | | | 279 | |
| | | 280 | static void wapbl_evcnt_init(struct wapbl *); |
| | | 281 | static void wapbl_evcnt_free(struct wapbl *); |
| | | 282 | |
273 | #if 0 | | 283 | #if 0 |
274 | int wapbl_replay_verify(struct wapbl_replay *, struct vnode *); | | 284 | int wapbl_replay_verify(struct wapbl_replay *, struct vnode *); |
275 | #endif | | 285 | #endif |
276 | | | 286 | |
277 | static int wapbl_replay_isopen1(struct wapbl_replay *); | | 287 | static int wapbl_replay_isopen1(struct wapbl_replay *); |
278 | | | 288 | |
279 | struct wapbl_ops wapbl_ops = { | | 289 | struct wapbl_ops wapbl_ops = { |
280 | .wo_wapbl_discard = wapbl_discard, | | 290 | .wo_wapbl_discard = wapbl_discard, |
281 | .wo_wapbl_replay_isopen = wapbl_replay_isopen1, | | 291 | .wo_wapbl_replay_isopen = wapbl_replay_isopen1, |
282 | .wo_wapbl_replay_can_read = wapbl_replay_can_read, | | 292 | .wo_wapbl_replay_can_read = wapbl_replay_can_read, |
283 | .wo_wapbl_replay_read = wapbl_replay_read, | | 293 | .wo_wapbl_replay_read = wapbl_replay_read, |
284 | .wo_wapbl_add_buf = wapbl_add_buf, | | 294 | .wo_wapbl_add_buf = wapbl_add_buf, |
285 | .wo_wapbl_remove_buf = wapbl_remove_buf, | | 295 | .wo_wapbl_remove_buf = wapbl_remove_buf, |
| @@ -342,26 +352,54 @@ wapbl_init(void) | | | @@ -342,26 +352,54 @@ wapbl_init(void) |
342 | static int | | 352 | static int |
343 | wapbl_fini(void) | | 353 | wapbl_fini(void) |
344 | { | | 354 | { |
345 | | | 355 | |
346 | if (wapbl_sysctl != NULL) | | 356 | if (wapbl_sysctl != NULL) |
347 | sysctl_teardown(&wapbl_sysctl); | | 357 | sysctl_teardown(&wapbl_sysctl); |
348 | | | 358 | |
349 | pool_destroy(&wapbl_dealloc_pool); | | 359 | pool_destroy(&wapbl_dealloc_pool); |
350 | pool_destroy(&wapbl_entry_pool); | | 360 | pool_destroy(&wapbl_entry_pool); |
351 | | | 361 | |
352 | return 0; | | 362 | return 0; |
353 | } | | 363 | } |
354 | | | 364 | |
| | | 365 | static void |
| | | 366 | wapbl_evcnt_init(struct wapbl *wl) |
| | | 367 | { |
| | | 368 | snprintf(wl->wl_ev_group, sizeof(wl->wl_ev_group), |
| | | 369 | "wapbl fsid 0x%x/0x%x", |
| | | 370 | wl->wl_mount->mnt_stat.f_fsidx.__fsid_val[0], |
| | | 371 | wl->wl_mount->mnt_stat.f_fsidx.__fsid_val[1] |
| | | 372 | ); |
| | | 373 | |
| | | 374 | evcnt_attach_dynamic(&wl->wl_ev_commit, EVCNT_TYPE_MISC, |
| | | 375 | NULL, wl->wl_ev_group, "commit"); |
| | | 376 | evcnt_attach_dynamic(&wl->wl_ev_journalwrite, EVCNT_TYPE_MISC, |
| | | 377 | NULL, wl->wl_ev_group, "journal sync block write"); |
| | | 378 | evcnt_attach_dynamic(&wl->wl_ev_metawrite, EVCNT_TYPE_MISC, |
| | | 379 | NULL, wl->wl_ev_group, "metadata finished block write"); |
| | | 380 | evcnt_attach_dynamic(&wl->wl_ev_cacheflush, EVCNT_TYPE_MISC, |
| | | 381 | NULL, wl->wl_ev_group, "cache flush"); |
| | | 382 | } |
| | | 383 | |
| | | 384 | static void |
| | | 385 | wapbl_evcnt_free(struct wapbl *wl) |
| | | 386 | { |
| | | 387 | evcnt_detach(&wl->wl_ev_commit); |
| | | 388 | evcnt_detach(&wl->wl_ev_journalwrite); |
| | | 389 | evcnt_detach(&wl->wl_ev_metawrite); |
| | | 390 | evcnt_detach(&wl->wl_ev_cacheflush); |
| | | 391 | } |
| | | 392 | |
355 | static int | | 393 | static int |
356 | wapbl_start_flush_inodes(struct wapbl *wl, struct wapbl_replay *wr) | | 394 | wapbl_start_flush_inodes(struct wapbl *wl, struct wapbl_replay *wr) |
357 | { | | 395 | { |
358 | int error, i; | | 396 | int error, i; |
359 | | | 397 | |
360 | WAPBL_PRINTF(WAPBL_PRINT_REPLAY, | | 398 | WAPBL_PRINTF(WAPBL_PRINT_REPLAY, |
361 | ("wapbl_start: reusing log with %d inodes\n", wr->wr_inodescnt)); | | 399 | ("wapbl_start: reusing log with %d inodes\n", wr->wr_inodescnt)); |
362 | | | 400 | |
363 | /* | | 401 | /* |
364 | * Its only valid to reuse the replay log if its | | 402 | * Its only valid to reuse the replay log if its |
365 | * the same as the new log we just opened. | | 403 | * the same as the new log we just opened. |
366 | */ | | 404 | */ |
367 | KDASSERT(!wapbl_replay_isopen(wr)); | | 405 | KDASSERT(!wapbl_replay_isopen(wr)); |
| @@ -512,26 +550,28 @@ wapbl_start(struct wapbl ** wlp, struct | | | @@ -512,26 +550,28 @@ wapbl_start(struct wapbl ** wlp, struct |
512 | - offsetof(struct wapbl_wc_blocklist, wc_blocks)) / | | 550 | - offsetof(struct wapbl_wc_blocklist, wc_blocks)) / |
513 | sizeof(((struct wapbl_wc_blocklist *)0)->wc_blocks[0]); | | 551 | sizeof(((struct wapbl_wc_blocklist *)0)->wc_blocks[0]); |
514 | KASSERT(wl->wl_brperjblock > 0); | | 552 | KASSERT(wl->wl_brperjblock > 0); |
515 | | | 553 | |
516 | /* XXX tie this into resource estimation */ | | 554 | /* XXX tie this into resource estimation */ |
517 | wl->wl_dealloclim = wl->wl_bufbytes_max / mp->mnt_stat.f_bsize / 2; | | 555 | wl->wl_dealloclim = wl->wl_bufbytes_max / mp->mnt_stat.f_bsize / 2; |
518 | TAILQ_INIT(&wl->wl_dealloclist); | | 556 | TAILQ_INIT(&wl->wl_dealloclist); |
519 | | | 557 | |
520 | wl->wl_buffer = wapbl_alloc(MAXPHYS); | | 558 | wl->wl_buffer = wapbl_alloc(MAXPHYS); |
521 | wl->wl_buffer_used = 0; | | 559 | wl->wl_buffer_used = 0; |
522 | | | 560 | |
523 | wapbl_inodetrk_init(wl, WAPBL_INODETRK_SIZE); | | 561 | wapbl_inodetrk_init(wl, WAPBL_INODETRK_SIZE); |
524 | | | 562 | |
| | | 563 | wapbl_evcnt_init(wl); |
| | | 564 | |
525 | /* Initialize the commit header */ | | 565 | /* Initialize the commit header */ |
526 | { | | 566 | { |
527 | struct wapbl_wc_header *wc; | | 567 | struct wapbl_wc_header *wc; |
528 | size_t len = 1 << wl->wl_log_dev_bshift; | | 568 | size_t len = 1 << wl->wl_log_dev_bshift; |
529 | wc = wapbl_calloc(1, len); | | 569 | wc = wapbl_calloc(1, len); |
530 | wc->wc_type = WAPBL_WC_HEADER; | | 570 | wc->wc_type = WAPBL_WC_HEADER; |
531 | wc->wc_len = len; | | 571 | wc->wc_len = len; |
532 | wc->wc_circ_off = wl->wl_circ_off; | | 572 | wc->wc_circ_off = wl->wl_circ_off; |
533 | wc->wc_circ_size = wl->wl_circ_size; | | 573 | wc->wc_circ_size = wl->wl_circ_size; |
534 | /* XXX wc->wc_fsid */ | | 574 | /* XXX wc->wc_fsid */ |
535 | wc->wc_log_dev_bshift = wl->wl_log_dev_bshift; | | 575 | wc->wc_log_dev_bshift = wl->wl_log_dev_bshift; |
536 | wc->wc_fs_dev_bshift = wl->wl_fs_dev_bshift; | | 576 | wc->wc_fs_dev_bshift = wl->wl_fs_dev_bshift; |
537 | wl->wl_wc_header = wc; | | 577 | wl->wl_wc_header = wc; |
| @@ -736,26 +776,28 @@ wapbl_stop(struct wapbl *wl, int force) | | | @@ -736,26 +776,28 @@ wapbl_stop(struct wapbl *wl, int force) |
736 | KASSERT(wl->wl_bufcount == 0); | | 776 | KASSERT(wl->wl_bufcount == 0); |
737 | KASSERT(LIST_EMPTY(&wl->wl_bufs)); | | 777 | KASSERT(LIST_EMPTY(&wl->wl_bufs)); |
738 | KASSERT(wl->wl_dealloccnt == 0); | | 778 | KASSERT(wl->wl_dealloccnt == 0); |
739 | KASSERT(SIMPLEQ_EMPTY(&wl->wl_entries)); | | 779 | KASSERT(SIMPLEQ_EMPTY(&wl->wl_entries)); |
740 | KASSERT(wl->wl_inohashcnt == 0); | | 780 | KASSERT(wl->wl_inohashcnt == 0); |
741 | KASSERT(TAILQ_EMPTY(&wl->wl_dealloclist)); | | 781 | KASSERT(TAILQ_EMPTY(&wl->wl_dealloclist)); |
742 | KASSERT(wl->wl_dealloccnt == 0); | | 782 | KASSERT(wl->wl_dealloccnt == 0); |
743 | | | 783 | |
744 | wapbl_free(wl->wl_wc_scratch, wl->wl_wc_header->wc_len); | | 784 | wapbl_free(wl->wl_wc_scratch, wl->wl_wc_header->wc_len); |
745 | wapbl_free(wl->wl_wc_header, wl->wl_wc_header->wc_len); | | 785 | wapbl_free(wl->wl_wc_header, wl->wl_wc_header->wc_len); |
746 | wapbl_free(wl->wl_buffer, MAXPHYS); | | 786 | wapbl_free(wl->wl_buffer, MAXPHYS); |
747 | wapbl_inodetrk_free(wl); | | 787 | wapbl_inodetrk_free(wl); |
748 | | | 788 | |
| | | 789 | wapbl_evcnt_free(wl); |
| | | 790 | |
749 | cv_destroy(&wl->wl_reclaimable_cv); | | 791 | cv_destroy(&wl->wl_reclaimable_cv); |
750 | mutex_destroy(&wl->wl_mtx); | | 792 | mutex_destroy(&wl->wl_mtx); |
751 | rw_destroy(&wl->wl_rwlock); | | 793 | rw_destroy(&wl->wl_rwlock); |
752 | wapbl_free(wl, sizeof(*wl)); | | 794 | wapbl_free(wl, sizeof(*wl)); |
753 | | | 795 | |
754 | return 0; | | 796 | return 0; |
755 | } | | 797 | } |
756 | | | 798 | |
757 | /****************************************************************/ | | 799 | /****************************************************************/ |
758 | /* | | 800 | /* |
759 | * Unbuffered disk I/O | | 801 | * Unbuffered disk I/O |
760 | */ | | 802 | */ |
761 | | | 803 | |
| @@ -848,26 +890,28 @@ wapbl_read(void *data, size_t len, struc | | | @@ -848,26 +890,28 @@ wapbl_read(void *data, size_t len, struc |
848 | */ | | 890 | */ |
849 | static int | | 891 | static int |
850 | wapbl_buffered_flush(struct wapbl *wl) | | 892 | wapbl_buffered_flush(struct wapbl *wl) |
851 | { | | 893 | { |
852 | int error; | | 894 | int error; |
853 | | | 895 | |
854 | if (wl->wl_buffer_used == 0) | | 896 | if (wl->wl_buffer_used == 0) |
855 | return 0; | | 897 | return 0; |
856 | | | 898 | |
857 | error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used, | | 899 | error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used, |
858 | wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE); | | 900 | wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE); |
859 | wl->wl_buffer_used = 0; | | 901 | wl->wl_buffer_used = 0; |
860 | | | 902 | |
| | | 903 | wl->wl_ev_journalwrite.ev_count++; |
| | | 904 | |
861 | return error; | | 905 | return error; |
862 | } | | 906 | } |
863 | | | 907 | |
864 | /* | | 908 | /* |
865 | * wapbl_buffered_write(data, len, wl, pbn) | | 909 | * wapbl_buffered_write(data, len, wl, pbn) |
866 | * | | 910 | * |
867 | * Write len bytes from data to physical block pbn on | | 911 | * Write len bytes from data to physical block pbn on |
868 | * wl->wl_devvp. The write may not complete until | | 912 | * wl->wl_devvp. The write may not complete until |
869 | * wapbl_buffered_flush. | | 913 | * wapbl_buffered_flush. |
870 | */ | | 914 | */ |
871 | static int | | 915 | static int |
872 | wapbl_buffered_write(void *data, size_t len, struct wapbl *wl, daddr_t pbn) | | 916 | wapbl_buffered_write(void *data, size_t len, struct wapbl *wl, daddr_t pbn) |
873 | { | | 917 | { |
| @@ -1461,26 +1505,27 @@ wapbl_biodone(struct buf *bp) | | | @@ -1461,26 +1505,27 @@ wapbl_biodone(struct buf *bp) |
1461 | */ | | 1505 | */ |
1462 | brelse(bp, 0); | | 1506 | brelse(bp, 0); |
1463 | | | 1507 | |
1464 | mutex_enter(&wl->wl_mtx); | | 1508 | mutex_enter(&wl->wl_mtx); |
1465 | | | 1509 | |
1466 | KASSERT(we->we_bufcount > 0); | | 1510 | KASSERT(we->we_bufcount > 0); |
1467 | we->we_bufcount--; | | 1511 | we->we_bufcount--; |
1468 | #ifdef WAPBL_DEBUG_BUFBYTES | | 1512 | #ifdef WAPBL_DEBUG_BUFBYTES |
1469 | KASSERT(we->we_unsynced_bufbytes >= bufsize); | | 1513 | KASSERT(we->we_unsynced_bufbytes >= bufsize); |
1470 | we->we_unsynced_bufbytes -= bufsize; | | 1514 | we->we_unsynced_bufbytes -= bufsize; |
1471 | KASSERT(wl->wl_unsynced_bufbytes >= bufsize); | | 1515 | KASSERT(wl->wl_unsynced_bufbytes >= bufsize); |
1472 | wl->wl_unsynced_bufbytes -= bufsize; | | 1516 | wl->wl_unsynced_bufbytes -= bufsize; |
1473 | #endif | | 1517 | #endif |
| | | 1518 | wl->wl_ev_metawrite.ev_count++; |
1474 | | | 1519 | |
1475 | /* | | 1520 | /* |
1476 | * If the current transaction can be reclaimed, start | | 1521 | * If the current transaction can be reclaimed, start |
1477 | * at the beginning and reclaim any consecutive reclaimable | | 1522 | * at the beginning and reclaim any consecutive reclaimable |
1478 | * transactions. If we successfully reclaim anything, | | 1523 | * transactions. If we successfully reclaim anything, |
1479 | * then wakeup anyone waiting for the reclaim. | | 1524 | * then wakeup anyone waiting for the reclaim. |
1480 | */ | | 1525 | */ |
1481 | if (we->we_bufcount == 0) { | | 1526 | if (we->we_bufcount == 0) { |
1482 | size_t delta = 0; | | 1527 | size_t delta = 0; |
1483 | int errcnt = 0; | | 1528 | int errcnt = 0; |
1484 | #ifdef WAPBL_DEBUG_BUFBYTES | | 1529 | #ifdef WAPBL_DEBUG_BUFBYTES |
1485 | KDASSERT(we->we_unsynced_bufbytes == 0); | | 1530 | KDASSERT(we->we_unsynced_bufbytes == 0); |
1486 | #endif | | 1531 | #endif |
| @@ -2169,26 +2214,29 @@ wapbl_cache_sync(struct wapbl *wl, const | | | @@ -2169,26 +2214,29 @@ wapbl_cache_sync(struct wapbl *wl, const |
2169 | "returned %d\n", (uintmax_t)wl->wl_devvp->v_rdev, error)); | | 2214 | "returned %d\n", (uintmax_t)wl->wl_devvp->v_rdev, error)); |
2170 | } | | 2215 | } |
2171 | if (verbose) { | | 2216 | if (verbose) { |
2172 | struct bintime d; | | 2217 | struct bintime d; |
2173 | struct timespec ts; | | 2218 | struct timespec ts; |
2174 | | | 2219 | |
2175 | bintime(&d); | | 2220 | bintime(&d); |
2176 | bintime_sub(&d, &start_time); | | 2221 | bintime_sub(&d, &start_time); |
2177 | bintime2timespec(&d, &ts); | | 2222 | bintime2timespec(&d, &ts); |
2178 | printf("wapbl_cache_sync: %s: dev 0x%jx %ju.%09lu\n", | | 2223 | printf("wapbl_cache_sync: %s: dev 0x%jx %ju.%09lu\n", |
2179 | msg, (uintmax_t)wl->wl_devvp->v_rdev, | | 2224 | msg, (uintmax_t)wl->wl_devvp->v_rdev, |
2180 | (uintmax_t)ts.tv_sec, ts.tv_nsec); | | 2225 | (uintmax_t)ts.tv_sec, ts.tv_nsec); |
2181 | } | | 2226 | } |
| | | 2227 | |
| | | 2228 | wl->wl_ev_cacheflush.ev_count++; |
| | | 2229 | |
2182 | return error; | | 2230 | return error; |
2183 | } | | 2231 | } |
2184 | | | 2232 | |
2185 | /* | | 2233 | /* |
2186 | * wapbl_write_commit(wl, head, tail) | | 2234 | * wapbl_write_commit(wl, head, tail) |
2187 | * | | 2235 | * |
2188 | * Issue a disk cache sync to wait for all pending writes to the | | 2236 | * Issue a disk cache sync to wait for all pending writes to the |
2189 | * log to complete, and then synchronously commit the current | | 2237 | * log to complete, and then synchronously commit the current |
2190 | * circular queue head and tail to the log, in the next of two | | 2238 | * circular queue head and tail to the log, in the next of two |
2191 | * locations for commit headers on disk. | | 2239 | * locations for commit headers on disk. |
2192 | * | | 2240 | * |
2193 | * Increment the generation number. If the generation number | | 2241 | * Increment the generation number. If the generation number |
2194 | * rolls over to zero, then a subsequent commit would appear to | | 2242 | * rolls over to zero, then a subsequent commit would appear to |
| @@ -2259,26 +2307,29 @@ wapbl_write_commit(struct wapbl *wl, off | | | @@ -2259,26 +2307,29 @@ wapbl_write_commit(struct wapbl *wl, off |
2259 | * This handles initialization and generation number rollover | | 2307 | * This handles initialization and generation number rollover |
2260 | */ | | 2308 | */ |
2261 | if (wc->wc_generation++ == 0) { | | 2309 | if (wc->wc_generation++ == 0) { |
2262 | error = wapbl_write_commit(wl, head, tail); | | 2310 | error = wapbl_write_commit(wl, head, tail); |
2263 | /* | | 2311 | /* |
2264 | * This panic should be able to be removed if we do the | | 2312 | * This panic should be able to be removed if we do the |
2265 | * zero'ing mentioned above, and we are certain to roll | | 2313 | * zero'ing mentioned above, and we are certain to roll |
2266 | * back generation number on failure. | | 2314 | * back generation number on failure. |
2267 | */ | | 2315 | */ |
2268 | if (error) | | 2316 | if (error) |
2269 | panic("wapbl_write_commit: error writing duplicate " | | 2317 | panic("wapbl_write_commit: error writing duplicate " |
2270 | "log header: %d", error); | | 2318 | "log header: %d", error); |
2271 | } | | 2319 | } |
| | | 2320 | |
| | | 2321 | wl->wl_ev_commit.ev_count++; |
| | | 2322 | |
2272 | return 0; | | 2323 | return 0; |
2273 | } | | 2324 | } |
2274 | | | 2325 | |
2275 | /* | | 2326 | /* |
2276 | * wapbl_write_blocks(wl, offp) | | 2327 | * wapbl_write_blocks(wl, offp) |
2277 | * | | 2328 | * |
2278 | * Write all pending physical blocks in the current transaction | | 2329 | * Write all pending physical blocks in the current transaction |
2279 | * from wapbl_add_buf to the log on disk, adding to the circular | | 2330 | * from wapbl_add_buf to the log on disk, adding to the circular |
2280 | * queue head at byte offset *offp, and returning the new head's | | 2331 | * queue head at byte offset *offp, and returning the new head's |
2281 | * byte offset in *offp. | | 2332 | * byte offset in *offp. |
2282 | */ | | 2333 | */ |
2283 | static int | | 2334 | static int |
2284 | wapbl_write_blocks(struct wapbl *wl, off_t *offp) | | 2335 | wapbl_write_blocks(struct wapbl *wl, off_t *offp) |