From bedbc13daa6dfe9e0221bfadb8d8db2378deaacc Mon Sep 17 00:00:00 2001
From: nssrikanth <75025422+nssrikanth@users.noreply.github.com>
Date: Tue, 2 Mar 2021 23:57:27 +0530
Subject: [PATCH 35/38] Cancel TRIM / initialize on FAULTED non-writeable vdevs

When a device which is actively trimming or initializing becomes
FAULTED, and therefore no longer writable, cancel the active
TRIM or initialization.  When the device is merely taken offline
with `zpool offline` then stop the operation but do not cancel it.
When the device is brought back online the operation will be
resumed if possible.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Vipin Kumar Verma <vipin.verma@hpe.com>
Signed-off-by: Srikanth N S <srikanth.nagasubbaraoseetharaman@hpe.com>
Closes #11588
---
 module/zfs/vdev_initialize.c                  | 10 ++-
 module/zfs/vdev_trim.c                        | 15 +++--
 tests/runfiles/common.run                     |  2 +
 .../cli_root/zpool_initialize/Makefile.am     |  1 +
 ..._initialize_fault_export_import_online.ksh | 59 ++++++++++++++++++
 .../cli_root/zpool_trim/Makefile.am           |  1 +
 .../zpool_trim_fault_export_import_online.ksh | 62 +++++++++++++++++++
 7 files changed, 144 insertions(+), 6 deletions(-)
 create mode 100755 tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh
 create mode 100755 tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_fault_export_import_online.ksh

Index: zfs/module/zfs/vdev_initialize.c
===================================================================
--- zfs.orig/module/zfs/vdev_initialize.c
+++ zfs/module/zfs/vdev_initialize.c
@@ -536,8 +536,14 @@ vdev_initialize_thread(void *arg)
 	vd->vdev_initialize_tree = NULL;
 
 	mutex_enter(&vd->vdev_initialize_lock);
-	if (!vd->vdev_initialize_exit_wanted && vdev_writeable(vd)) {
-		vdev_initialize_change_state(vd, VDEV_INITIALIZE_COMPLETE);
+	if (!vd->vdev_initialize_exit_wanted) {
+		if (vdev_writeable(vd)) {
+			vdev_initialize_change_state(vd,
+			    VDEV_INITIALIZE_COMPLETE);
+		} else if (vd->vdev_faulted) {
+			vdev_initialize_change_state(vd,
+			    VDEV_INITIALIZE_CANCELED);
+		}
 	}
 	ASSERT(vd->vdev_initialize_thread != NULL ||
 	    vd->vdev_initialize_inflight == 0);
Index: zfs/module/zfs/vdev_trim.c
===================================================================
--- zfs.orig/module/zfs/vdev_trim.c
+++ zfs/module/zfs/vdev_trim.c
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2016 by Delphix. All rights reserved.
  * Copyright (c) 2019 by Lawrence Livermore National Security, LLC.
+ * Copyright (c) 2021 Hewlett Packard Enterprise Development LP
  */
 
 #include <sys/spa.h>
@@ -911,10 +912,16 @@ vdev_trim_thread(void *arg)
 	range_tree_destroy(ta.trim_tree);
 
 	mutex_enter(&vd->vdev_trim_lock);
-	if (!vd->vdev_trim_exit_wanted && vdev_writeable(vd)) {
-		vdev_trim_change_state(vd, VDEV_TRIM_COMPLETE,
-		    vd->vdev_trim_rate, vd->vdev_trim_partial,
-		    vd->vdev_trim_secure);
+	if (!vd->vdev_trim_exit_wanted) {
+		if (vdev_writeable(vd)) {
+			vdev_trim_change_state(vd, VDEV_TRIM_COMPLETE,
+			    vd->vdev_trim_rate, vd->vdev_trim_partial,
+			    vd->vdev_trim_secure);
+		} else if (vd->vdev_faulted) {
+			vdev_trim_change_state(vd, VDEV_TRIM_CANCELED,
+			    vd->vdev_trim_rate, vd->vdev_trim_partial,
+			    vd->vdev_trim_secure);
+		}
 	}
 	ASSERT(vd->vdev_trim_thread != NULL || vd->vdev_trim_inflight[0] == 0);
 
Index: zfs/tests/runfiles/common.run
===================================================================
--- zfs.orig/tests/runfiles/common.run
+++ zfs/tests/runfiles/common.run
@@ -410,6 +410,7 @@ tags = ['functional', 'cli_root', 'zpool
 
 [tests/functional/cli_root/zpool_initialize]
 tests = ['zpool_initialize_attach_detach_add_remove',
+    'zpool_initialize_fault_export_import_online',
     'zpool_initialize_import_export',
     'zpool_initialize_offline_export_import_online',
     'zpool_initialize_online_offline',
@@ -474,6 +475,7 @@ tags = ['functional', 'cli_root', 'zpool
 
 [tests/functional/cli_root/zpool_trim]
 tests = ['zpool_trim_attach_detach_add_remove',
+    'zpool_trim_fault_export_import_online',
     'zpool_trim_import_export', 'zpool_trim_multiple', 'zpool_trim_neg',
     'zpool_trim_offline_export_import_online', 'zpool_trim_online_offline',
     'zpool_trim_partial', 'zpool_trim_rate', 'zpool_trim_rate_neg',
Index: zfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am
===================================================================
--- zfs.orig/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am
+++ zfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/Makefile.am
@@ -2,6 +2,7 @@ pkgdatadir = $(datadir)/@PACKAGE@/zfs-te
 dist_pkgdata_SCRIPTS = \
 	cleanup.ksh \
 	zpool_initialize_attach_detach_add_remove.ksh \
+	zpool_initialize_fault_export_import_online.ksh \
 	zpool_initialize_import_export.ksh \
 	zpool_initialize_offline_export_import_online.ksh \
 	zpool_initialize_online_offline.ksh \
Index: zfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh
===================================================================
--- /dev/null
+++ zfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh
@@ -0,0 +1,59 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2021 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Miscellaneous complex sequences of operations function as expected.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start initializing, fault, export, import, online and verify along
+#    the way that the initializing was cancelled and not restarted.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool initialize $TESTPOOL $DISK1
+progress="$(initialize_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Initializing did not start"
+
+log_must zpool offline -f $TESTPOOL $DISK1
+log_must check_vdev_state $TESTPOOL $DISK1 "FAULTED"
+log_must eval "zpool status -i $TESTPOOL | grep $DISK1 | grep uninitialized"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+log_must check_vdev_state $TESTPOOL $DISK1 "FAULTED"
+log_must eval "zpool status -i $TESTPOOL | grep $DISK1 | grep uninitialized"
+
+log_must zpool online $TESTPOOL $DISK1
+log_must zpool clear $TESTPOOL $DISK1
+log_must check_vdev_state $TESTPOOL $DISK1 "ONLINE"
+log_must eval "zpool status -i $TESTPOOL | grep $DISK1 | grep uninitialized"
+
+log_pass "Initializing behaves as expected at each step of:" \
+    "initialize + fault + export + import + online"
Index: zfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am
===================================================================
--- zfs.orig/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am
+++ zfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/Makefile.am
@@ -3,6 +3,7 @@ dist_pkgdata_SCRIPTS = \
 	setup.ksh \
 	cleanup.ksh \
 	zpool_trim_attach_detach_add_remove.ksh \
+	zpool_trim_fault_export_import_online.ksh \
 	zpool_trim_import_export.ksh \
 	zpool_trim_multiple.ksh \
 	zpool_trim_neg.ksh \
Index: zfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_fault_export_import_online.ksh
===================================================================
--- /dev/null
+++ zfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_fault_export_import_online.ksh
@@ -0,0 +1,62 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2021 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Miscellaneous complex sequences of operations function as expected.
+#
+# STRATEGY:
+# 1. Create a pool with a two-way mirror.
+# 2. Start trimming, fault, export, import, online and verify along
+#    the way that the trim was cancelled and not restarted.
+#
+
+DISK1="$(echo $DISKS | cut -d' ' -f1)"
+DISK2="$(echo $DISKS | cut -d' ' -f2)"
+
+log_must zpool create -f $TESTPOOL mirror $DISK1 $DISK2
+
+log_must zpool trim -r 128M $TESTPOOL $DISK1
+progress="$(trim_progress $TESTPOOL $DISK1)"
+[[ -z "$progress" ]] && log_fail "Trimming did not start"
+
+log_must zpool offline -f $TESTPOOL $DISK1
+log_must check_vdev_state $TESTPOOL $DISK1 "FAULTED"
+log_must eval "zpool status -t $TESTPOOL | grep $DISK1 | grep untrimmed"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+# Note: the expected state here is unsupported since the faulted device
+# cannot be checked to determine if it supports TRIM.
+log_must check_vdev_state $TESTPOOL $DISK1 "FAULTED"
+log_must eval "zpool status -t $TESTPOOL | grep $DISK1 | grep unsupported"
+
+log_must zpool online $TESTPOOL $DISK1
+log_must zpool clear $TESTPOOL $DISK1
+log_must check_vdev_state $TESTPOOL $DISK1 "ONLINE"
+log_must eval "zpool status -t $TESTPOOL | grep $DISK1 | grep untrimmed"
+
+log_pass "Trimming behaves as expected at each step of:" \
+    "trim + fault + export + import + online"
