[Ocfs2-commits] jlbec commits r2073 - trunk/fs/configfs

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Mar 29 18:09:25 CST 2005


Author: jlbec
Signed-off-by: manish
Signed-off-by: mfasheh
Date: 2005-03-29 18:09:23 -0600 (Tue, 29 Mar 2005)
New Revision: 2073

Modified:
   trunk/fs/configfs/Makefile
   trunk/fs/configfs/configfs.h
   trunk/fs/configfs/dir.c
Log:

o Move the object linkage outside of the dcache muddling.
o Properly lock subsys->su_sem around make+link and unlink+drop.

Signed-off-by: manish
Signed-off-by: mfasheh



Modified: trunk/fs/configfs/Makefile
===================================================================
--- trunk/fs/configfs/Makefile	2005-03-29 22:31:33 UTC (rev 2072)
+++ trunk/fs/configfs/Makefile	2005-03-30 00:09:23 UTC (rev 2073)
@@ -23,8 +23,8 @@
 
 HEADERS =					\
 	uobject.h				\
-	usysfs.h				\
-	usysfs_internal.h			\
+	configfs.h				\
+	configfs_internal.h			\
 	compatinclude/linux/compat.h		\
 	compatinclude/linux/kref.h		\
 	compatinclude/linux/compat_libfs.h

Modified: trunk/fs/configfs/configfs.h
===================================================================
--- trunk/fs/configfs/configfs.h	2005-03-29 22:31:33 UTC (rev 2072)
+++ trunk/fs/configfs/configfs.h	2005-03-30 00:09:23 UTC (rev 2073)
@@ -67,7 +67,7 @@
 struct configfs_set_operations {
 	struct uobject *(*make_object)(struct uset *uset, const char *name);
 	struct uset *(*make_set)(struct uset *uset, const char *name);
-	int (*commit)(struct uobject *uobj);
+	int (*commit_object)(struct uobject *uobj);
         void (*drop_object)(struct uset *uset, struct uobject *uobj);
 };
 

Modified: trunk/fs/configfs/dir.c
===================================================================
--- trunk/fs/configfs/dir.c	2005-03-29 22:31:33 UTC (rev 2072)
+++ trunk/fs/configfs/dir.c	2005-03-30 00:09:23 UTC (rev 2073)
@@ -38,7 +38,6 @@
 #include "configfs_internal.h"
 
 DECLARE_RWSEM(configfs_rename_sem);
-static spinlock_t configfs_linkage_lock = SPIN_LOCK_UNLOCKED;
 
 static void configfs_d_iput(struct dentry * dentry,
 			    struct inode * inode)
@@ -488,20 +487,17 @@
 }
 
 /*
- * Remove an object from its uset and decrement the refcount.
- * This is used by both rmdir() and by mkdir() on error.
- * It expects a valid reference to be held on uobj in addition to
- * the reference from link_obj().
+ * All of link_obj/unlink_obj/link_set/unlink_set require that
+ * subsys->su_sem is held.
  */
+
 static void unlink_obj(struct uobject *uobj)
 {
 	struct uset *set;
 
 	set = uobj->uset;
 	if (set) {
-		spin_lock(&configfs_linkage_lock);
 		list_del_init(&uobj->entry);
-		spin_unlock(&configfs_linkage_lock);
 
 		uobj->uset = NULL;
 		uobj->parent = NULL;
@@ -513,16 +509,47 @@
 
 static void link_obj(struct uobject *parent_uobj, struct uobject *uobj)
 {
+	/* Parent seems redundant with set, but it makes certain
+	 * traversals much nicer. */
+	uobj->parent = parent_uobj;
 	uobj->uset = uset_get(to_uset(parent_uobj));
-
-	spin_lock(&configfs_linkage_lock);
 	list_add_tail(&uobj->entry, &uobj->uset->list);
-	spin_unlock(&configfs_linkage_lock);
 
-	uobj->parent = parent_uobj;
 	uobject_get(uobj);
 }
 
+static void unlink_set(struct uset *uset)
+{
+	int i;
+	struct uset *new_set;
+
+	if (uset->default_sets) {
+		for (i = 0; uset->default_sets[i]; i++) {
+			new_set = uset->default_sets[i];
+			unlink_set(new_set);
+		}
+	}
+
+	uset->subsys = NULL;
+	unlink_obj(&uset->uobj);
+}
+
+static void link_set(struct uset *parent_uset, struct uset *uset)
+{
+	int i;
+	struct uset *new_set;
+
+	link_obj(&parent_uset->uobj, &uset->uobj);
+	uset->subsys = parent_uset->subsys;
+
+	if (uset->default_sets) {
+		for (i = 0; uset->default_sets[i]; i++) {
+			new_set = uset->default_sets[i];
+			link_set(uset, new_set);
+		}
+	}
+}
+
 /*
  * The goal is that configfs_attach_object() (and
  * configfs_attach_set()) can be called from either the VFS or this
@@ -544,13 +571,11 @@
 {
 	int ret;
 
-	link_obj(parent_uobj, uobj);
 	ret = configfs_create_dir(uobj, dentry);
 	if (!ret) {
 		ret = populate_attrs(uobj);
 		if (ret) {
 			configfs_remove_dir(uobj);
-			unlink_obj(uobj);
 			d_delete(dentry);
 		}
 	}
@@ -562,7 +587,6 @@
 {
 	detach_attrs(uobj);
 	configfs_remove_dir(uobj);
-	unlink_obj(uobj);
 }
 
 static int configfs_attach_set(struct uobject *parent_uobj,
@@ -621,6 +645,7 @@
 	struct uset *uset;
 	struct uobject *uobj;
 	struct uobject *parent_uobj;
+	struct configfs_subsystem *subsys;
 	struct configfs_dirent *sd;
 	struct uobj_type *uktype;
 	struct module *owner;
@@ -635,6 +660,8 @@
 
 	parent_uobj = configfs_get_uobject(dentry->d_parent);
 	uktype = parent_uobj->ktype;
+	subsys = to_uset(parent_uobj)->subsys;
+	BUG_ON(!subsys);
 
 	if (!uktype || !uktype->set_ops ||
 	    (!uktype->set_ops->make_set &&
@@ -649,13 +676,24 @@
 		return -ENOMEM;
 	}
 	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
+
+	down(&subsys->su_sem);
+	uset = NULL;
+	uobj = NULL;
 	if (uktype->set_ops->make_set) {
-		uset = uktype->set_ops->make_set(to_uset(parent_uobj), name);
-		uobj = uset ? &uset->uobj : NULL;
+		uset = uktype->set_ops->make_set(to_uset(parent_uobj),
+						 name);
+		if (uset) {
+			link_set(to_uset(parent_uobj), uset);
+			uobj = &uset->uobj;
+		}
 	} else {
-		uset = NULL;
 		uobj = uktype->set_ops->make_object(to_uset(parent_uobj), name);
+		if (uobj)
+			link_obj(parent_uobj, uobj);
 	}
+	up(&subsys->su_sem);
+
 	kfree(name);
 	if (!uobj) {
 		uobject_put(parent_uobj);
@@ -667,16 +705,25 @@
 	if (uktype) {
 		owner = uktype->owner;
 		if (try_module_get(owner)) {
-			if (uset)
+			if (uset) {
 				ret = configfs_attach_set(parent_uobj,
 							  uobj,
 							  dentry);
-			else
+			} else {
 				ret = configfs_attach_object(parent_uobj,
 							     uobj,
 							     dentry);
+			}
+
 			if (ret) {
+				down(&subsys->su_sem);
+				if (uset)
+					unlink_set(uset);
+				else
+					unlink_obj(uobj);
 				client_drop_object(parent_uobj, uobj);
+				up(&subsys->su_sem);
+
 				uobject_put(parent_uobj);
 				module_put(owner);
 			}
@@ -690,6 +737,7 @@
 {
 	struct uobject *parent_uobj;
 	struct uobject *uobj;
+	struct configfs_subsystem *subsys;
 	struct configfs_dirent *sd;
 	struct module *owner = NULL;
 	int ret;
@@ -702,12 +750,14 @@
 		return -EPERM;
 
 	parent_uobj = configfs_get_uobject(dentry->d_parent);
+	subsys = to_uset(parent_uobj)->subsys;
+	BUG_ON(!subsys);
 
 	if (!parent_uobj->ktype) {
 		uobject_put(parent_uobj);
 		return -EINVAL;
 	}
-
+	
 	ret = configfs_empty_dir(dentry);
 	if (ret) {
 		uobject_put(parent_uobj);
@@ -722,12 +772,20 @@
 	if (uobj->ktype)
 		owner = uobj->ktype->owner;
 
-	if (sd->s_type & CONFIGFS_USET_DIR)
+	if (sd->s_type & CONFIGFS_USET_DIR) {
 		configfs_detach_set(uobj);
-	else
+
+		down(&subsys->su_sem);
+		unlink_set(to_uset(uobj));
+	} else {
 		configfs_detach_object(uobj);
 
+		down(&subsys->su_sem);
+		unlink_obj(uobj);
+	}
+
 	client_drop_object(parent_uobj, uobj);
+	up(&subsys->su_sem);
 
 	/* Drop our reference from above */
 	uobject_put(uobj);
@@ -947,6 +1005,10 @@
 	if (!set->uobj.k_name)
 		set->uobj.k_name = set->uobj.name;
 
+	sd = configfs_sb->s_root->d_fsdata;
+	link_set(to_uset(sd->s_element), set);
+	set->subsys = subsys;
+
 	down(&configfs_sb->s_root->d_inode->i_sem);
 
 	name.name = set->uobj.k_name;
@@ -960,7 +1022,6 @@
 	
 	d_add(dentry, NULL);
 
-	sd = configfs_sb->s_root->d_fsdata;
 	err = configfs_attach_set(sd->s_element, &set->uobj, dentry);
 	if (!err)
 		dentry = NULL;
@@ -972,6 +1033,7 @@
 	if (dentry) {
 	    dput(dentry);
 out_release:
+	    unlink_set(set);
 	    configfs_release_fs();
 	}
 
@@ -1002,6 +1064,8 @@
 	up(&configfs_sb->s_root->d_inode->i_sem);
 
 	dput(dentry);
+
+	unlink_set(set);
 	configfs_release_fs();
 }
 



More information about the Ocfs2-commits mailing list