aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_replay.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_replay.c')
-rw-r--r--module/zfs/zfs_replay.c30
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 */
};