lkml.org 
[lkml]   [2002]   [Dec]   [23]   [last100]   RSS Feed
Views: [more markup]   [less markup]   [headers]   [forward]  
 
Messages in this thread
Patch in this message
/
DateMon, 23 Dec 2002 07:05:47 -0800
From"Adam J. Richter" <>
SubjectRe: RFC/Preliminary patch - simpler raceless module unloading
I wrote:
> 	I plan to port net_device, filesystem, file_operations,
> block_device_operations, and device_driver to use it.  So if what
> I've described above is too verbose, it should become clearer once
> I post some ports of code to it.

	Here is a preliminary port of fs/filesystems.c, although I have
not done the clean-ups it enables.  I am running it now and have verified
that I can at least load and unload a filesystem module and that I'm
still prevented from unloading a filesystem module that is in use.

Adam J. Richter     __     ______________   575 Oroville Road
adam@yggdrasil.com     \ /                  Milpitas, California 95035
+1 408 309-6081         | g g d r a s i l   United States of America
                         "Free Software For The Rest Of Us."--- linux-2.5.52/include/linux/fs.h	2002-12-15 18:07:50.000000000 -0800
+++ linux/include/linux/fs.h	2002-12-23 07:00:02.000000000 -0800
@@ -19,6 +19,7 @@
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/radix-tree.h>
+#include <linux/module_rwsem.h>
 #include <asm/atomic.h>
 
 struct iovec;
@@ -953,7 +954,8 @@
 	int fs_flags;
 	struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *);
 	void (*kill_sb) (struct super_block *);
-	struct module *owner;
+	struct module *owner;	/* Will be subsumed into mod_rwsem. */
+	struct module_rwsem	mod_rwsem;
 	struct file_system_type * next;
 	struct list_head fs_supers;
 };
--- linux-2.5.52/fs/filesystems.c	2002-12-15 18:08:14.000000000 -0800
+++ linux/fs/filesystems.c	2002-12-23 06:56:40.000000000 -0800
@@ -26,7 +26,7 @@
  */
 
 static struct file_system_type *file_systems;
-static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
+static DECLARE_RWSEM(file_systems_rwsem);
 
 /* WARNING: This can be used only if we _already_ own a reference */
 void get_filesystem(struct file_system_type *fs)
@@ -81,13 +81,17 @@
 	if (fs->next)
 		return -EBUSY;
 	INIT_LIST_HEAD(&fs->fs_supers);
-	write_lock(&file_systems_lock);
+	down_write(&file_systems_rwsem);
 	p = find_filesystem(fs->name);
 	if (*p)
 		res = -EBUSY;
-	else
+	else {
 		*p = fs;
-	write_unlock(&file_systems_lock);
+		fs->mod_rwsem.module = fs->owner;
+		fs->mod_rwsem.rwsem = &file_systems_rwsem;
+		register_module_rwsem(&fs->mod_rwsem);
+	}
+	up_write(&file_systems_rwsem);
 	return res;
 }
 
@@ -107,18 +111,18 @@
 {
 	struct file_system_type ** tmp;
 
-	write_lock(&file_systems_lock);
+	/* sys_delete_module has already done a
+	   down_write(&file_systems_rwsem) for us. */
 	tmp = &file_systems;
 	while (*tmp) {
 		if (fs == *tmp) {
 			*tmp = fs->next;
 			fs->next = NULL;
-			write_unlock(&file_systems_lock);
+			up_write(&file_systems_rwsem);
 			return 0;
 		}
 		tmp = &(*tmp)->next;
 	}
-	write_unlock(&file_systems_lock);
 	return -EINVAL;
 }
 
@@ -134,14 +138,14 @@
 		return err;
 
 	err = -EINVAL;
-	read_lock(&file_systems_lock);
+	down_read(&file_systems_rwsem);
 	for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
 		if (strcmp(tmp->name,name) == 0) {
 			err = index;
 			break;
 		}
 	}
-	read_unlock(&file_systems_lock);
+	up_read(&file_systems_rwsem);
 	putname(name);
 	return err;
 }
@@ -151,11 +155,11 @@
 	struct file_system_type * tmp;
 	int len, res;
 
-	read_lock(&file_systems_lock);
+	down_read(&file_systems_rwsem);
 	for (tmp = file_systems; tmp; tmp = tmp->next, index--)
 		if (index <= 0 && try_inc_mod_count(tmp->owner))
 				break;
-	read_unlock(&file_systems_lock);
+	up_read(&file_systems_rwsem);
 	if (!tmp)
 		return -EINVAL;
 
@@ -171,10 +175,10 @@
 	struct file_system_type * tmp;
 	int index;
 
-	read_lock(&file_systems_lock);
+	down_read(&file_systems_rwsem);
 	for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
 		;
-	read_unlock(&file_systems_lock);
+	up_read(&file_systems_rwsem);
 	return index;
 }
 
@@ -206,7 +210,7 @@
 	int len = 0;
 	struct file_system_type * tmp;
 
-	read_lock(&file_systems_lock);
+	down_read(&file_systems_rwsem);
 	tmp = file_systems;
 	while (tmp && len < PAGE_SIZE - 80) {
 		len += sprintf(buf+len, "%s\t%s\n",
@@ -214,7 +218,7 @@
 			tmp->name);
 		tmp = tmp->next;
 	}
-	read_unlock(&file_systems_lock);
+	up_read(&file_systems_rwsem);
 	return len;
 }
 
@@ -222,17 +226,17 @@
 {
 	struct file_system_type *fs;
 
-	read_lock(&file_systems_lock);
+	down_read(&file_systems_rwsem);
 	fs = *(find_filesystem(name));
 	if (fs && !try_inc_mod_count(fs->owner))
 		fs = NULL;
-	read_unlock(&file_systems_lock);
+	up_read(&file_systems_rwsem);
 	if (!fs && (request_module(name) == 0)) {
-		read_lock(&file_systems_lock);
+		down_read(&file_systems_rwsem);
 		fs = *(find_filesystem(name));
 		if (fs && !try_inc_mod_count(fs->owner))
 			fs = NULL;
-		read_unlock(&file_systems_lock);
+		up_read(&file_systems_rwsem);
 	}
 	return fs;
 }
\
 
 \ /
  Last update: 2005-03-22 11:31    [from the cache]
©2003-2008