version 1.101, 2017/12/02 17:29:55 |
version 1.101.4.3, 2020/04/21 18:42:42 |
Line 68 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 68 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define wapbl_free(a, s) kmem_free((a), (s)) |
#define wapbl_free(a, s) kmem_free((a), (s)) |
#define wapbl_calloc(n, s) kmem_zalloc((n)*(s), KM_SLEEP) |
#define wapbl_calloc(n, s) kmem_zalloc((n)*(s), KM_SLEEP) |
|
|
static struct sysctllog *wapbl_sysctl; |
|
static int wapbl_flush_disk_cache = 1; |
static int wapbl_flush_disk_cache = 1; |
static int wapbl_verbose_commit = 0; |
static int wapbl_verbose_commit = 0; |
static int wapbl_allow_dpofua = 0; /* switched off by default for now */ |
static int wapbl_allow_dpofua = 0; /* switched off by default for now */ |
|
|
u_long wl_inohashmask; |
u_long wl_inohashmask; |
int wl_inohashcnt; |
int wl_inohashcnt; |
|
|
SIMPLEQ_HEAD(, wapbl_entry) wl_entries; /* On disk transaction |
SIMPLEQ_HEAD(, wapbl_entry) wl_entries; /* m: On disk transaction |
accounting */ |
accounting */ |
|
|
/* buffers for wapbl_buffered_write() */ |
/* buffers for wapbl_buffered_write() */ |
Line 301 int wapbl_replay_verify(struct wapbl_rep |
|
Line 300 int wapbl_replay_verify(struct wapbl_rep |
|
|
|
static int wapbl_replay_isopen1(struct wapbl_replay *); |
static int wapbl_replay_isopen1(struct wapbl_replay *); |
|
|
struct wapbl_ops wapbl_ops = { |
const struct wapbl_ops wapbl_ops = { |
.wo_wapbl_discard = wapbl_discard, |
.wo_wapbl_discard = wapbl_discard, |
.wo_wapbl_replay_isopen = wapbl_replay_isopen1, |
.wo_wapbl_replay_isopen = wapbl_replay_isopen1, |
.wo_wapbl_replay_can_read = wapbl_replay_can_read, |
.wo_wapbl_replay_can_read = wapbl_replay_can_read, |
Line 312 struct wapbl_ops wapbl_ops = { |
|
Line 311 struct wapbl_ops wapbl_ops = { |
|
.wo_wapbl_begin = wapbl_begin, |
.wo_wapbl_begin = wapbl_begin, |
.wo_wapbl_end = wapbl_end, |
.wo_wapbl_end = wapbl_end, |
.wo_wapbl_junlock_assert= wapbl_junlock_assert, |
.wo_wapbl_junlock_assert= wapbl_junlock_assert, |
|
.wo_wapbl_jlock_assert = wapbl_jlock_assert, |
|
|
/* XXX: the following is only used to say "this is a wapbl buf" */ |
/* XXX: the following is only used to say "this is a wapbl buf" */ |
.wo_wapbl_biodone = wapbl_biodone, |
.wo_wapbl_biodone = wapbl_biodone, |
}; |
}; |
|
|
static int |
SYSCTL_SETUP(wapbl_sysctl_init, "wapbl sysctl") |
wapbl_sysctl_init(void) |
|
{ |
{ |
int rv; |
int rv; |
const struct sysctlnode *rnode, *cnode; |
const struct sysctlnode *rnode, *cnode; |
|
|
wapbl_sysctl = NULL; |
rv = sysctl_createv(clog, 0, NULL, &rnode, |
|
|
rv = sysctl_createv(&wapbl_sysctl, 0, NULL, &rnode, |
|
CTLFLAG_PERMANENT, |
CTLFLAG_PERMANENT, |
CTLTYPE_NODE, "wapbl", |
CTLTYPE_NODE, "wapbl", |
SYSCTL_DESCR("WAPBL journaling options"), |
SYSCTL_DESCR("WAPBL journaling options"), |
NULL, 0, NULL, 0, |
NULL, 0, NULL, 0, |
CTL_VFS, CTL_CREATE, CTL_EOL); |
CTL_VFS, CTL_CREATE, CTL_EOL); |
if (rv) |
if (rv) |
return rv; |
return; |
|
|
rv = sysctl_createv(&wapbl_sysctl, 0, &rnode, &cnode, |
rv = sysctl_createv(clog, 0, &rnode, &cnode, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLTYPE_INT, "flush_disk_cache", |
CTLTYPE_INT, "flush_disk_cache", |
SYSCTL_DESCR("flush disk cache"), |
SYSCTL_DESCR("flush disk cache"), |
NULL, 0, &wapbl_flush_disk_cache, 0, |
NULL, 0, &wapbl_flush_disk_cache, 0, |
CTL_CREATE, CTL_EOL); |
CTL_CREATE, CTL_EOL); |
if (rv) |
if (rv) |
return rv; |
return; |
|
|
rv = sysctl_createv(&wapbl_sysctl, 0, &rnode, &cnode, |
rv = sysctl_createv(clog, 0, &rnode, &cnode, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLTYPE_INT, "verbose_commit", |
CTLTYPE_INT, "verbose_commit", |
SYSCTL_DESCR("show time and size of wapbl log commits"), |
SYSCTL_DESCR("show time and size of wapbl log commits"), |
NULL, 0, &wapbl_verbose_commit, 0, |
NULL, 0, &wapbl_verbose_commit, 0, |
CTL_CREATE, CTL_EOL); |
CTL_CREATE, CTL_EOL); |
if (rv) |
if (rv) |
return rv; |
return; |
|
|
rv = sysctl_createv(&wapbl_sysctl, 0, &rnode, &cnode, |
rv = sysctl_createv(clog, 0, &rnode, &cnode, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLTYPE_INT, "allow_dpofua", |
CTLTYPE_INT, "allow_dpofua", |
SYSCTL_DESCR("allow use of FUA/DPO instead of cash flush if available"), |
SYSCTL_DESCR("allow use of FUA/DPO instead of cache flush if available"), |
NULL, 0, &wapbl_allow_dpofua, 0, |
NULL, 0, &wapbl_allow_dpofua, 0, |
CTL_CREATE, CTL_EOL); |
CTL_CREATE, CTL_EOL); |
if (rv) |
if (rv) |
return rv; |
return; |
|
|
rv = sysctl_createv(&wapbl_sysctl, 0, &rnode, &cnode, |
rv = sysctl_createv(clog, 0, &rnode, &cnode, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLTYPE_INT, "journal_iobufs", |
CTLTYPE_INT, "journal_iobufs", |
SYSCTL_DESCR("count of bufs used for journal I/O (max async count)"), |
SYSCTL_DESCR("count of bufs used for journal I/O (max async count)"), |
NULL, 0, &wapbl_journal_iobufs, 0, |
NULL, 0, &wapbl_journal_iobufs, 0, |
CTL_CREATE, CTL_EOL); |
CTL_CREATE, CTL_EOL); |
if (rv) |
if (rv) |
return rv; |
return; |
|
|
return rv; |
return; |
} |
} |
|
|
static void |
static void |
Line 381 wapbl_init(void) |
|
Line 378 wapbl_init(void) |
|
"wapblentrypl", &pool_allocator_kmem, IPL_VM); |
"wapblentrypl", &pool_allocator_kmem, IPL_VM); |
pool_init(&wapbl_dealloc_pool, sizeof(struct wapbl_dealloc), 0, 0, 0, |
pool_init(&wapbl_dealloc_pool, sizeof(struct wapbl_dealloc), 0, 0, 0, |
"wapbldealloc", &pool_allocator_nointr, IPL_NONE); |
"wapbldealloc", &pool_allocator_nointr, IPL_NONE); |
|
|
wapbl_sysctl_init(); |
|
} |
} |
|
|
static int |
static int |
wapbl_fini(void) |
wapbl_fini(void) |
{ |
{ |
|
|
if (wapbl_sysctl != NULL) |
|
sysctl_teardown(&wapbl_sysctl); |
|
|
|
pool_destroy(&wapbl_dealloc_pool); |
pool_destroy(&wapbl_dealloc_pool); |
pool_destroy(&wapbl_entry_pool); |
pool_destroy(&wapbl_entry_pool); |
|
|
Line 785 wapbl_discard(struct wapbl *wl) |
|
Line 777 wapbl_discard(struct wapbl *wl) |
|
mutex_enter(&wl->wl_mtx); |
mutex_enter(&wl->wl_mtx); |
while ((bp = TAILQ_FIRST(&wl->wl_bufs)) != NULL) { |
while ((bp = TAILQ_FIRST(&wl->wl_bufs)) != NULL) { |
if (bbusy(bp, 0, 0, &wl->wl_mtx) == 0) { |
if (bbusy(bp, 0, 0, &wl->wl_mtx) == 0) { |
|
KASSERT(bp->b_flags & B_LOCKED); |
|
KASSERT(bp->b_oflags & BO_DELWRI); |
/* |
/* |
|
* Buffer is already on BQ_LOCKED queue. |
* The buffer will be unlocked and |
* The buffer will be unlocked and |
* removed from the transaction in brelse |
* removed from the transaction in brelsel() |
*/ |
*/ |
mutex_exit(&wl->wl_mtx); |
mutex_exit(&wl->wl_mtx); |
brelsel(bp, 0); |
bremfree(bp); |
|
brelsel(bp, BC_INVAL); |
mutex_enter(&wl->wl_mtx); |
mutex_enter(&wl->wl_mtx); |
} |
} |
} |
} |
mutex_exit(&wl->wl_mtx); |
|
mutex_exit(&bufcache_lock); |
|
|
|
/* |
/* |
* Remove references to this wl from wl_entries, free any which |
* Remove references to this wl from wl_entries, free any which |
* no longer have buffers, others will be freed in wapbl_biodone |
* no longer have buffers, others will be freed in wapbl_biodone() |
* when they no longer have any buffers. |
* when they no longer have any buffers. |
*/ |
*/ |
while ((we = SIMPLEQ_FIRST(&wl->wl_entries)) != NULL) { |
while ((we = SIMPLEQ_FIRST(&wl->wl_entries)) != NULL) { |
Line 815 wapbl_discard(struct wapbl *wl) |
|
Line 809 wapbl_discard(struct wapbl *wl) |
|
} |
} |
} |
} |
|
|
|
mutex_exit(&wl->wl_mtx); |
|
mutex_exit(&bufcache_lock); |
|
|
/* Discard list of deallocs */ |
/* Discard list of deallocs */ |
while ((wd = TAILQ_FIRST(&wl->wl_dealloclist)) != NULL) |
while ((wd = TAILQ_FIRST(&wl->wl_dealloclist)) != NULL) |
wapbl_deallocation_free(wl, wd, true); |
wapbl_deallocation_free(wl, wd, true); |
Line 921 wapbl_doio(void *data, size_t len, struc |
|
Line 918 wapbl_doio(void *data, size_t len, struc |
|
|
|
bp = getiobuf(devvp, true); |
bp = getiobuf(devvp, true); |
bp->b_flags = flags; |
bp->b_flags = flags; |
bp->b_cflags = BC_BUSY; /* mandatory, asserted by biowait() */ |
bp->b_cflags |= BC_BUSY; /* mandatory, asserted by biowait() */ |
bp->b_dev = devvp->v_rdev; |
bp->b_dev = devvp->v_rdev; |
bp->b_data = data; |
bp->b_data = data; |
bp->b_bufsize = bp->b_resid = bp->b_bcount = len; |
bp->b_bufsize = bp->b_resid = bp->b_bcount = len; |
Line 996 wapbl_buffered_write_async(struct wapbl |
|
Line 993 wapbl_buffered_write_async(struct wapbl |
|
TAILQ_REMOVE(&wl->wl_iobufs, bp, b_wapbllist); |
TAILQ_REMOVE(&wl->wl_iobufs, bp, b_wapbllist); |
|
|
bp->b_flags |= B_WRITE; |
bp->b_flags |= B_WRITE; |
bp->b_cflags = BC_BUSY; /* mandatory, asserted by biowait() */ |
bp->b_cflags |= BC_BUSY; /* mandatory, asserted by biowait() */ |
bp->b_oflags = 0; |
bp->b_oflags = 0; |
bp->b_bcount = bp->b_resid; |
bp->b_bcount = bp->b_resid; |
BIO_SETPRIO(bp, BPRIO_TIMECRITICAL); |
BIO_SETPRIO(bp, BPRIO_TIMECRITICAL); |
|
|
wapbl_biodone(struct buf *bp) |
wapbl_biodone(struct buf *bp) |
{ |
{ |
struct wapbl_entry *we = bp->b_private; |
struct wapbl_entry *we = bp->b_private; |
struct wapbl *wl = we->we_wapbl; |
struct wapbl *wl; |
#ifdef WAPBL_DEBUG_BUFBYTES |
#ifdef WAPBL_DEBUG_BUFBYTES |
const int bufsize = bp->b_bufsize; |
const int bufsize = bp->b_bufsize; |
#endif |
#endif |
|
|
|
mutex_enter(&bufcache_lock); |
|
wl = we->we_wapbl; |
|
mutex_exit(&bufcache_lock); |
|
|
/* |
/* |
* Handle possible flushing of buffers after log has been |
* Handle possible flushing of buffers after log has been |
* decomissioned. |
* decomissioned. |