[lustre-devel] [PATCH 20/21] lustre: obdclass: fix module load locking.

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


Safe module loading requires that we try_module_get() in a context
where the module cannot be unloaded, typically prodected by
a spinlock that module-unload has to take.
This doesn't currently happen in class_get_type().

There is a per-type spinlock, but it is almost entirely unused, and
cannot be used to protect the module from being unloaded.

So discard ->obd_type_lock, and ensure that __class_search_type() and
try_module_get() are both called while obd_types_lock is held - this
prevent class_unregister_type() from completing (so the 'type' won't get
freed.  That is always called from a module-unload function - if it
has got that far, try_module_get() will fail.

So also check the return status of try_module_get().

Signed-off-by: NeilBrown <neilb at suse.com>
---
 drivers/staging/lustre/lustre/include/obd.h     |    1 -
 drivers/staging/lustre/lustre/obdclass/genops.c |   24 ++++++++++++++---------
 2 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index 171d2c214be6..463ab680b524 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -106,7 +106,6 @@ struct obd_type {
 	char			*typ_name;
 	int			 typ_refcnt;
 	struct lu_device_type	*typ_lu;
-	spinlock_t		 obd_type_lock;
 	struct kobject		*typ_kobj;
 };
 
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index a174f538dd0d..dad21d9fa328 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -109,35 +109,42 @@ static struct obd_type *class_search_type(const char *name)
 
 static struct obd_type *class_get_type(const char *name)
 {
-	struct obd_type *type = class_search_type(name);
+	struct obd_type *type;
+
+	spin_lock(&obd_types_lock);
+	type = __class_search_type(name);
 
 	if (!type) {
 		const char *modname = name;
 
+		spin_unlock(&obd_types_lock);
 		if (!request_module("%s", modname)) {
 			CDEBUG(D_INFO, "Loaded module '%s'\n", modname);
-			type = class_search_type(name);
 		} else {
 			LCONSOLE_ERROR_MSG(0x158, "Can't load module '%s'\n",
 					   modname);
 		}
+		spin_lock(&obd_types_lock);
+		type = __class_search_type(name);
 	}
 	if (type) {
-		spin_lock(&type->obd_type_lock);
-		type->typ_refcnt++;
-		try_module_get(type->typ_dt_ops->owner);
-		spin_unlock(&type->obd_type_lock);
+		if (try_module_get(type->typ_dt_ops->owner))
+			type->typ_refcnt++;
+		else
+			type = NULL;
 	}
+	spin_unlock(&obd_types_lock);
 	return type;
 }
 
 void class_put_type(struct obd_type *type)
 {
 	LASSERT(type);
-	spin_lock(&type->obd_type_lock);
+	spin_lock(&obd_types_lock);
+	LASSERT(type->typ_refcnt > 0);
 	type->typ_refcnt--;
 	module_put(type->typ_dt_ops->owner);
-	spin_unlock(&type->obd_type_lock);
+	spin_unlock(&obd_types_lock);
 }
 
 static void class_sysfs_release(struct kobject *kobj)
@@ -206,7 +213,6 @@ int class_register_type(struct obd_ops *dt_ops, struct md_ops *md_ops,
 	if (md_ops)
 		*type->typ_md_ops = *md_ops;
 	strcpy(type->typ_name, name);
-	spin_lock_init(&type->obd_type_lock);
 
 	type->typ_debugfs_entry = debugfs_create_dir(type->typ_name,
 						     debugfs_lustre_root);




More information about the lustre-devel mailing list