changeset 9846:6527c7b4a92e

6566744 vdev_open() should be done in parallel
author Eric Taylor <Eric.Taylor@Sun.COM>
date Thu, 11 Jun 2009 11:10:31 -0600
parents 0d705da26956
children 2f3ba86e857a
files usr/src/uts/common/fs/zfs/spa_misc.c usr/src/uts/common/fs/zfs/sys/vdev.h usr/src/uts/common/fs/zfs/sys/vdev_impl.h usr/src/uts/common/fs/zfs/vdev.c usr/src/uts/common/fs/zfs/vdev_label.c usr/src/uts/common/fs/zfs/vdev_mirror.c usr/src/uts/common/fs/zfs/vdev_raidz.c usr/src/uts/common/fs/zfs/vdev_root.c
diffstat 8 files changed, 65 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/spa_misc.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/spa_misc.c	Thu Jun 11 11:10:31 2009 -0600
@@ -310,8 +310,12 @@
 void
 spa_config_enter(spa_t *spa, int locks, void *tag, krw_t rw)
 {
+	int wlocks_held = 0;
+
 	for (int i = 0; i < SCL_LOCKS; i++) {
 		spa_config_lock_t *scl = &spa->spa_config_lock[i];
+		if (scl->scl_writer == curthread)
+			wlocks_held |= (1 << i);
 		if (!(locks & (1 << i)))
 			continue;
 		mutex_enter(&scl->scl_lock);
@@ -331,6 +335,7 @@
 		(void) refcount_add(&scl->scl_count, tag);
 		mutex_exit(&scl->scl_lock);
 	}
+	ASSERT(wlocks_held <= locks);
 }
 
 void
--- a/usr/src/uts/common/fs/zfs/sys/vdev.h	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/vdev.h	Thu Jun 11 11:10:31 2009 -0600
@@ -47,6 +47,7 @@
 extern boolean_t zfs_nocacheflush;
 
 extern int vdev_open(vdev_t *);
+extern void vdev_open_children(vdev_t *vd);
 extern int vdev_validate(vdev_t *);
 extern void vdev_close(vdev_t *);
 extern int vdev_create(vdev_t *, uint64_t txg, boolean_t isreplace);
--- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h	Thu Jun 11 11:10:31 2009 -0600
@@ -127,6 +127,8 @@
 	space_map_t	vdev_dtl[DTL_TYPES]; /* in-core dirty time logs	*/
 	vdev_stat_t	vdev_stat;	/* virtual device statistics	*/
 	boolean_t	vdev_expanding;	/* expand the vdev?		*/
+	int		vdev_open_error; /* error on last open		*/
+	kthread_t	*vdev_open_thread; /* thread opening children	*/
 
 	/*
 	 * Top-level vdev state.
--- a/usr/src/uts/common/fs/zfs/vdev.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev.c	Thu Jun 11 11:10:31 2009 -0600
@@ -993,6 +993,32 @@
 	return (NULL);
 }
 
+static void
+vdev_open_child(void *arg)
+{
+	vdev_t *vd = arg;
+
+	vd->vdev_open_thread = curthread;
+	vd->vdev_open_error = vdev_open(vd);
+	vd->vdev_open_thread = NULL;
+}
+
+void
+vdev_open_children(vdev_t *vd)
+{
+	taskq_t *tq;
+	int children = vd->vdev_children;
+
+	tq = taskq_create("vdev_open", children, minclsyspri,
+	    children, children, TASKQ_PREPOPULATE);
+
+	for (int c = 0; c < children; c++)
+		VERIFY(taskq_dispatch(tq, vdev_open_child, vd->vdev_child[c],
+		    TQ_SLEEP) != NULL);
+
+	taskq_destroy(tq);
+}
+
 /*
  * Prepare a virtual device for access.
  */
@@ -1005,8 +1031,8 @@
 	uint64_t asize, psize;
 	uint64_t ashift = 0;
 
-	ASSERT(spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL);
-
+	ASSERT(vd->vdev_open_thread == curthread ||
+	    spa_config_held(spa, SCL_STATE_ALL, RW_WRITER) == SCL_STATE_ALL);
 	ASSERT(vd->vdev_state == VDEV_STATE_CLOSED ||
 	    vd->vdev_state == VDEV_STATE_CANT_OPEN ||
 	    vd->vdev_state == VDEV_STATE_OFFLINE);
--- a/usr/src/uts/common/fs/zfs/vdev_label.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_label.c	Thu Jun 11 11:10:31 2009 -0600
@@ -642,8 +642,8 @@
 	/*
 	 * Initialize uberblock template.
 	 */
-	ub = zio_buf_alloc(VDEV_UBERBLOCK_SIZE(vd));
-	bzero(ub, VDEV_UBERBLOCK_SIZE(vd));
+	ub = zio_buf_alloc(VDEV_UBERBLOCK_RING);
+	bzero(ub, VDEV_UBERBLOCK_RING);
 	*ub = spa->spa_uberblock;
 	ub->ub_txg = 0;
 
@@ -672,11 +672,9 @@
 		    offsetof(vdev_label_t, vl_pad2),
 		    VDEV_PAD_SIZE, NULL, NULL, flags);
 
-		for (int n = 0; n < VDEV_UBERBLOCK_COUNT(vd); n++) {
-			vdev_label_write(zio, vd, l, ub,
-			    VDEV_UBERBLOCK_OFFSET(vd, n),
-			    VDEV_UBERBLOCK_SIZE(vd), NULL, NULL, flags);
-		}
+		vdev_label_write(zio, vd, l, ub,
+		    offsetof(vdev_label_t, vl_uberblock),
+		    VDEV_UBERBLOCK_RING, NULL, NULL, flags);
 	}
 
 	error = zio_wait(zio);
@@ -688,7 +686,7 @@
 
 	nvlist_free(label);
 	zio_buf_free(pad2, VDEV_PAD_SIZE);
-	zio_buf_free(ub, VDEV_UBERBLOCK_SIZE(vd));
+	zio_buf_free(ub, VDEV_UBERBLOCK_RING);
 	zio_buf_free(vp, sizeof (vdev_phys_t));
 
 	/*
--- a/usr/src/uts/common/fs/zfs/vdev_mirror.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_mirror.c	Thu Jun 11 11:10:31 2009 -0600
@@ -124,21 +124,21 @@
 static int
 vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
 {
-	vdev_t *cvd;
-	uint64_t c;
 	int numerrors = 0;
-	int ret, lasterror = 0;
+	int lasterror = 0;
 
 	if (vd->vdev_children == 0) {
 		vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
 		return (EINVAL);
 	}
 
-	for (c = 0; c < vd->vdev_children; c++) {
-		cvd = vd->vdev_child[c];
+	vdev_open_children(vd);
 
-		if ((ret = vdev_open(cvd)) != 0) {
-			lasterror = ret;
+	for (int c = 0; c < vd->vdev_children; c++) {
+		vdev_t *cvd = vd->vdev_child[c];
+
+		if (cvd->vdev_open_error) {
+			lasterror = cvd->vdev_open_error;
 			numerrors++;
 			continue;
 		}
@@ -158,9 +158,7 @@
 static void
 vdev_mirror_close(vdev_t *vd)
 {
-	uint64_t c;
-
-	for (c = 0; c < vd->vdev_children; c++)
+	for (int c = 0; c < vd->vdev_children; c++)
 		vdev_close(vd->vdev_child[c]);
 }
 
--- a/usr/src/uts/common/fs/zfs/vdev_raidz.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_raidz.c	Thu Jun 11 11:10:31 2009 -0600
@@ -559,9 +559,7 @@
 static int
 vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
 {
-	vdev_t *cvd;
 	uint64_t nparity = vd->vdev_nparity;
-	int c, error;
 	int lasterror = 0;
 	int numerrors = 0;
 
@@ -573,11 +571,13 @@
 		return (EINVAL);
 	}
 
-	for (c = 0; c < vd->vdev_children; c++) {
-		cvd = vd->vdev_child[c];
+	vdev_open_children(vd);
 
-		if ((error = vdev_open(cvd)) != 0) {
-			lasterror = error;
+	for (int c = 0; c < vd->vdev_children; c++) {
+		vdev_t *cvd = vd->vdev_child[c];
+
+		if (cvd->vdev_open_error) {
+			lasterror = cvd->vdev_open_error;
 			numerrors++;
 			continue;
 		}
@@ -599,9 +599,7 @@
 static void
 vdev_raidz_close(vdev_t *vd)
 {
-	int c;
-
-	for (c = 0; c < vd->vdev_children; c++)
+	for (int c = 0; c < vd->vdev_children; c++)
 		vdev_close(vd->vdev_child[c]);
 }
 
--- a/usr/src/uts/common/fs/zfs/vdev_root.c	Thu Jun 11 05:00:01 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/vdev_root.c	Thu Jun 11 11:10:31 2009 -0600
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -52,7 +52,6 @@
 static int
 vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift)
 {
-	int c;
 	int lasterror = 0;
 	int numerrors = 0;
 
@@ -61,15 +60,14 @@
 		return (EINVAL);
 	}
 
-	for (c = 0; c < vd->vdev_children; c++) {
-		vdev_t *cvd = vd->vdev_child[c];
-		int error;
+	vdev_open_children(vd);
 
-		if ((error = vdev_open(cvd)) != 0 &&
-		    !cvd->vdev_islog) {
-			lasterror = error;
+	for (int c = 0; c < vd->vdev_children; c++) {
+		vdev_t *cvd = vd->vdev_child[c];
+
+		if (cvd->vdev_open_error && !cvd->vdev_islog) {
+			lasterror = cvd->vdev_open_error;
 			numerrors++;
-			continue;
 		}
 	}
 
@@ -87,9 +85,7 @@
 static void
 vdev_root_close(vdev_t *vd)
 {
-	int c;
-
-	for (c = 0; c < vd->vdev_children; c++)
+	for (int c = 0; c < vd->vdev_children; c++)
 		vdev_close(vd->vdev_child[c]);
 }