[lustre-devel] [PATCH 19/21] lustre: obdclass: avoid races in class_register_type()

NeilBrown neilb at suse.com
Wed Feb 6 16:03:33 PST 2019


If there are two parallel attempts to register the
same class name, it could get registered twice.
So re-check after allocation to make sure the name is
still unique.

Signed-off-by: NeilBrown <neilb at suse.com>
---
 drivers/staging/lustre/lustre/obdclass/genops.c |   29 +++++++++++++++--------
 1 file changed, 19 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index 382eaf519a79..a174f538dd0d 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -86,17 +86,23 @@ static void obd_device_free(struct obd_device *obd)
 	kmem_cache_free(obd_device_cachep, obd);
 }
 
-static struct obd_type *class_search_type(const char *name)
+static struct obd_type *__class_search_type(const char *name)
 {
 	struct obd_type *type;
 
-	spin_lock(&obd_types_lock);
 	list_for_each_entry(type, &obd_types, typ_chain) {
-		if (strcmp(type->typ_name, name) == 0) {
-			spin_unlock(&obd_types_lock);
+		if (strcmp(type->typ_name, name) == 0)
 			return type;
-		}
 	}
+	return NULL;
+}
+
+static struct obd_type *class_search_type(const char *name)
+{
+	struct obd_type *type;
+
+	spin_lock(&obd_types_lock);
+	type = __class_search_type(name);
 	spin_unlock(&obd_types_lock);
 	return NULL;
 }
@@ -214,19 +220,22 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 	if (ldt) {
 		type->typ_lu = ldt;
 		rc = lu_device_type_init(ldt);
-		if (rc != 0) {
-			kobject_put(type->typ_kobj);
+		if (rc != 0)
 			goto failed;
-		}
 	}
 
+	INIT_LIST_HEAD(&type->typ_chain);
 	spin_lock(&obd_types_lock);
-	list_add(&type->typ_chain, &obd_types);
+	if (__class_search_type(name) == NULL)
+		list_add(&type->typ_chain, &obd_types);
 	spin_unlock(&obd_types_lock);
 
-	return 0;
+	if (!list_empty(&type->typ_chain))
+		return 0;
 
 failed:
+	if (!IS_ERR_OR_NULL(type->typ_kobj))
+		kobject_put(type->typ_kobj);
 	kfree(type->typ_name);
 	kfree(type->typ_md_ops);
 	kfree(type->typ_dt_ops);




More information about the lustre-devel mailing list