From 6eb6073a044653016013b1a72de03a1257e899c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kan=20Johansson?= Date: Mon, 5 Jun 2017 22:53:09 +0200 Subject: [PATCH] Allow add of raidz and mirror with same redundancy Allow new members to be added to a pool mixing raidz and mirror vdevs without giving -f, as long as they have matching redundancy. This case was missed in #5915, which only handled zpool create. Add zfstest zpool_add_010_pos.ksh, with test of zpool create followed by zpool add of mixed raidz and mirror vdevs. Add some more mixed raidz and mirror cases to zpool_create_006_pos.ksh. Reviewed-by: Brian Behlendorf Signed-off-by: Haakan Johansson Issue #5915 Closes #6181 --- cmd/zpool/zpool_vdev.c | 17 +- tests/runfiles/linux.run | 1 + .../functional/cli_root/zpool_add/Makefile.am | 1 + .../cli_root/zpool_add/zpool_add_010_pos.ksh | 164 ++++++++++++++++++ .../zpool_create/zpool_create_006_pos.ksh | 13 +- 5 files changed, 192 insertions(+), 4 deletions(-) create mode 100755 tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index 74ba4455b..b0b639684 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -1053,6 +1053,7 @@ check_replication(nvlist_t *config, nvlist_t *newroot) nvlist_t **child; uint_t children; replication_level_t *current = NULL, *new; + replication_level_t *raidz, *mirror; int ret; /* @@ -1100,7 +1101,21 @@ check_replication(nvlist_t *config, nvlist_t *newroot) */ ret = 0; if (current != NULL) { - if (strcmp(current->zprl_type, new->zprl_type) != 0) { + if (is_raidz_mirror(current, new, &raidz, &mirror) || + is_raidz_mirror(new, current, &raidz, &mirror)) { + if (raidz->zprl_parity != mirror->zprl_children - 1) { + vdev_error(gettext( + "mismatched replication level: pool and " + "new vdev with different redundancy, %s " + "and %s vdevs, %llu vs. %llu (%llu-way)\n"), + raidz->zprl_type, + mirror->zprl_type, + raidz->zprl_parity, + mirror->zprl_children - 1, + mirror->zprl_children); + ret = -1; + } + } else if (strcmp(current->zprl_type, new->zprl_type) != 0) { vdev_error(gettext( "mismatched replication level: pool uses %s " "and new vdev is %s\n"), diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run index 115b9b025..a0d89f277 100644 --- a/tests/runfiles/linux.run +++ b/tests/runfiles/linux.run @@ -193,6 +193,7 @@ tests = ['zpool_001_neg', 'zpool_002_pos', 'zpool_003_pos'] tests = ['zpool_add_001_pos', 'zpool_add_002_pos', 'zpool_add_003_pos', 'zpool_add_004_pos', 'zpool_add_005_pos', 'zpool_add_006_pos', 'zpool_add_007_neg', 'zpool_add_008_neg', 'zpool_add_009_neg', + 'zpool_add_010_pos', 'add-o_ashift', 'add_prop_ashift'] [tests/functional/cli_root/zpool_attach] diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am index 30be8ecfc..4b6b533fe 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/Makefile.am @@ -13,5 +13,6 @@ dist_pkgdata_SCRIPTS = \ zpool_add_007_neg.ksh \ zpool_add_008_neg.ksh \ zpool_add_009_neg.ksh \ + zpool_add_010_pos.ksh \ add-o_ashift.ksh \ add_prop_ashift.ksh diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh new file mode 100755 index 000000000..f949e8ae9 --- /dev/null +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh @@ -0,0 +1,164 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib + +# +# DESCRIPTION: +# Verify zpool add succeed when adding vdevs with matching redundancy. +# +# STRATEGY: +# 1. Create base filesystem to hold virtual disk files. +# 2. Create several files == $MINVDEVSIZE. +# 3. Create pool with given redundancy. +# 3. Verify 'zpool add' succeed with with matching redundancy. +# + +verify_runnable "global" + +function cleanup +{ + datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1 + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + + +log_assert "Verify 'zpool add' succeed with keywords combination." +log_onexit cleanup + +create_pool $TESTPOOL $DISKS +mntpnt=$(get_prop mountpoint $TESTPOOL) + +typeset -i i=0 +while ((i < 10)); do + log_must truncate -s $MINVDEVSIZE $mntpnt/vdev$i + + eval vdev$i=$mntpnt/vdev$i + ((i += 1)) +done + +set -A redundancy0_create_args \ + "$vdev0" + +set -A redundancy1_create_args \ + "mirror $vdev0 $vdev1" \ + "raidz1 $vdev0 $vdev1" + +set -A redundancy2_create_args \ + "mirror $vdev0 $vdev1 $vdev2" \ + "raidz2 $vdev0 $vdev1 $vdev2" + +set -A redundancy3_create_args \ + "mirror $vdev0 $vdev1 $vdev2 $vdev3" \ + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3" + +set -A redundancy0_add_args \ + "$vdev5" \ + "$vdev5 $vdev6" + +set -A redundancy1_add_args \ + "mirror $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8" + +set -A redundancy2_add_args \ + "mirror $vdev5 $vdev6 $vdev7" \ + "raidz2 $vdev5 $vdev6 $vdev7" + +set -A redundancy3_add_args \ + "mirror $vdev5 $vdev6 $vdev7 $vdev8" \ + "raidz3 $vdev5 $vdev6 $vdev7 $vdev8" + +typeset -i j=0 + +function zpool_create_add +{ + typeset -n create_args=$1 + typeset -n add_args=$2 + + i=0 + while ((i < ${#create_args[@]})); do + j=0 + while ((j < ${#add_args[@]})); do + log_must zpool create $TESTPOOL1 ${create_args[$i]} + log_must zpool add $TESTPOOL1 ${add_args[$j]} + log_must zpool destroy -f $TESTPOOL1 + + ((j += 1)) + done + ((i += 1)) + done +} + +function zpool_create_forced_add +{ + typeset -n create_args=$1 + typeset -n add_args=$2 + + i=0 + while ((i < ${#create_args[@]})); do + j=0 + while ((j < ${#add_args[@]})); do + log_must zpool create $TESTPOOL1 ${create_args[$i]} + log_mustnot zpool add $TESTPOOL1 ${add_args[$j]} + log_must zpool add -f $TESTPOOL1 ${add_args[$j]} + log_must zpool destroy -f $TESTPOOL1 + + ((j += 1)) + done + ((i += 1)) + done +} + +zpool_create_add redundancy0_create_args redundancy0_add_args +zpool_create_add redundancy1_create_args redundancy1_add_args +zpool_create_add redundancy2_create_args redundancy2_add_args +zpool_create_add redundancy3_create_args redundancy3_add_args + +zpool_create_forced_add redundancy0_create_args redundancy1_add_args +zpool_create_forced_add redundancy0_create_args redundancy2_add_args +zpool_create_forced_add redundancy0_create_args redundancy3_add_args + +zpool_create_forced_add redundancy1_create_args redundancy0_add_args +zpool_create_forced_add redundancy1_create_args redundancy2_add_args +zpool_create_forced_add redundancy1_create_args redundancy3_add_args + +zpool_create_forced_add redundancy2_create_args redundancy0_add_args +zpool_create_forced_add redundancy2_create_args redundancy1_add_args +zpool_create_forced_add redundancy2_create_args redundancy3_add_args + +zpool_create_forced_add redundancy3_create_args redundancy0_add_args +zpool_create_forced_add redundancy3_create_args redundancy1_add_args +zpool_create_forced_add redundancy3_create_args redundancy2_add_args + +log_pass "'zpool add' succeed with keywords combination." diff --git a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh index 060c7af4b..79a0060c9 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_006_pos.ksh @@ -59,7 +59,7 @@ mntpnt=$(get_prop mountpoint $TESTPOOL) typeset -i i=0 while ((i < 10)); do - log_must mkfile $MINVDEVSIZE $mntpnt/vdev$i + log_must truncate -s $MINVDEVSIZE $mntpnt/vdev$i eval vdev$i=$mntpnt/vdev$i ((i += 1)) @@ -73,6 +73,12 @@ set -A valid_args \ "mirror $vdev0 $vdev1 mirror $vdev2 $vdev3 mirror $vdev4 $vdev5 \ spare $vdev6 $vdev7" \ "mirror $vdev0 $vdev1 spare $vdev2 mirror $vdev3 $vdev4" \ + "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3" \ + "mirror $vdev0 $vdev1 raidz $vdev2 $vdev3 $vdev4" \ + "mirror $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5" \ + "mirror $vdev0 $vdev1 $vdev2 $vdev3 \ + raidz3 $vdev4 $vdev5 $vdev6 $vdev7" \ + "raidz $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4" \ "raidz $vdev0 $vdev1 $vdev2 raidz1 $vdev3 $vdev4 $vdev5" \ "raidz $vdev0 $vdev1 raidz1 $vdev2 $vdev3 raidz $vdev4 $vdev5" \ "raidz $vdev0 $vdev1 $vdev2 raidz1 $vdev3 $vdev4 $vdev5 \ @@ -80,6 +86,7 @@ set -A valid_args \ "raidz $vdev0 $vdev1 raidz1 $vdev2 $vdev3 raidz $vdev4 $vdev5 \ spare $vdev6 $vdev7" \ "raidz $vdev0 $vdev1 spare $vdev2 raidz $vdev3 $vdev4" \ + "raidz2 $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 $vdev5" \ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5" \ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5 \ raidz2 $vdev6 $vdev7 $vdev8" \ @@ -88,6 +95,8 @@ set -A valid_args \ "raidz2 $vdev0 $vdev1 $vdev2 raidz2 $vdev3 $vdev4 $vdev5 \ raidz2 $vdev6 $vdev7 $vdev8 spare $vdev9" \ "raidz2 $vdev0 $vdev1 $vdev2 spare $vdev3 raidz2 $vdev4 $vdev5 $vdev6" \ + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3 \ + mirror $vdev4 $vdev5 $vdev6 $vdev7" \ "spare $vdev0 $vdev1 $vdev2 mirror $vdev3 $vdev4 raidz $vdev5 $vdev6" set -A forced_args \ @@ -111,7 +120,6 @@ set -A forced_args \ i=0 while ((i < ${#valid_args[@]})); do log_must zpool create $TESTPOOL1 ${valid_args[$i]} - sync; sync log_must zpool destroy -f $TESTPOOL1 ((i += 1)) @@ -121,7 +129,6 @@ i=0 while ((i < ${#forced_args[@]})); do log_mustnot zpool create $TESTPOOL1 ${forced_args[$i]} log_must zpool create -f $TESTPOOL1 ${forced_args[$i]} - sync; sync log_must zpool destroy -f $TESTPOOL1 ((i += 1))