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_replay.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_replay.c')
-rw-r--r-- | module/zfs/zfs_replay.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index 32be27a8b..04dfda56b 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -22,6 +22,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Cyril Plisko. All rights reserved. * Copyright (c) 2013, 2017 by Delphix. All rights reserved. + * Copyright (c) 2021, 2022 by Pawel Jakub Dawidek */ #include <sys/types.h> @@ -1162,6 +1163,34 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap) return (error); } +static int +zfs_replay_clone_range(void *arg1, void *arg2, boolean_t byteswap) +{ + zfsvfs_t *zfsvfs = arg1; + lr_clone_range_t *lr = arg2; + znode_t *zp; + int error; + + if (byteswap) + byteswap_uint64_array(lr, sizeof (*lr)); + + if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { + /* + * Clones can be logged out of order, so don't be surprised if + * the file is gone - just return success. + */ + if (error == ENOENT) + error = 0; + return (error); + } + + error = zfs_clone_range_replay(zp, lr->lr_offset, lr->lr_length, + lr->lr_blksz, lr->lr_bps, lr->lr_nbps); + + zrele(zp); + return (error); +} + /* * Callback vectors for replaying records */ @@ -1190,4 +1219,5 @@ zil_replay_func_t *const zfs_replay_vector[TX_MAX_TYPE] = { zfs_replay_setsaxattr, /* TX_SETSAXATTR */ zfs_replay_rename_exchange, /* TX_RENAME_EXCHANGE */ zfs_replay_rename_whiteout, /* TX_RENAME_WHITEOUT */ + zfs_replay_clone_range, /* TX_CLONE_RANGE */ }; |