aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zil.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zil.c')
-rw-r--r--module/zfs/zil.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/module/zfs/zil.c b/module/zfs/zil.c
index a11886136..37fb792f5 100644
--- a/module/zfs/zil.c
+++ b/module/zfs/zil.c
@@ -522,6 +522,7 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
lr_t *lr = (lr_t *)lrp;
reclen = lr->lrc_reclen;
ASSERT3U(reclen, >=, sizeof (lr_t));
+ ASSERT3U(reclen, <=, end - lrp);
if (lr->lrc_seq > claim_lr_seq) {
arc_buf_destroy(abuf, &abuf);
goto done;
@@ -604,7 +605,7 @@ zil_claim_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t first_txg)
lr_write_t *lr = (lr_write_t *)lrc;
int error;
- ASSERT(lrc->lrc_txtype == TX_WRITE);
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
/*
* If the block is not readable, don't claim it. This can happen
@@ -631,7 +632,9 @@ zil_claim_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx)
spa_t *spa;
uint_t ii;
- ASSERT(lrc->lrc_txtype == TX_CLONE_RANGE);
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lrc->lrc_reclen, >=, offsetof(lr_clone_range_t,
+ lr_bps[lr->lr_nbps]));
if (tx == NULL) {
return (0);
@@ -691,7 +694,7 @@ zil_free_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t claim_txg)
lr_write_t *lr = (lr_write_t *)lrc;
blkptr_t *bp = &lr->lr_blkptr;
- ASSERT(lrc->lrc_txtype == TX_WRITE);
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
/*
* If we previously claimed it, we need to free it.
@@ -712,7 +715,9 @@ zil_free_clone_range(zilog_t *zilog, const lr_t *lrc, void *tx)
spa_t *spa;
uint_t ii;
- ASSERT(lrc->lrc_txtype == TX_CLONE_RANGE);
+ ASSERT3U(lrc->lrc_reclen, >=, sizeof (*lr));
+ ASSERT3U(lrc->lrc_reclen, >=, offsetof(lr_clone_range_t,
+ lr_bps[lr->lr_nbps]));
if (tx == NULL) {
return (0);
@@ -1794,6 +1799,7 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
itx = list_next(&lwb->lwb_itxs, itx))
zil_lwb_commit(zilog, lwb, itx);
lwb->lwb_nused = lwb->lwb_nfilled;
+ ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_nmax);
lwb->lwb_root_zio = zio_root(spa, zil_lwb_flush_vdevs_done, lwb,
ZIO_FLAG_CANFAIL);
@@ -2023,13 +2029,16 @@ zil_lwb_assign(zilog_t *zilog, lwb_t *lwb, itx_t *itx, list_t *ilwbs)
return (lwb);
}
+ reclen = lr->lrc_reclen;
if (lr->lrc_txtype == TX_WRITE && itx->itx_wr_state == WR_NEED_COPY) {
+ ASSERT3U(reclen, ==, sizeof (lr_write_t));
dlen = P2ROUNDUP_TYPED(
lrw->lr_length, sizeof (uint64_t), uint64_t);
} else {
+ ASSERT3U(reclen, >=, sizeof (lr_t));
dlen = 0;
}
- reclen = lr->lrc_reclen;
+ ASSERT3U(reclen, <=, zil_max_log_data(zilog, 0));
zilog->zl_cur_used += (reclen + dlen);
cont:
@@ -2048,19 +2057,19 @@ cont:
if (lwb == NULL)
return (NULL);
lwb_sp = lwb->lwb_nmax - lwb->lwb_nused;
-
- /*
- * There must be enough space in the new, empty log block to
- * hold reclen. For WR_COPIED, we need to fit the whole
- * record in one block, and reclen is the header size + the
- * data size. For WR_NEED_COPY, we can create multiple
- * records, splitting the data into multiple blocks, so we
- * only need to fit one word of data per block; in this case
- * reclen is just the header size (no data).
- */
- ASSERT3U(reclen + MIN(dlen, sizeof (uint64_t)), <=, lwb_sp);
}
+ /*
+ * There must be enough space in the log block to hold reclen.
+ * For WR_COPIED, we need to fit the whole record in one block,
+ * and reclen is the write record header size + the data size.
+ * For WR_NEED_COPY, we can create multiple records, splitting
+ * the data into multiple blocks, so we only need to fit one
+ * word of data per block; in this case reclen is just the header
+ * size (no data).
+ */
+ ASSERT3U(reclen + MIN(dlen, sizeof (uint64_t)), <=, lwb_sp);
+
dnow = MIN(dlen, lwb_sp - reclen);
if (dlen > dnow) {
ASSERT3U(lr->lrc_txtype, ==, TX_WRITE);
@@ -2236,7 +2245,9 @@ zil_itx_create(uint64_t txtype, size_t olrsize)
size_t itxsize, lrsize;
itx_t *itx;
+ ASSERT3U(olrsize, >=, sizeof (lr_t));
lrsize = P2ROUNDUP_TYPED(olrsize, sizeof (uint64_t), size_t);
+ ASSERT3U(lrsize, >=, olrsize);
itxsize = offsetof(itx_t, itx_lr) + lrsize;
itx = zio_data_buf_alloc(itxsize);
@@ -2255,6 +2266,10 @@ zil_itx_create(uint64_t txtype, size_t olrsize)
static itx_t *
zil_itx_clone(itx_t *oitx)
{
+ ASSERT3U(oitx->itx_size, >=, sizeof (itx_t));
+ ASSERT3U(oitx->itx_size, ==,
+ offsetof(itx_t, itx_lr) + oitx->itx_lr.lrc_reclen);
+
itx_t *itx = zio_data_buf_alloc(oitx->itx_size);
memcpy(itx, oitx, oitx->itx_size);
itx->itx_callback = NULL;
@@ -2265,6 +2280,9 @@ zil_itx_clone(itx_t *oitx)
void
zil_itx_destroy(itx_t *itx)
{
+ ASSERT3U(itx->itx_size, >=, sizeof (itx_t));
+ ASSERT3U(itx->itx_lr.lrc_reclen, ==,
+ itx->itx_size - offsetof(itx_t, itx_lr));
IMPLY(itx->itx_lr.lrc_txtype == TX_COMMIT, itx->itx_callback == NULL);
IMPLY(itx->itx_callback != NULL, itx->itx_lr.lrc_txtype != TX_COMMIT);
@@ -2348,7 +2366,7 @@ void
zil_remove_async(zilog_t *zilog, uint64_t oid)
{
uint64_t otxg, txg;
- itx_async_node_t *ian;
+ itx_async_node_t *ian, ian_search;
avl_tree_t *t;
avl_index_t where;
list_t clean_list;
@@ -2375,7 +2393,8 @@ zil_remove_async(zilog_t *zilog, uint64_t oid)
* Locate the object node and append its list.
*/
t = &itxg->itxg_itxs->i_async_tree;
- ian = avl_find(t, &oid, &where);
+ ian_search.ia_foid = oid;
+ ian = avl_find(t, &ian_search, &where);
if (ian != NULL)
list_move_tail(&clean_list, &ian->ia_list);
mutex_exit(&itxg->itxg_lock);
@@ -2573,7 +2592,7 @@ void
zil_async_to_sync(zilog_t *zilog, uint64_t foid)
{
uint64_t otxg, txg;
- itx_async_node_t *ian;
+ itx_async_node_t *ian, ian_search;
avl_tree_t *t;
avl_index_t where;
@@ -2603,7 +2622,8 @@ zil_async_to_sync(zilog_t *zilog, uint64_t foid)
*/
t = &itxg->itxg_itxs->i_async_tree;
if (foid != 0) {
- ian = avl_find(t, &foid, &where);
+ ian_search.ia_foid = foid;
+ ian = avl_find(t, &ian_search, &where);
if (ian != NULL) {
list_move_tail(&itxg->itxg_itxs->i_sync_list,
&ian->ia_list);