changeset 13966:0e1d84ebb004

3578 transferring the freed map to the defer map should be constant time 3579 ztest trips assertion in metaslab_weight() Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: Dan Kimmel <dan.kimmel@delphix.com> Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Richard Elling <richard.elling@dey-sys.com> Approved by: Dan McDonald <danmcd@nexenta.com>
author George Wilson <george.wilson@delphix.com>
date Wed, 20 Feb 2013 13:30:36 -0800
parents 74a52e9ca211
children 92bec6d87f59
files usr/src/uts/common/fs/zfs/metaslab.c
diffstat 1 files changed, 27 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/metaslab.c	Tue Feb 19 15:34:49 2013 -0500
+++ b/usr/src/uts/common/fs/zfs/metaslab.c	Wed Feb 20 13:30:36 2013 -0800
@@ -814,6 +814,16 @@
 	ASSERT(MUTEX_HELD(&msp->ms_lock));
 
 	/*
+	 * This vdev is in the process of being removed so there is nothing
+	 * for us to do here.
+	 */
+	if (vd->vdev_removing) {
+		ASSERT0(smo->smo_alloc);
+		ASSERT0(vd->vdev_ms_shift);
+		return (0);
+	}
+
+	/*
 	 * The baseline weight is the metaslab's free space.
 	 */
 	space = sm->sm_size - smo->smo_alloc;
@@ -1193,8 +1203,8 @@
 	space_map_obj_t *smo = &msp->ms_smo;
 	space_map_obj_t *smosync = &msp->ms_smo_syncing;
 	space_map_t *sm = msp->ms_map;
-	space_map_t *freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
-	space_map_t *defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE];
+	space_map_t **freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
+	space_map_t **defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE];
 	metaslab_group_t *mg = msp->ms_group;
 	vdev_t *vd = mg->mg_vd;
 	int64_t alloc_delta, defer_delta;
@@ -1207,8 +1217,8 @@
 	 * If this metaslab is just becoming available, initialize its
 	 * allocmaps, freemaps, and defermap and add its capacity to the vdev.
 	 */
-	if (freed_map == NULL) {
-		ASSERT(defer_map == NULL);
+	if (*freed_map == NULL) {
+		ASSERT(*defer_map == NULL);
 		for (int t = 0; t < TXG_SIZE; t++) {
 			msp->ms_allocmap[t] = kmem_zalloc(sizeof (space_map_t),
 			    KM_SLEEP);
@@ -1227,14 +1237,14 @@
 			    sm->sm_size, sm->sm_shift, sm->sm_lock);
 		}
 
-		freed_map = msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
-		defer_map = msp->ms_defermap[txg % TXG_DEFER_SIZE];
+		freed_map = &msp->ms_freemap[TXG_CLEAN(txg) & TXG_MASK];
+		defer_map = &msp->ms_defermap[txg % TXG_DEFER_SIZE];
 
 		vdev_space_update(vd, 0, 0, sm->sm_size);
 	}
 
 	alloc_delta = smosync->smo_alloc - smo->smo_alloc;
-	defer_delta = freed_map->sm_space - defer_map->sm_space;
+	defer_delta = (*freed_map)->sm_space - (*defer_map)->sm_space;
 
 	vdev_space_update(vd, alloc_delta + defer_delta, defer_delta, 0);
 
@@ -1244,12 +1254,18 @@
 	/*
 	 * If there's a space_map_load() in progress, wait for it to complete
 	 * so that we have a consistent view of the in-core space map.
-	 * Then, add defer_map (oldest deferred frees) to this map and
-	 * transfer freed_map (this txg's frees) to defer_map.
 	 */
 	space_map_load_wait(sm);
-	space_map_vacate(defer_map, sm->sm_loaded ? space_map_free : NULL, sm);
-	space_map_vacate(freed_map, space_map_add, defer_map);
+
+	/*
+	 * Move the frees from the defer_map to this map (if it's loaded).
+	 * Swap the freed_map and the defer_map -- this is safe to do
+	 * because we've just emptied out the defer_map.
+	 */
+	space_map_vacate(*defer_map, sm->sm_loaded ? space_map_free : NULL, sm);
+	ASSERT0((*defer_map)->sm_space);
+	ASSERT0(avl_numnodes(&(*defer_map)->sm_root));
+	space_map_swap(freed_map, defer_map);
 
 	*smo = *smosync;