aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2014-12-08 06:04:42 +0000
committerXin LI <delphij@FreeBSD.org>2014-12-08 06:04:42 +0000
commitc2161091ad3723e6b6bf7a6bd982bd8a5ab5dda8 (patch)
tree6ce5967ded79329e9e434dc5a52ba4ea190af5a3
parentd6ad6a865a9b9e0b33ed2af9f1774eb20666c91c (diff)
parent6e0d888ba8300d9c22454e580d2037feee85d884 (diff)
downloadsrc-c2161091ad3723e6b6bf7a6bd982bd8a5ab5dda8.tar.gz
src-c2161091ad3723e6b6bf7a6bd982bd8a5ab5dda8.zip
MFV r275540:
When importing a pool, don't assume that the passed pool configuration at vdev_load is always vaild. It's possible that a stale configuration that comes with extra vdevs, where metaslab_init() would fail because of lower layer returns error. Change the code to make metaslab_init() handle and return errors from lower layer and pass it back to upper layer and handle it there. Illumos issue: 5213 panic in metaslab_init due to space_map_open returning ENXIO MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=275594
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c56
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c6
3 files changed, 40 insertions, 26 deletions
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
index 9e53f08a6806..c565e8b8fbd5 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
@@ -1297,28 +1297,36 @@ metaslab_unload(metaslab_t *msp)
msp->ms_weight &= ~METASLAB_ACTIVE_MASK;
}
-metaslab_t *
-metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
+int
+metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg,
+ metaslab_t **msp)
{
vdev_t *vd = mg->mg_vd;
objset_t *mos = vd->vdev_spa->spa_meta_objset;
- metaslab_t *msp;
+ metaslab_t *ms;
+ int error;
- msp = kmem_zalloc(sizeof (metaslab_t), KM_SLEEP);
- mutex_init(&msp->ms_lock, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&msp->ms_load_cv, NULL, CV_DEFAULT, NULL);
- msp->ms_id = id;
- msp->ms_start = id << vd->vdev_ms_shift;
- msp->ms_size = 1ULL << vd->vdev_ms_shift;
+ ms = kmem_zalloc(sizeof (metaslab_t), KM_SLEEP);
+ mutex_init(&ms->ms_lock, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&ms->ms_load_cv, NULL, CV_DEFAULT, NULL);
+ ms->ms_id = id;
+ ms->ms_start = id << vd->vdev_ms_shift;
+ ms->ms_size = 1ULL << vd->vdev_ms_shift;
/*
* We only open space map objects that already exist. All others
* will be opened when we finally allocate an object for it.
*/
if (object != 0) {
- VERIFY0(space_map_open(&msp->ms_sm, mos, object, msp->ms_start,
- msp->ms_size, vd->vdev_ashift, &msp->ms_lock));
- ASSERT(msp->ms_sm != NULL);
+ error = space_map_open(&ms->ms_sm, mos, object, ms->ms_start,
+ ms->ms_size, vd->vdev_ashift, &ms->ms_lock);
+
+ if (error != 0) {
+ kmem_free(ms, sizeof (metaslab_t));
+ return (error);
+ }
+
+ ASSERT(ms->ms_sm != NULL);
}
/*
@@ -1328,11 +1336,11 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
* addition of new space; and for debugging, it ensures that we'd
* data fault on any attempt to use this metaslab before it's ready.
*/
- msp->ms_tree = range_tree_create(&metaslab_rt_ops, msp, &msp->ms_lock);
- metaslab_group_add(mg, msp);
+ ms->ms_tree = range_tree_create(&metaslab_rt_ops, ms, &ms->ms_lock);
+ metaslab_group_add(mg, ms);
- msp->ms_fragmentation = metaslab_fragmentation(msp);
- msp->ms_ops = mg->mg_class->mc_ops;
+ ms->ms_fragmentation = metaslab_fragmentation(ms);
+ ms->ms_ops = mg->mg_class->mc_ops;
/*
* If we're opening an existing pool (txg == 0) or creating
@@ -1341,25 +1349,27 @@ metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg)
* does not become available until after this txg has synced.
*/
if (txg <= TXG_INITIAL)
- metaslab_sync_done(msp, 0);
+ metaslab_sync_done(ms, 0);
/*
* If metaslab_debug_load is set and we're initializing a metaslab
* that has an allocated space_map object then load the its space
* map so that can verify frees.
*/
- if (metaslab_debug_load && msp->ms_sm != NULL) {
- mutex_enter(&msp->ms_lock);
- VERIFY0(metaslab_load(msp));
- mutex_exit(&msp->ms_lock);
+ if (metaslab_debug_load && ms->ms_sm != NULL) {
+ mutex_enter(&ms->ms_lock);
+ VERIFY0(metaslab_load(ms));
+ mutex_exit(&ms->ms_lock);
}
if (txg != 0) {
vdev_dirty(vd, 0, NULL, txg);
- vdev_dirty(vd, VDD_METASLAB, msp, txg);
+ vdev_dirty(vd, VDD_METASLAB, ms, txg);
}
- return (msp);
+ *msp = ms;
+
+ return (0);
}
void
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h
index deefb196fdef..74031f15ebe9 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/metaslab.h
@@ -42,8 +42,8 @@ typedef struct metaslab_ops {
extern metaslab_ops_t *zfs_metaslab_ops;
-metaslab_t *metaslab_init(metaslab_group_t *, uint64_t,
- uint64_t, uint64_t);
+int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
+ metaslab_t **);
void metaslab_fini(metaslab_t *);
void metaslab_load_wait(metaslab_t *);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
index a9cd4f0de199..55070eded5c7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
@@ -955,7 +955,11 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
if (error)
return (error);
}
- vd->vdev_ms[m] = metaslab_init(vd->vdev_mg, m, object, txg);
+
+ error = metaslab_init(vd->vdev_mg, m, object, txg,
+ &(vd->vdev_ms[m]));
+ if (error)
+ return (error);
}
if (txg == 0)