version 1.51.2.1, 2012/05/07 03:01:13 |
version 1.51.2.2, 2013/01/02 23:23:15 |
|
|
|
|
SIMPLEQ_HEAD(, wapbl_entry) wl_entries; /* On disk transaction |
SIMPLEQ_HEAD(, wapbl_entry) wl_entries; /* On disk transaction |
accounting */ |
accounting */ |
|
|
|
u_char *wl_buffer; /* l: buffer for wapbl_buffered_write() */ |
|
daddr_t wl_buffer_dblk; /* l: buffer disk block address */ |
|
size_t wl_buffer_used; /* l: buffer current use */ |
}; |
}; |
|
|
#ifdef WAPBL_DEBUG_PRINT |
#ifdef WAPBL_DEBUG_PRINT |
Line 489 wapbl_start(struct wapbl ** wlp, struct |
|
Line 493 wapbl_start(struct wapbl ** wlp, struct |
|
wl->wl_dealloclens = wapbl_alloc(sizeof(*wl->wl_dealloclens) * |
wl->wl_dealloclens = wapbl_alloc(sizeof(*wl->wl_dealloclens) * |
wl->wl_dealloclim); |
wl->wl_dealloclim); |
|
|
|
wl->wl_buffer = wapbl_alloc(MAXPHYS); |
|
wl->wl_buffer_used = 0; |
|
|
wapbl_inodetrk_init(wl, WAPBL_INODETRK_SIZE); |
wapbl_inodetrk_init(wl, WAPBL_INODETRK_SIZE); |
|
|
/* Initialize the commit header */ |
/* Initialize the commit header */ |
Line 537 wapbl_start(struct wapbl ** wlp, struct |
|
Line 544 wapbl_start(struct wapbl ** wlp, struct |
|
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim); |
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim); |
wapbl_free(wl->wl_dealloclens, |
wapbl_free(wl->wl_dealloclens, |
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim); |
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim); |
|
wapbl_free(wl->wl_buffer, MAXPHYS); |
wapbl_inodetrk_free(wl); |
wapbl_inodetrk_free(wl); |
wapbl_free(wl, sizeof(*wl)); |
wapbl_free(wl, sizeof(*wl)); |
|
|
Line 716 wapbl_stop(struct wapbl *wl, int force) |
|
Line 724 wapbl_stop(struct wapbl *wl, int force) |
|
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim); |
sizeof(*wl->wl_deallocblks) * wl->wl_dealloclim); |
wapbl_free(wl->wl_dealloclens, |
wapbl_free(wl->wl_dealloclens, |
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim); |
sizeof(*wl->wl_dealloclens) * wl->wl_dealloclim); |
|
wapbl_free(wl->wl_buffer, MAXPHYS); |
wapbl_inodetrk_free(wl); |
wapbl_inodetrk_free(wl); |
|
|
cv_destroy(&wl->wl_reclaimable_cv); |
cv_destroy(&wl->wl_reclaimable_cv); |
Line 791 wapbl_read(void *data, size_t len, struc |
|
Line 800 wapbl_read(void *data, size_t len, struc |
|
} |
} |
|
|
/* |
/* |
|
* Flush buffered data if any. |
|
*/ |
|
static int |
|
wapbl_buffered_flush(struct wapbl *wl) |
|
{ |
|
int error; |
|
|
|
if (wl->wl_buffer_used == 0) |
|
return 0; |
|
|
|
error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used, |
|
wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE); |
|
wl->wl_buffer_used = 0; |
|
|
|
return error; |
|
} |
|
|
|
/* |
|
* Write data to the log. |
|
* Try to coalesce writes and emit MAXPHYS aligned blocks. |
|
*/ |
|
static int |
|
wapbl_buffered_write(void *data, size_t len, struct wapbl *wl, daddr_t pbn) |
|
{ |
|
int error; |
|
size_t resid; |
|
|
|
/* |
|
* If not adjacent to buffered data flush first. Disk block |
|
* address is always valid for non-empty buffer. |
|
*/ |
|
if (wl->wl_buffer_used > 0 && |
|
pbn != wl->wl_buffer_dblk + btodb(wl->wl_buffer_used)) { |
|
error = wapbl_buffered_flush(wl); |
|
if (error) |
|
return error; |
|
} |
|
/* |
|
* If this write goes to an empty buffer we have to |
|
* save the disk block address first. |
|
*/ |
|
if (wl->wl_buffer_used == 0) |
|
wl->wl_buffer_dblk = pbn; |
|
/* |
|
* Remaining space so this buffer ends on a MAXPHYS boundary. |
|
* |
|
* Cannot become less or equal zero as the buffer would have been |
|
* flushed on the last call then. |
|
*/ |
|
resid = MAXPHYS - dbtob(wl->wl_buffer_dblk % btodb(MAXPHYS)) - |
|
wl->wl_buffer_used; |
|
KASSERT(resid > 0); |
|
KASSERT(dbtob(btodb(resid)) == resid); |
|
if (len >= resid) { |
|
memcpy(wl->wl_buffer + wl->wl_buffer_used, data, resid); |
|
wl->wl_buffer_used += resid; |
|
error = wapbl_doio(wl->wl_buffer, wl->wl_buffer_used, |
|
wl->wl_devvp, wl->wl_buffer_dblk, B_WRITE); |
|
data = (uint8_t *)data + resid; |
|
len -= resid; |
|
wl->wl_buffer_dblk = pbn + btodb(resid); |
|
wl->wl_buffer_used = 0; |
|
if (error) |
|
return error; |
|
} |
|
KASSERT(len < MAXPHYS); |
|
if (len > 0) { |
|
memcpy(wl->wl_buffer + wl->wl_buffer_used, data, len); |
|
wl->wl_buffer_used += len; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
/* |
* Off is byte offset returns new offset for next write |
* Off is byte offset returns new offset for next write |
* handles log wraparound |
* handles log wraparound |
*/ |
*/ |
Line 813 wapbl_circ_write(struct wapbl *wl, void |
|
Line 897 wapbl_circ_write(struct wapbl *wl, void |
|
#ifdef _KERNEL |
#ifdef _KERNEL |
pbn = btodb(pbn << wl->wl_log_dev_bshift); |
pbn = btodb(pbn << wl->wl_log_dev_bshift); |
#endif |
#endif |
error = wapbl_write(data, slen, wl->wl_devvp, pbn); |
error = wapbl_buffered_write(data, slen, wl, pbn); |
if (error) |
if (error) |
return error; |
return error; |
data = (uint8_t *)data + slen; |
data = (uint8_t *)data + slen; |
Line 824 wapbl_circ_write(struct wapbl *wl, void |
|
Line 908 wapbl_circ_write(struct wapbl *wl, void |
|
#ifdef _KERNEL |
#ifdef _KERNEL |
pbn = btodb(pbn << wl->wl_log_dev_bshift); |
pbn = btodb(pbn << wl->wl_log_dev_bshift); |
#endif |
#endif |
error = wapbl_write(data, len, wl->wl_devvp, pbn); |
error = wapbl_buffered_write(data, len, wl, pbn); |
if (error) |
if (error) |
return error; |
return error; |
off += len; |
off += len; |
Line 1224 wapbl_biodone(struct buf *bp) |
|
Line 1308 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 = we->we_wapbl; |
|
#ifdef WAPBL_DEBUG_BUFBYTES |
|
const int bufsize = bp->b_bufsize; |
|
#endif |
|
|
/* |
/* |
* Handle possible flushing of buffers after log has been |
* Handle possible flushing of buffers after log has been |
Line 1233 wapbl_biodone(struct buf *bp) |
|
Line 1320 wapbl_biodone(struct buf *bp) |
|
KASSERT(we->we_bufcount > 0); |
KASSERT(we->we_bufcount > 0); |
we->we_bufcount--; |
we->we_bufcount--; |
#ifdef WAPBL_DEBUG_BUFBYTES |
#ifdef WAPBL_DEBUG_BUFBYTES |
KASSERT(we->we_unsynced_bufbytes >= bp->b_bufsize); |
KASSERT(we->we_unsynced_bufbytes >= bufsize); |
we->we_unsynced_bufbytes -= bp->b_bufsize; |
we->we_unsynced_bufbytes -= bufsize; |
#endif |
#endif |
|
|
if (we->we_bufcount == 0) { |
if (we->we_bufcount == 0) { |
Line 1300 wapbl_biodone(struct buf *bp) |
|
Line 1387 wapbl_biodone(struct buf *bp) |
|
#endif |
#endif |
} |
} |
|
|
|
/* |
|
* Release the buffer here. wapbl_flush() may wait for the |
|
* log to become empty and we better unbusy the buffer before |
|
* wapbl_flush() returns. |
|
*/ |
|
brelse(bp, 0); |
|
|
mutex_enter(&wl->wl_mtx); |
mutex_enter(&wl->wl_mtx); |
|
|
KASSERT(we->we_bufcount > 0); |
KASSERT(we->we_bufcount > 0); |
we->we_bufcount--; |
we->we_bufcount--; |
#ifdef WAPBL_DEBUG_BUFBYTES |
#ifdef WAPBL_DEBUG_BUFBYTES |
KASSERT(we->we_unsynced_bufbytes >= bp->b_bufsize); |
KASSERT(we->we_unsynced_bufbytes >= bufsize); |
we->we_unsynced_bufbytes -= bp->b_bufsize; |
we->we_unsynced_bufbytes -= bufsize; |
KASSERT(wl->wl_unsynced_bufbytes >= bp->b_bufsize); |
KASSERT(wl->wl_unsynced_bufbytes >= bufsize); |
wl->wl_unsynced_bufbytes -= bp->b_bufsize; |
wl->wl_unsynced_bufbytes -= bufsize; |
#endif |
#endif |
|
|
/* |
/* |
Line 1345 wapbl_biodone(struct buf *bp) |
|
Line 1439 wapbl_biodone(struct buf *bp) |
|
} |
} |
|
|
mutex_exit(&wl->wl_mtx); |
mutex_exit(&wl->wl_mtx); |
brelse(bp, 0); |
|
} |
} |
|
|
/* |
/* |
Line 1958 wapbl_write_commit(struct wapbl *wl, off |
|
Line 2051 wapbl_write_commit(struct wapbl *wl, off |
|
int error; |
int error; |
daddr_t pbn; |
daddr_t pbn; |
|
|
|
error = wapbl_buffered_flush(wl); |
|
if (error) |
|
return error; |
/* |
/* |
* flush disk cache to ensure that blocks we've written are actually |
* flush disk cache to ensure that blocks we've written are actually |
* written to the stable storage before the commit header. |
* written to the stable storage before the commit header. |
Line 1989 wapbl_write_commit(struct wapbl *wl, off |
|
Line 2085 wapbl_write_commit(struct wapbl *wl, off |
|
#ifdef _KERNEL |
#ifdef _KERNEL |
pbn = btodb(pbn << wc->wc_log_dev_bshift); |
pbn = btodb(pbn << wc->wc_log_dev_bshift); |
#endif |
#endif |
error = wapbl_write(wc, wc->wc_len, wl->wl_devvp, pbn); |
error = wapbl_buffered_write(wc, wc->wc_len, wl, pbn); |
|
if (error) |
|
return error; |
|
error = wapbl_buffered_flush(wl); |
if (error) |
if (error) |
return error; |
return error; |
|
|