Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1808

kernel-2.6.18-238.el5.src.rpm

From: Jonathan Brassow <jbrassow@redhat.com>
Date: Tue, 12 Aug 2008 13:46:21 -0500
Subject: [md] remove internal mod refs fields from interface
Message-id: 1218566781.22247.30.camel@hydrogen
O-Subject: [RHEL 5.3 Patch 6 of 8]: device-mapper interface exposure (bz 429337)
Bugzilla: 429337
RH-Acked-by: Alasdair G Kergon <agk@redhat.com>

Patch: dm-log-make-module-use-tracking-internal.patch

 brassow

Remove internal module reference fields from the interface.

Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>

diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 0cd48e5..110549d 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -15,27 +15,44 @@
 
 #define DM_MSG_PREFIX "dirty region log"
 
+struct dm_dirty_log_internal {
+	struct dm_dirty_log_type *type;
+
+	struct list_head list;
+	long use;
+};
+
 static LIST_HEAD(_log_types);
 static DEFINE_SPINLOCK(_lock);
 
-static struct dm_dirty_log_type *_get_type(const char *type_name)
+static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name)
 {
-	struct dm_dirty_log_type *type;
+	struct dm_dirty_log_internal *log_type;
+
+	list_for_each_entry(log_type, &_log_types, list)
+		if (!strcmp(name, log_type->type->name))
+			return log_type;
+
+        return NULL;
+}
+
+static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name)
+{
+	struct dm_dirty_log_internal *log_type;
 
 	spin_lock(&_lock);
-	list_for_each_entry (type, &_log_types, list)
-		if (!strcmp(type_name, type->name)) {
-			if (!type->use_count && !try_module_get(type->module)){
-				spin_unlock(&_lock);
-				return NULL;
-			}
-			type->use_count++;
-			spin_unlock(&_lock);
-			return type;
-		}
+
+	log_type = __find_dirty_log_type(name);
+	if (log_type) {
+		if (!log_type->use && !try_module_get(log_type->type->module))
+			log_type = NULL;
+		else
+			log_type->use++;
+	}
 
 	spin_unlock(&_lock);
-	return NULL;
+
+	return log_type;
 }
 
 /*
@@ -64,11 +81,14 @@ static struct dm_dirty_log_type *_get_type(const char *type_name)
 static struct dm_dirty_log_type *get_type(const char *type_name)
 {
 	char *p, *type_name_dup;
-	struct dm_dirty_log_type *type;
+	struct dm_dirty_log_internal *log_type;
+
+	if (!type_name)
+		return NULL;
 
-	type = _get_type(type_name);
-	if (type)
-		return type;
+	log_type = _get_dirty_log_type(type_name);
+	if (log_type)
+		return log_type->type;
 
 	type_name_dup = kstrdup(type_name, GFP_KERNEL);
 	if (!type_name_dup) {
@@ -78,7 +98,7 @@ static struct dm_dirty_log_type *get_type(const char *type_name)
 	}
 
 	while (request_module("dm-log-%s", type_name_dup) ||
-	       !(type = _get_type(type_name))) {
+	       !(log_type = _get_dirty_log_type(type_name))) {
 		/* find the last '-' */
 		p = strrchr(type_name_dup, '-');
 		if (!p)
@@ -86,43 +106,88 @@ static struct dm_dirty_log_type *get_type(const char *type_name)
 		p[0] = '\0';
 	}
 
-	if (!type)
+	if (!log_type)
 		DMWARN("Module for logging type \"%s\" not found.", type_name);
 
 	kfree(type_name_dup);
 
-	return type;
+	return log_type ? log_type->type : NULL;
 }
 
 static void put_type(struct dm_dirty_log_type *type)
 {
+	struct dm_dirty_log_internal *log_type;
+
+	if (!type)
+		return;
+
 	spin_lock(&_lock);
-	if (!--type->use_count)
+	log_type = __find_dirty_log_type(type->name);
+	if (!log_type)
+		goto out;
+
+	if (!--log_type->use)
 		module_put(type->module);
+
+	BUG_ON(log_type->use < 0);
+out:
 	spin_unlock(&_lock);
 }
 
+static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type)
+{
+	struct dm_dirty_log_internal *log_type;
+
+	log_type = kzalloc(sizeof(*log_type), GFP_KERNEL);
+	if (log_type)
+		log_type->type = type;
+
+	return log_type;
+}
+
 int dm_dirty_log_type_register(struct dm_dirty_log_type *type)
 {
+	struct dm_dirty_log_internal *log_type;
+	int r = 0;
+
+	log_type = _alloc_dirty_log_type(type);
+	if (!log_type)
+		return -ENOMEM;
+
 	spin_lock(&_lock);
-	type->use_count = 0;
-	list_add(&type->list, &_log_types);
+	if (!__find_dirty_log_type(type->name))
+		list_add(&log_type->list, &_log_types);
+	else {
+		kfree(log_type);
+		r = -EEXIST;
+	}
 	spin_unlock(&_lock);
 
-	return 0;
+	return r;
 }
 EXPORT_SYMBOL(dm_dirty_log_type_register);
 
 int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type)
 {
+	struct dm_dirty_log_internal *log_type;
+
 	spin_lock(&_lock);
 
-	if (type->use_count)
-		DMWARN("Attempt to unregister a log type that is still in use");
-	else
-		list_del(&type->list);
+	log_type = __find_dirty_log_type(type->name);
+	if (!log_type) {
+		spin_unlock(&_lock);
+		return -EINVAL;
+	}
+
+	if (log_type->use) {
+		spin_unlock(&_lock);
+		return -ETXTBSY;
+	}
+
+	list_del(&log_type->list);
 
 	spin_unlock(&_lock);
+	kfree(log_type);
 
 	return 0;
 }
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h
index d3df7f3..e8f19d4 100644
--- a/drivers/md/dm-log.h
+++ b/drivers/md/dm-log.h
@@ -29,10 +29,8 @@ struct dm_dirty_log {
 
 struct dm_dirty_log_type {
 	uint64_t features;
-	struct list_head list;
 	const char *name;
 	struct module *module;
-	unsigned int use_count;
 	unsigned int flags;
 
 	int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti,