@@ -25,6 +25,40 @@
2525#include <sys/zfs_vnops.h>
2626#include <sys/zfeature.h>
272728+/*
29+ * Take the source and destination inode locks for a remap (clone or dedupe).
30+ *
31+ * Since Linux 4.20 the VFS does not lock the inodes for ->remap_file_range();
32+ * the filesystem must, and it must impose an order on the two, or two remaps
33+ * running in opposite directions deadlock: each would hold one inode and wait
34+ * for the other, and an rwsem writer queues behind the existing readers. Order
35+ * by inode address, as btrfs does. The destination is taken exclusively and
36+ * the source shared, so concurrent remaps out of one hot source still proceed.
37+ * Only the acquisition needs the order: releasing never waits, so the unlock
38+ * side does not mirror it.
39+ */
40+static void
41+zpl_remap_lock_two(struct inode *src_i, struct inode *dst_i)
42+{
43+if (src_i == dst_i) {
44+spl_inode_lock(dst_i);
45+ } else if (src_i < dst_i) {
46+spl_inode_lock_shared(src_i);
47+spl_inode_lock(dst_i);
48+ } else {
49+spl_inode_lock(dst_i);
50+spl_inode_lock_shared(src_i);
51+ }
52+}
53+54+static void
55+zpl_remap_unlock_two(struct inode *src_i, struct inode *dst_i)
56+{
57+spl_inode_unlock(dst_i);
58+if (src_i != dst_i)
59+spl_inode_unlock_shared(src_i);
60+}
61+2862/*
2963 * Clone part of a file via block cloning.
3064 *
@@ -51,9 +85,7 @@ zpl_clone_file_range_impl(struct file *src_file, loff_t src_off,
5185dmu_objset_spa(ITOZSB(dst_i)->z_os), SPA_FEATURE_BLOCK_CLONING))
5286return (-EOPNOTSUPP);
538754-if (src_i != dst_i)
55-spl_inode_lock_shared(src_i);
56-spl_inode_lock(dst_i);
88+zpl_remap_lock_two(src_i, dst_i);
57895890crhold(cr);
5991cookie = spl_fstrans_mark();
@@ -64,16 +96,67 @@ zpl_clone_file_range_impl(struct file *src_file, loff_t src_off,
6496spl_fstrans_unmark(cookie);
6597crfree(cr);
669867-spl_inode_unlock(dst_i);
68-if (src_i != dst_i)
69-spl_inode_unlock_shared(src_i);
99+zpl_remap_unlock_two(src_i, dst_i);
7010071101if (err < 0)
72102return (err);
7310374104return ((ssize_t)len_o);
75105}
76106107+#if defined(HAVE_VFS_REMAP_FILE_RANGE) || \
108+ defined(HAVE_VFS_DEDUPE_FILE_RANGE)
109+/*
110+ * Logic shared by the FIDEDUPERANGE entry points. Compare len bytes at
111+ * src_off in src_file with dst_off in dst_file and, if they are identical,
112+ * share the underlying blocks via zfs_dedupe_range(). Returns the number of
113+ * bytes deduped, -EBADE if the ranges differ (which the VFS reports as
114+ * FILE_DEDUPE_RANGE_DIFFERS), or another negative errno on failure.
115+ */
116+static ssize_t
117+zpl_dedupe_file_range_impl(struct file *src_file, loff_t src_off,
118+struct file *dst_file, loff_t dst_off, size_t len, boolean_t can_shorten)
119+{
120+struct inode *src_i = file_inode(src_file);
121+struct inode *dst_i = file_inode(dst_file);
122+uint64_t src_off_o = (uint64_t)src_off;
123+uint64_t dst_off_o = (uint64_t)dst_off;
124+uint64_t len_o = (uint64_t)len;
125+cred_t *cr = CRED();
126+fstrans_cookie_t cookie;
127+boolean_t same = B_FALSE;
128+int err;
129+130+if (!zfs_bclone_enabled)
131+return (-EOPNOTSUPP);
132+133+if (!spa_feature_is_enabled(
134+dmu_objset_spa(ITOZSB(dst_i)->z_os), SPA_FEATURE_BLOCK_CLONING))
135+return (-EOPNOTSUPP);
136+137+zpl_remap_lock_two(src_i, dst_i);
138+139+crhold(cr);
140+cookie = spl_fstrans_mark();
141+142+err = -zfs_dedupe_range(ITOZ(src_i), src_off_o, ITOZ(dst_i),
143+dst_off_o, &len_o, cr, can_shorten, &same);
144+145+spl_fstrans_unmark(cookie);
146+crfree(cr);
147+148+zpl_remap_unlock_two(src_i, dst_i);
149+150+if (err < 0)
151+return (err);
152+153+if (!same)
154+return (-EBADE);
155+156+return ((ssize_t)len_o);
157+}
158+#endif
159+77160/*
78161 * Entry point for copy_file_range(). Copy len bytes from src_off in src_file
79162 * to dst_off in dst_file. We are permitted to do this however we like, so we
@@ -149,9 +232,9 @@ zpl_remap_file_range(struct file *src_file, loff_t src_off,
149232if (flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_CAN_SHORTEN))
150233return (-EINVAL);
151234152-/* No support for dedup yet */
153235if (flags & REMAP_FILE_DEDUP)
154-return (-EOPNOTSUPP);
236+return (zpl_dedupe_file_range_impl(src_file, src_off, dst_file,
237+dst_off, len, !!(flags & REMAP_FILE_CAN_SHORTEN)));
155238156239/* Zero length means to clone everything to the end of the file */
157240if (len == 0)
198281zpl_dedupe_file_range(struct file *src_file, loff_t src_off,
199282struct file *dst_file, loff_t dst_off, uint64_t len)
200283{
201-/* No support for dedup yet */
202-return (-EOPNOTSUPP);
284+/*
285+ * The pre-4.20 dedupe interface has no way to signal that a short
286+ * dedupe is acceptable, so the whole range must match.
287+ */
288+return (zpl_dedupe_file_range_impl(src_file, src_off, dst_file,
289+dst_off, len, B_FALSE));
203290}
204291#endif /* HAVE_VFS_DEDUPE_FILE_RANGE */