Skip to content

Commit dcab588

Browse files
committed
ZIL: Call brt_pending_add() replaying TX_CLONE_RANGE
zil_claim_clone_range() takes references on cloned blocks before ZIL replay. Later zil_free_clone_range() drops them after replay or on dataset destroy. The total balance is neutral. It means on actual replay we must take additional references, which would stay in BRT. Without this blocks could be freed prematurely when either original file or its clone are destroyed. I've observed BRT being emptied and the feature being desctivated after ZIL replay completion, which should not have happened. With the patch I see expected stats. Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc.
1 parent 2a27fd4 commit dcab588

File tree

3 files changed

+5
-8
lines changed

3 files changed

+5
-8
lines changed

include/sys/dmu.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,8 +1086,7 @@ int dmu_offset_next(objset_t *os, uint64_t object, boolean_t hole,
10861086
int dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset,
10871087
uint64_t length, struct blkptr *bps, size_t *nbpsp);
10881088
int dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset,
1089-
uint64_t length, dmu_tx_t *tx, const struct blkptr *bps, size_t nbps,
1090-
boolean_t replay);
1089+
uint64_t length, dmu_tx_t *tx, const struct blkptr *bps, size_t nbps);
10911090

10921091
/*
10931092
* Initial setup and final teardown.

module/zfs/dmu.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,7 +2286,7 @@ dmu_read_l0_bps(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
22862286

22872287
int
22882288
dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
2289-
dmu_tx_t *tx, const blkptr_t *bps, size_t nbps, boolean_t replay)
2289+
dmu_tx_t *tx, const blkptr_t *bps, size_t nbps)
22902290
{
22912291
spa_t *spa;
22922292
dmu_buf_t **dbp, *dbuf;
@@ -2360,10 +2360,8 @@ dmu_brt_clone(objset_t *os, uint64_t object, uint64_t offset, uint64_t length,
23602360
* When data in embedded into BP there is no need to create
23612361
* BRT entry as there is no data block. Just copy the BP as
23622362
* it contains the data.
2363-
* Also, when replaying ZIL we don't want to bump references
2364-
* in the BRT as it was already done during ZIL claim.
23652363
*/
2366-
if (!replay && !BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp)) {
2364+
if (!BP_IS_HOLE(bp) && !BP_IS_EMBEDDED(bp)) {
23672365
brt_pending_add(spa, bp, tx);
23682366
}
23692367
}

module/zfs/zfs_vnops.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
13271327
}
13281328

13291329
error = dmu_brt_clone(outos, outzp->z_id, outoff, size, tx,
1330-
bps, nbps, B_FALSE);
1330+
bps, nbps);
13311331
if (error != 0) {
13321332
dmu_tx_commit(tx);
13331333
break;
@@ -1461,7 +1461,7 @@ zfs_clone_range_replay(znode_t *zp, uint64_t off, uint64_t len, uint64_t blksz,
14611461
if (zp->z_blksz < blksz)
14621462
zfs_grow_blocksize(zp, blksz, tx);
14631463

1464-
dmu_brt_clone(zfsvfs->z_os, zp->z_id, off, len, tx, bps, nbps, B_TRUE);
1464+
dmu_brt_clone(zfsvfs->z_os, zp->z_id, off, len, tx, bps, nbps);
14651465

14661466
zfs_tstamp_update_setup(zp, CONTENT_MODIFIED, mtime, ctime);
14671467

0 commit comments

Comments
 (0)