Illumos 5213 - panic in metaslab_init due to space_map_open returning ENXIO

5213 panic in metaslab_init due to space_map_open returning ENXIO
Reviewed by: Matthew Ahrens mahrens@delphix.com
Reviewed by: George Wilson george.wilson@delphix.com

References:
  https://www.illumos.org/issues/5213
  https://reviews.csiden.org/r/110

Porting notes:

For the Linux port, KM_SLEEP was replaced with KM_PUSHPAGE.

Ported by: Turbo Fredriksson <turbo@bayour.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #2745
This commit is contained in:
Prakash Surya 2014-10-06 16:32:36 +02:00 committed by Brian Behlendorf
parent a82db4e15f
commit fb42a49328
3 changed files with 40 additions and 26 deletions

View File

@ -42,8 +42,8 @@ typedef struct metaslab_ops {
extern metaslab_ops_t *zfs_metaslab_ops; extern metaslab_ops_t *zfs_metaslab_ops;
metaslab_t *metaslab_init(metaslab_group_t *, uint64_t, int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t); metaslab_t **);
void metaslab_fini(metaslab_t *); void metaslab_fini(metaslab_t *);
void metaslab_load_wait(metaslab_t *); void metaslab_load_wait(metaslab_t *);

View File

@ -1237,28 +1237,36 @@ metaslab_unload(metaslab_t *msp)
msp->ms_weight &= ~METASLAB_ACTIVE_MASK; msp->ms_weight &= ~METASLAB_ACTIVE_MASK;
} }
metaslab_t * int
metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg) metaslab_init(metaslab_group_t *mg, uint64_t id, uint64_t object, uint64_t txg,
metaslab_t **msp)
{ {
vdev_t *vd = mg->mg_vd; vdev_t *vd = mg->mg_vd;
objset_t *mos = vd->vdev_spa->spa_meta_objset; objset_t *mos = vd->vdev_spa->spa_meta_objset;
metaslab_t *msp; metaslab_t *ms;
int error;
msp = kmem_zalloc(sizeof (metaslab_t), KM_PUSHPAGE); ms = kmem_zalloc(sizeof (metaslab_t), KM_PUSHPAGE);
mutex_init(&msp->ms_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&ms->ms_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&msp->ms_load_cv, NULL, CV_DEFAULT, NULL); cv_init(&ms->ms_load_cv, NULL, CV_DEFAULT, NULL);
msp->ms_id = id; ms->ms_id = id;
msp->ms_start = id << vd->vdev_ms_shift; ms->ms_start = id << vd->vdev_ms_shift;
msp->ms_size = 1ULL << vd->vdev_ms_shift; ms->ms_size = 1ULL << vd->vdev_ms_shift;
/* /*
* We only open space map objects that already exist. All others * We only open space map objects that already exist. All others
* will be opened when we finally allocate an object for it. * will be opened when we finally allocate an object for it.
*/ */
if (object != 0) { if (object != 0) {
VERIFY0(space_map_open(&msp->ms_sm, mos, object, msp->ms_start, error = space_map_open(&ms->ms_sm, mos, object, ms->ms_start,
msp->ms_size, vd->vdev_ashift, &msp->ms_lock)); ms->ms_size, vd->vdev_ashift, &ms->ms_lock);
ASSERT(msp->ms_sm != NULL);
if (error != 0) {
kmem_free(ms, sizeof (metaslab_t));
return (error);
}
ASSERT(ms->ms_sm != NULL);
} }
/* /*
@ -1268,11 +1276,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 * 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. * 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); ms->ms_tree = range_tree_create(&metaslab_rt_ops, ms, &ms->ms_lock);
metaslab_group_add(mg, msp); metaslab_group_add(mg, ms);
msp->ms_fragmentation = metaslab_fragmentation(msp); ms->ms_fragmentation = metaslab_fragmentation(ms);
msp->ms_ops = mg->mg_class->mc_ops; ms->ms_ops = mg->mg_class->mc_ops;
/* /*
* If we're opening an existing pool (txg == 0) or creating * If we're opening an existing pool (txg == 0) or creating
@ -1281,25 +1289,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. * does not become available until after this txg has synced.
*/ */
if (txg <= TXG_INITIAL) 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 * If metaslab_debug_load is set and we're initializing a metaslab
* that has an allocated space_map object then load the its space * that has an allocated space_map object then load the its space
* map so that can verify frees. * map so that can verify frees.
*/ */
if (metaslab_debug_load && msp->ms_sm != NULL) { if (metaslab_debug_load && ms->ms_sm != NULL) {
mutex_enter(&msp->ms_lock); mutex_enter(&ms->ms_lock);
VERIFY0(metaslab_load(msp)); VERIFY0(metaslab_load(ms));
mutex_exit(&msp->ms_lock); mutex_exit(&ms->ms_lock);
} }
if (txg != 0) { if (txg != 0) {
vdev_dirty(vd, 0, NULL, txg); 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 void

View File

@ -876,7 +876,11 @@ vdev_metaslab_init(vdev_t *vd, uint64_t txg)
if (error) if (error)
return (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) if (txg == 0)