Commit a8610297 authored by Fan Yong's avatar Fan Yong Committed by Greg Kroah-Hartman

staging: lustre: obdclass: bug fixes for lu_device_type handling

There was no protection when inc/dec lu_device_type::ldt_device_nr,
which may caused the ldt_device_nr to be wrong and trigger assert.
This patch redefine lu_device_type::ldt_device_nr as atomic type.

There was no protection when add/del lu_device_type::ldt_linkage
into/from the global lu_device_types list, which may caused bad
address accessing. This patch uses the existing obd_types_lock
to protect related operations.

We do NOT need lu_types_stop() any longer. Such function scans
the global lu_device_types list, and for each type item on it
which has zerod lu_device_type::ldt_device_nr, call its stop()
method. In fact, the lu_device_type::ldt_device_nr only will be
zero when the last lu_device_fini() is called, and at that time,
inside the lu_device_fini(), its stop() method will be called.
So it is unnecessary to call the stop() again via lu_types_stop().
Signed-off-by: default avatarFan Yong <fan.yong@intel.com>
Intel-bug-id: https://jira.hpdd.intel.com/browse/LU-4604
Reviewed-on: http://review.whamcloud.com/8694Reviewed-by: default avatarJian Yu <jian.yu@intel.com>
Reviewed-by: default avatarAndreas Dilger <andreas.dilger@intel.com>
Reviewed-by: default avatarOleg Drokin <oleg.drokin@intel.com>
Signed-off-by: default avatarJames Simmons <jsimmons@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f4ba0420
...@@ -327,7 +327,7 @@ struct lu_device_type { ...@@ -327,7 +327,7 @@ struct lu_device_type {
/** /**
* Number of existing device type instances. * Number of existing device type instances.
*/ */
unsigned ldt_device_nr; atomic_t ldt_device_nr;
/** /**
* Linkage into a global list of all device types. * Linkage into a global list of all device types.
* *
...@@ -673,7 +673,6 @@ void lu_object_add(struct lu_object *before, struct lu_object *o); ...@@ -673,7 +673,6 @@ void lu_object_add(struct lu_object *before, struct lu_object *o);
int lu_device_type_init(struct lu_device_type *ldt); int lu_device_type_init(struct lu_device_type *ldt);
void lu_device_type_fini(struct lu_device_type *ldt); void lu_device_type_fini(struct lu_device_type *ldt);
void lu_types_stop(void);
/** @} ctors */ /** @} ctors */
......
...@@ -368,12 +368,6 @@ int cl_sb_fini(struct super_block *sb) ...@@ -368,12 +368,6 @@ int cl_sb_fini(struct super_block *sb)
CERROR("Cannot cleanup cl-stack due to memory shortage.\n"); CERROR("Cannot cleanup cl-stack due to memory shortage.\n");
result = PTR_ERR(env); result = PTR_ERR(env);
} }
/*
* If mount failed (sbi->ll_cl == NULL), and this there are no other
* mounts, stop device types manually (this usually happens
* automatically when last device is destroyed).
*/
lu_types_stop();
return result; return result;
} }
......
...@@ -726,34 +726,31 @@ int lu_device_type_init(struct lu_device_type *ldt) ...@@ -726,34 +726,31 @@ int lu_device_type_init(struct lu_device_type *ldt)
{ {
int result = 0; int result = 0;
atomic_set(&ldt->ldt_device_nr, 0);
INIT_LIST_HEAD(&ldt->ldt_linkage); INIT_LIST_HEAD(&ldt->ldt_linkage);
if (ldt->ldt_ops->ldto_init) if (ldt->ldt_ops->ldto_init)
result = ldt->ldt_ops->ldto_init(ldt); result = ldt->ldt_ops->ldto_init(ldt);
if (result == 0)
if (!result) {
spin_lock(&obd_types_lock);
list_add(&ldt->ldt_linkage, &lu_device_types); list_add(&ldt->ldt_linkage, &lu_device_types);
spin_unlock(&obd_types_lock);
}
return result; return result;
} }
EXPORT_SYMBOL(lu_device_type_init); EXPORT_SYMBOL(lu_device_type_init);
void lu_device_type_fini(struct lu_device_type *ldt) void lu_device_type_fini(struct lu_device_type *ldt)
{ {
spin_lock(&obd_types_lock);
list_del_init(&ldt->ldt_linkage); list_del_init(&ldt->ldt_linkage);
spin_unlock(&obd_types_lock);
if (ldt->ldt_ops->ldto_fini) if (ldt->ldt_ops->ldto_fini)
ldt->ldt_ops->ldto_fini(ldt); ldt->ldt_ops->ldto_fini(ldt);
} }
EXPORT_SYMBOL(lu_device_type_fini); EXPORT_SYMBOL(lu_device_type_fini);
void lu_types_stop(void)
{
struct lu_device_type *ldt;
list_for_each_entry(ldt, &lu_device_types, ldt_linkage) {
if (ldt->ldt_device_nr == 0 && ldt->ldt_ops->ldto_stop)
ldt->ldt_ops->ldto_stop(ldt);
}
}
EXPORT_SYMBOL(lu_types_stop);
/** /**
* Global list of all sites on this node * Global list of all sites on this node
*/ */
...@@ -1082,8 +1079,10 @@ EXPORT_SYMBOL(lu_device_put); ...@@ -1082,8 +1079,10 @@ EXPORT_SYMBOL(lu_device_put);
*/ */
int lu_device_init(struct lu_device *d, struct lu_device_type *t) int lu_device_init(struct lu_device *d, struct lu_device_type *t)
{ {
if (t->ldt_device_nr++ == 0 && t->ldt_ops->ldto_start) if (atomic_inc_return(&t->ldt_device_nr) == 1 &&
t->ldt_ops->ldto_start)
t->ldt_ops->ldto_start(t); t->ldt_ops->ldto_start(t);
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));
atomic_set(&d->ld_ref, 0); atomic_set(&d->ld_ref, 0);
d->ld_type = t; d->ld_type = t;
...@@ -1098,9 +1097,8 @@ EXPORT_SYMBOL(lu_device_init); ...@@ -1098,9 +1097,8 @@ EXPORT_SYMBOL(lu_device_init);
*/ */
void lu_device_fini(struct lu_device *d) void lu_device_fini(struct lu_device *d)
{ {
struct lu_device_type *t; struct lu_device_type *t = d->ld_type;
t = d->ld_type;
if (d->ld_obd) { if (d->ld_obd) {
d->ld_obd->obd_lu_dev = NULL; d->ld_obd->obd_lu_dev = NULL;
d->ld_obd = NULL; d->ld_obd = NULL;
...@@ -1109,8 +1107,10 @@ void lu_device_fini(struct lu_device *d) ...@@ -1109,8 +1107,10 @@ void lu_device_fini(struct lu_device *d)
lu_ref_fini(&d->ld_reference); lu_ref_fini(&d->ld_reference);
LASSERTF(atomic_read(&d->ld_ref) == 0, LASSERTF(atomic_read(&d->ld_ref) == 0,
"Refcount is %u\n", atomic_read(&d->ld_ref)); "Refcount is %u\n", atomic_read(&d->ld_ref));
LASSERT(t->ldt_device_nr > 0); LASSERT(atomic_read(&t->ldt_device_nr) > 0);
if (--t->ldt_device_nr == 0 && t->ldt_ops->ldto_stop)
if (atomic_dec_and_test(&t->ldt_device_nr) &&
t->ldt_ops->ldto_stop)
t->ldt_ops->ldto_stop(t); t->ldt_ops->ldto_stop(t);
} }
EXPORT_SYMBOL(lu_device_fini); EXPORT_SYMBOL(lu_device_fini);
......
...@@ -670,7 +670,6 @@ int lustre_common_put_super(struct super_block *sb) ...@@ -670,7 +670,6 @@ int lustre_common_put_super(struct super_block *sb)
} }
/* Drop a ref to the mounted disk */ /* Drop a ref to the mounted disk */
lustre_put_lsi(sb); lustre_put_lsi(sb);
lu_types_stop();
return rc; return rc;
} }
EXPORT_SYMBOL(lustre_common_put_super); EXPORT_SYMBOL(lustre_common_put_super);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment