diff options
author | Pawel Jakub Dawidek <[email protected]> | 2023-03-10 20:59:53 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2023-03-10 11:59:53 -0800 |
commit | 67a1b0379159c46bcd60a462a2790248046c8804 (patch) | |
tree | dbba99ec9db66f8afefebad07caa22d36f04f3ff /module/zfs/zfs_log.c | |
parent | da19d919a853ad05ef300fe000e6c96c4db84bcf (diff) |
Implementation of block cloning for ZFS
Block Cloning allows to manually clone a file (or a subset of its
blocks) into another (or the same) file by just creating additional
references to the data blocks without copying the data itself.
Those references are kept in the Block Reference Tables (BRTs).
The whole design of block cloning is documented in module/zfs/brt.c.
Reviewed-by: Alexander Motin <[email protected]>
Reviewed-by: Christian Schwarz <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Rich Ercolani <[email protected]>
Signed-off-by: Pawel Jakub Dawidek <[email protected]>
Closes #13392
Diffstat (limited to 'module/zfs/zfs_log.c')
-rw-r--r-- | module/zfs/zfs_log.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index 77bf9140d..d009c58d8 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2018 by Delphix. All rights reserved. + * Copyright (c) 2022 by Pawel Jakub Dawidek */ @@ -891,5 +892,56 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, zil_itx_assign(zilog, itx, tx); } +/* + * Handles TX_CLONE_RANGE transactions. + */ +void +zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, + uint64_t off, uint64_t len, uint64_t blksz, const blkptr_t *bps, + size_t nbps) +{ + itx_t *itx; + lr_clone_range_t *lr; + uint64_t partlen, max_log_data; + size_t i, partnbps; + + VERIFY(!zil_replaying(zilog, tx)); + + if (zp->z_unlinked) + return; + + max_log_data = zil_max_log_data(zilog, sizeof (lr_clone_range_t)); + + while (nbps > 0) { + partnbps = MIN(nbps, max_log_data / sizeof (bps[0])); + partlen = 0; + for (i = 0; i < partnbps; i++) { + partlen += BP_GET_LSIZE(&bps[i]); + } + partlen = MIN(partlen, len); + + itx = zil_itx_create(txtype, + sizeof (*lr) + sizeof (bps[0]) * partnbps); + lr = (lr_clone_range_t *)&itx->itx_lr; + lr->lr_foid = zp->z_id; + lr->lr_offset = off; + lr->lr_length = partlen; + lr->lr_blksz = blksz; + lr->lr_nbps = partnbps; + memcpy(lr->lr_bps, bps, sizeof (bps[0]) * partnbps); + + itx->itx_sync = (zp->z_sync_cnt != 0); + + zil_itx_assign(zilog, itx, tx); + + bps += partnbps; + ASSERT3U(nbps, >=, partnbps); + nbps -= partnbps; + off += partlen; + ASSERT3U(len, >=, partlen); + len -= partlen; + } +} + ZFS_MODULE_PARAM(zfs, zfs_, immediate_write_sz, S64, ZMOD_RW, "Largest data block to write to zil"); |