Skip to content

Commit 5f7a8e6

Browse files
author
Dan McDonald
committed
6562 Refquota on receive doesn't account for overage
Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com> Reviewed by: Toomas Soome <tsoome@me.com> Approved by: Gordon Ross <gwr@nexenta.com>
1 parent d7e7cb9 commit 5f7a8e6

File tree

7 files changed

+124
-8
lines changed

7 files changed

+124
-8
lines changed

usr/src/pkg/manifests/system-test-zfstest.mf

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
#
1313
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
14-
# Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
1514
# Copyright 2015 Nexenta Systems, Inc. All rights reserved.
15+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
1616
#
1717

1818
set name=pkg.fmri value=pkg:/system/test/zfstest@$(PKGVERS)
@@ -699,6 +699,9 @@ file \
699699
file \
700700
path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_011_pos \
701701
mode=0555
702+
file \
703+
path=opt/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_012_pos \
704+
mode=0555
702705
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/cleanup mode=0555
703706
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/setup mode=0555
704707
file path=opt/zfs-tests/tests/functional/cli_root/zfs_rename/zfs_rename.cfg \

usr/src/test/zfs-tests/runfiles/delphix.run

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#
1313
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
14+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
1415
#
1516

1617
[DEFAULT]
@@ -149,7 +150,7 @@ tests = ['zfs_written_property_001_pos']
149150
tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
150151
'zfs_receive_005_neg', 'zfs_receive_006_pos',
151152
'zfs_receive_007_neg', 'zfs_receive_008_pos', 'zfs_receive_009_neg',
152-
'zfs_receive_010_pos', 'zfs_receive_011_pos']
153+
'zfs_receive_010_pos', 'zfs_receive_011_pos', 'zfs_receive_012_pos']
153154

154155
[/opt/zfs-tests/tests/functional/cli_root/zfs_rename]
155156
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',

usr/src/test/zfs-tests/runfiles/omnios.run

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#
1313
# Copyright (c) 2013, 2015 by Delphix. All rights reserved.
14+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
1415
#
1516

1617
[DEFAULT]
@@ -149,7 +150,7 @@ tests = ['zfs_written_property_001_pos']
149150
tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
150151
'zfs_receive_005_neg', 'zfs_receive_006_pos',
151152
'zfs_receive_007_neg', 'zfs_receive_008_pos', 'zfs_receive_009_neg',
152-
'zfs_receive_010_pos', 'zfs_receive_011_pos']
153+
'zfs_receive_010_pos', 'zfs_receive_011_pos', 'zfs_receive_012_pos']
153154

154155
[/opt/zfs-tests/tests/functional/cli_root/zfs_rename]
155156
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',

usr/src/test/zfs-tests/runfiles/openindiana.run

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#
1313
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
14+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
1415
#
1516

1617
[DEFAULT]
@@ -149,7 +150,7 @@ tests = ['zfs_written_property_001_pos']
149150
tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
150151
'zfs_receive_005_neg', 'zfs_receive_006_pos',
151152
'zfs_receive_007_neg', 'zfs_receive_008_pos', 'zfs_receive_009_neg',
152-
'zfs_receive_010_pos', 'zfs_receive_011_pos']
153+
'zfs_receive_010_pos', 'zfs_receive_011_pos', 'zfs_receive_012_pos']
153154

154155
[/opt/zfs-tests/tests/functional/cli_root/zfs_rename]
155156
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',

usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#
1313
# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
14+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
1415
#
1516

1617
include $(SRC)/Makefile.master
@@ -30,7 +31,8 @@ PROGS = cleanup \
3031
zfs_receive_008_pos \
3132
zfs_receive_009_neg \
3233
zfs_receive_010_pos \
33-
zfs_receive_011_pos
34+
zfs_receive_011_pos \
35+
zfs_receive_012_pos
3436

3537
CMDS = $(PROGS:%=$(TESTDIR)/%)
3638
$(CMDS) := FILEMODE = 0555
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# This file and its contents are supplied under the terms of the
6+
# Common Development and Distribution License ("CDDL"), version 1.0.
7+
# You may only use this file in accordance with the terms of version
8+
# 1.0 of the CDDL.
9+
#
10+
# A full copy of the text of the CDDL should have accompanied this
11+
# source. A copy of the CDDL is also available via the Internet at
12+
# http://www.illumos.org/license/CDDL.
13+
#
14+
# CDDL HEADER END
15+
#
16+
17+
#
18+
# Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
19+
#
20+
21+
. $STF_SUITE/include/libtest.shlib
22+
23+
#
24+
# DESCRIPTION:
25+
# refquota, like regular quota, is loosely enforced. A dataset
26+
# can exceed its refquota by one transaction. This loose enforcement
27+
# used to cause problems upon receiving a datastream where its
28+
# refquota is slightly exceeded. This test confirms that we can
29+
# successfully receive a slightly over refquota stream.
30+
#
31+
# STRATEGY:
32+
# 1. Create a filesystem.
33+
# 2. Set a refquota.
34+
# 3. Snapshot the filesystem.
35+
# 4. Send a replication stream to a new filesystem.
36+
# 5. On the original filesystem, fill it up to its quota.
37+
# 6. Snapshot the original filesystem again.
38+
# 7. Send an incremental stream to the same new filesystem.
39+
#
40+
41+
verify_runnable "both"
42+
43+
typeset streamfile=/var/tmp/streamfile.$$
44+
45+
function cleanup
46+
{
47+
log_must $RM $streamfile
48+
log_must $ZFS destroy -rf $TESTPOOL/$TESTFS1
49+
log_must $ZFS destroy -rf $TESTPOOL/$TESTFS2
50+
}
51+
52+
log_assert "The allowable slight refquota overage is properly sent-and-" \
53+
"received."
54+
log_onexit cleanup
55+
56+
orig=$TESTPOOL/$TESTFS1
57+
dest=$TESTPOOL/$TESTFS2
58+
59+
# 1. Create a filesystem.
60+
log_must $ZFS create $orig
61+
origdir=$(get_prop mountpoint $orig)
62+
63+
# 2. Set a refquota.
64+
log_must $ZFS set refquota=50M $orig
65+
66+
# 3. Snapshot the filesystem.
67+
log_must $ZFS snapshot $orig@1
68+
69+
# 4. Send a replication stream to a new filesystem.
70+
log_must eval "$ZFS send -R $orig@1 > $streamfile"
71+
log_must eval "$ZFS recv $dest < $streamfile"
72+
73+
# 5. On the original filesystem, fill it up to its quota.
74+
cat < /dev/urandom > $origdir/fill-it-up
75+
76+
# 6. Snapshot the original filesystem again.
77+
log_must $ZFS snapshot $orig@2
78+
79+
# 7. Send an incremental stream to the same new filesystem.
80+
log_must eval "$ZFS send -I 1 -R $orig@2 > $streamfile"
81+
log_must eval "$ZFS recv $dest < $streamfile"
82+
83+
log_pass "Verified receiving a slightly-over-refquota stream succeeds."

usr/src/uts/common/fs/zfs/dsl_dataset.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
* Copyright (c) 2014 RackTop Systems.
2626
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
2727
* Copyright (c) 2014 Integros [integros.com]
28+
* Copyright 2016, OmniTI Computer Consulting, Inc. All rights reserved.
2829
*/
2930

3031
#include <sys/dmu_objset.h>
@@ -78,6 +79,8 @@ int zfs_max_recordsize = 1 * 1024 * 1024;
7879

7980
extern inline dsl_dataset_phys_t *dsl_dataset_phys(dsl_dataset_t *ds);
8081

82+
extern int spa_asize_inflation;
83+
8184
/*
8285
* Figure out how much of this delta should be propogated to the dsl_dir
8386
* layer. If there's a refreservation, that space has already been
@@ -2788,6 +2791,11 @@ int
27882791
dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
27892792
dsl_dataset_t *origin_head, boolean_t force, void *owner, dmu_tx_t *tx)
27902793
{
2794+
/*
2795+
* "slack" factor for received datasets with refquota set on them.
2796+
* See the bottom of this function for details on its use.
2797+
*/
2798+
uint64_t refquota_slack = DMU_MAX_ACCESS * spa_asize_inflation;
27912799
int64_t unused_refres_delta;
27922800

27932801
/* they should both be heads */
@@ -2830,10 +2838,22 @@ dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
28302838
dsl_dir_space_available(origin_head->ds_dir, NULL, 0, TRUE))
28312839
return (SET_ERROR(ENOSPC));
28322840

2833-
/* clone can't be over the head's refquota */
2841+
/*
2842+
* The clone can't be too much over the head's refquota.
2843+
*
2844+
* To ensure that the entire refquota can be used, we allow one
2845+
* transaction to exceed the the refquota. Therefore, this check
2846+
* needs to also allow for the space referenced to be more than the
2847+
* refquota. The maximum amount of space that one transaction can use
2848+
* on disk is DMU_MAX_ACCESS * spa_asize_inflation. Allowing this
2849+
* overage ensures that we are able to receive a filesystem that
2850+
* exceeds the refquota on the source system.
2851+
*
2852+
* So that overage is the refquota_slack we use below.
2853+
*/
28342854
if (origin_head->ds_quota != 0 &&
28352855
dsl_dataset_phys(clone)->ds_referenced_bytes >
2836-
origin_head->ds_quota)
2856+
origin_head->ds_quota + refquota_slack)
28372857
return (SET_ERROR(EDQUOT));
28382858

28392859
return (0);
@@ -2847,8 +2867,13 @@ dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
28472867
int64_t unused_refres_delta;
28482868

28492869
ASSERT(clone->ds_reserved == 0);
2870+
/*
2871+
* NOTE: On DEBUG kernels there could be a race between this and
2872+
* the check function if spa_asize_inflation is adjusted...
2873+
*/
28502874
ASSERT(origin_head->ds_quota == 0 ||
2851-
dsl_dataset_phys(clone)->ds_unique_bytes <= origin_head->ds_quota);
2875+
dsl_dataset_phys(clone)->ds_unique_bytes <= origin_head->ds_quota +
2876+
DMU_MAX_ACCESS * spa_asize_inflation);
28522877
ASSERT3P(clone->ds_prev, ==, origin_head->ds_prev);
28532878

28542879
/*

0 commit comments

Comments
 (0)