Skip to content

Commit 3ae96fe

Browse files
robnlundman
authored andcommitted
copy_file_range: fix fallback when source create on same txg
In 019dea0 we removed the conversion from EAGAIN->EXDEV inside zfs_clone_range(), but forgot to add a test for EAGAIN to the copy_file_range() entry points to trigger fallback to a content copy. This commit fixes that. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Kay Pedersen <[email protected]> Signed-off-by: Rob Norris <[email protected]> Closes openzfs#15170 Closes openzfs#15172
1 parent 3f1d777 commit 3ae96fe

File tree

7 files changed

+81
-8
lines changed

7 files changed

+81
-8
lines changed

module/os/freebsd/zfs/zfs_vnops_os.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6288,7 +6288,8 @@ zfs_freebsd_copy_file_range(struct vop_copy_file_range_args *ap)
62886288

62896289
error = zfs_clone_range(VTOZ(invp), ap->a_inoffp, VTOZ(outvp),
62906290
ap->a_outoffp, &len, ap->a_outcred);
6291-
if (error == EXDEV || error == EINVAL || error == EOPNOTSUPP)
6291+
if (error == EXDEV || error == EAGAIN || error == EINVAL ||
6292+
error == EOPNOTSUPP)
62926293
goto bad_locked_fallback;
62936294
*ap->a_lenp = (size_t)len;
62946295
out_locked:

module/os/linux/zfs/zpl_file_range.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,16 @@ zpl_copy_file_range(struct file *src_file, loff_t src_off,
103103
* Since Linux 5.3 the filesystem driver is responsible for executing
104104
* an appropriate fallback, and a generic fallback function is provided.
105105
*/
106-
if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV)
106+
if (ret == -EOPNOTSUPP || ret == -EINVAL || ret == -EXDEV ||
107+
ret == -EAGAIN)
107108
ret = generic_copy_file_range(src_file, src_off, dst_file,
108109
dst_off, len, flags);
109110
#else
110111
/*
111112
* Before Linux 5.3 the filesystem has to return -EOPNOTSUPP to signal
112113
* to the kernel that it should fallback to a content copy.
113114
*/
114-
if (ret == -EINVAL || ret == -EXDEV)
115+
if (ret == -EINVAL || ret == -EXDEV || ret == -EAGAIN)
115116
ret = -EOPNOTSUPP;
116117
#endif /* HAVE_VFS_GENERIC_COPY_FILE_RANGE */
117118

module/zfs/zfs_vnops.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,9 +1261,10 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
12611261
&nbps);
12621262
if (error != 0) {
12631263
/*
1264-
* If we are tyring to clone a block that was created
1265-
* in the current transaction group. Return an error,
1266-
* so the caller can fallback to just copying the data.
1264+
* If we are trying to clone a block that was created
1265+
* in the current transaction group, error will be
1266+
* EAGAIN here, which we can just return to the caller
1267+
* so it can fallback if it likes.
12671268
*/
12681269
break;
12691270
}

tests/runfiles/linux.run

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ tests = ['block_cloning_copyfilerange', 'block_cloning_copyfilerange_partial',
4141
'block_cloning_ficlonerange_partial',
4242
'block_cloning_disabled_copyfilerange', 'block_cloning_disabled_ficlone',
4343
'block_cloning_disabled_ficlonerange',
44-
'block_cloning_copyfilerange_cross_dataset']
44+
'block_cloning_copyfilerange_cross_dataset',
45+
'block_cloning_copyfilerange_fallback_same_txg']
4546
tags = ['functional', 'block_cloning']
4647

4748
[tests/functional/chattr:Linux]

tests/test-runner/bin/zts-report.py.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ elif sys.platform.startswith('linux'):
304304
['SKIP', cfr_reason],
305305
'block_cloning/block_cloning_copyfilerange_cross_dataset':
306306
['SKIP', cfr_cross_reason],
307+
'block_cloning/block_cloning_copyfilerange_fallback_same_txg':
308+
['SKIP', cfr_cross_reason],
307309
})
308310

309311

tests/zfs-tests/tests/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,10 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
441441
functional/block_cloning/cleanup.ksh \
442442
functional/block_cloning/setup.ksh \
443443
functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh \
444+
functional/block_cloning/block_cloning_copyfilerange_fallback.ksh \
445+
functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh \
444446
functional/block_cloning/block_cloning_copyfilerange.ksh \
445447
functional/block_cloning/block_cloning_copyfilerange_partial.ksh \
446-
functional/block_cloning/block_cloning_copyfilerange_fallback.ksh \
447448
functional/block_cloning/block_cloning_disabled_copyfilerange.ksh \
448449
functional/block_cloning/block_cloning_disabled_ficlone.ksh \
449450
functional/block_cloning/block_cloning_disabled_ficlonerange.ksh \
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# The contents of this file are subject to the terms of the
6+
# Common Development and Distribution License (the "License").
7+
# You may not use this file except in compliance with the License.
8+
#
9+
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10+
# or https://opensource.org/licenses/CDDL-1.0.
11+
# See the License for the specific language governing permissions
12+
# and limitations under the License.
13+
#
14+
# When distributing Covered Code, include this CDDL HEADER in each
15+
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16+
# If applicable, add the following below this CDDL HEADER, with the
17+
# fields enclosed by brackets "[]" replaced with your own identifying
18+
# information: Portions Copyright [yyyy] [name of copyright owner]
19+
#
20+
# CDDL HEADER END
21+
#
22+
23+
#
24+
# Copyright (c) 2023, Klara Inc.
25+
# Copyright (c) 2023, Rob Norris <[email protected]>
26+
#
27+
28+
. $STF_SUITE/include/libtest.shlib
29+
. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
30+
31+
verify_runnable "global"
32+
33+
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
34+
log_unsupported "copy_file_range not available before Linux 4.5"
35+
fi
36+
37+
claim="copy_file_range will fall back to copy when cloning on same txg"
38+
39+
log_assert $claim
40+
41+
typeset timeout=$(get_tunable TXG_TIMEOUT)
42+
43+
function cleanup
44+
{
45+
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
46+
set_tunable64 TXG_TIMEOUT $timeout
47+
}
48+
49+
log_onexit cleanup
50+
51+
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
52+
53+
log_must set_tunable64 TXG_TIMEOUT 5000
54+
55+
log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=128K count=4
56+
log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 0 0 524288
57+
58+
log_must sync_pool $TESTPOOL
59+
60+
log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
61+
62+
typeset blocks=$(unique_blocks $TESTPOOL file $TESTPOOL clone)
63+
log_must [ "$blocks" = "" ]
64+
65+
log_pass $claim
66+

0 commit comments

Comments
 (0)