[Ocfs2-commits] jlbec commits r1967 - trunk/fs/usysfs

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Mar 9 19:41:44 CST 2005


Author: jlbec
Signed-off-by: manish
Date: 2005-03-09 19:41:42 -0600 (Wed, 09 Mar 2005)
New Revision: 1967

Modified:
   trunk/fs/usysfs/bobtest.c
   trunk/fs/usysfs/dir.c
   trunk/fs/usysfs/inode.c
   trunk/fs/usysfs/mount.c
   trunk/fs/usysfs/usysfs.h
Log:

o Make default_sets work.

Signed-off-by: manish



Modified: trunk/fs/usysfs/bobtest.c
===================================================================
--- trunk/fs/usysfs/bobtest.c	2005-03-09 01:11:15 UTC (rev 1966)
+++ trunk/fs/usysfs/bobtest.c	2005-03-10 01:41:42 UTC (rev 1967)
@@ -10,6 +10,82 @@
 #include "usysfs.h"
 
 
+struct robert {
+	struct kset kset;
+};
+
+struct robert_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct robert *, char *);
+};
+
+static inline struct robert *to_robert(struct kobject *kobj)
+{
+	return kobj ? container_of(to_kset(kobj), struct robert, kset) : NULL;
+}
+
+static ssize_t robert_print_read(struct robert *robert, char *page)
+{
+	ssize_t pos;
+
+	pos = sprintf(page, "%s\n", "This is a default bob");
+
+	return pos;
+}
+
+static struct robert_attribute robert_attr_print = {
+	.attr	= { .name = "print", .mode = S_IRUGO },
+	.show	= robert_print_read,
+};
+
+static struct attribute *robert_attrs[] = {
+	&robert_attr_print.attr,
+	NULL,
+};
+
+static ssize_t robert_attr_show(struct kobject *kobj,
+		   		struct attribute *attr,
+		   		char *page)
+{
+	struct robert *robert = to_robert(kobj);
+	struct robert_attribute *robert_attr =
+		container_of(attr, struct robert_attribute, attr);
+	ssize_t ret = 0;
+
+	if (robert_attr->show)
+		ret = robert_attr->show(robert, page);
+	return ret;
+}
+
+struct sysfs_ops robert_sysfs_ops = {
+	.show	= &robert_attr_show,
+};
+
+static void robert_release(struct kobject *kobj)
+{
+	kfree(to_robert(kobj));
+}
+
+static struct ukobj_type uktype_robert = {
+	.ktype	= {
+		.release	= robert_release,
+		.sysfs_ops	= &robert_sysfs_ops,
+		.default_attrs	= robert_attrs,
+	},
+	.owner	= THIS_MODULE,
+};
+
+static struct robert robert = {
+	.kset = {
+		.kobj = {
+			.name = "robert",
+			.ktype = &uktype_robert.ktype,
+		},
+	},
+};
+
+
+
 struct bob {
 	struct kobject kobj;
 	int showme;
@@ -171,6 +247,11 @@
 	NULL,
 };
 
+static struct kset *bobset_sets[] = {
+	&robert.kset,
+	NULL,
+};
+
 static struct kobject *make_bob(struct kset *kset, const char *name)
 {
 	struct bobset *bobset = to_bobset(kset);
@@ -194,9 +275,9 @@
 	return &bob->kobj;
 }
 
-static void drop_bob(struct kobject *kobj)
+static void drop_bob(struct kset *kset, struct kobject *kobj)
 {
-	struct bobset *bobset = to_bobset(kobj->kset);
+	struct bobset *bobset = to_bobset(kset);
 
 	bobset->n_bobs--;
 	kobject_put(kobj);
@@ -209,6 +290,7 @@
 	},
 	.make_object	= make_bob,
 	.drop_object	= drop_bob,
+	.default_sets	= bobset_sets,
 };
 
 static struct bobset bobset = {
@@ -232,6 +314,7 @@
 	int ret;
 
 	kset_init(&bobset.kset);
+	kset_init(&robert.kset);
 	ret = usysfs_register_subsystem(&bobset.kset);
 	if (ret)
 		printk(KERN_ERR "bobtest: Registration returned %d\n", ret);

Modified: trunk/fs/usysfs/dir.c
===================================================================
--- trunk/fs/usysfs/dir.c	2005-03-09 01:11:15 UTC (rev 1966)
+++ trunk/fs/usysfs/dir.c	2005-03-10 01:41:42 UTC (rev 1967)
@@ -19,7 +19,7 @@
 #include "usysfs_internal.h"
 
 DECLARE_RWSEM(usysfs_rename_sem);
-DECLARE_MUTEX(usysfs_linkage_sem);
+static spinlock_t usysfs_linkage_lock = SPIN_LOCK_UNLOCKED;
 
 static void usysfs_d_iput(struct dentry * dentry, struct inode * inode)
 {
@@ -280,9 +280,13 @@
 	struct usysfs_dirent *sd;
 
 	list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
-		if (sd->s_type & (USYSFS_NOT_PINNED |
-				  USYSFS_DEFAULT_DIR))
+		if (sd->s_type & USYSFS_NOT_PINNED)
 			continue;
+		/* Eww, recursion */
+		if ((sd->s_type & USYSFS_DEFAULT_DIR) &&
+		    usysfs_empty_dir(sd->s_dentry))
+			continue;
+
 		return 0;
 	}
 
@@ -338,66 +342,151 @@
 	return error;
 }
 
+static int usysfs_instantiate_set(struct kobject *parent_kobj,
+				  struct kobject *kobj,
+				  struct dentry *dentry);
+static void usysfs_drop_set(struct kobject *kobj);
+
+static void drop_sets(struct kset *kset)
+{
+	struct dentry * dentry = dget(kset->kobj.dentry);
+	struct dentry *child;
+	struct usysfs_dirent *parent_sd;
+	struct usysfs_dirent *sd, *tmp;
+
+	if (!dentry)
+		return;
+
+	parent_sd = dentry->d_fsdata;
+	list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
+		if (!sd->s_element ||
+		    !(sd->s_type & USYSFS_DEFAULT_DIR))
+			continue;
+		list_del_init(&sd->s_sibling);
+		child = sd->s_dentry;
+		usysfs_drop_set(sd->s_element);
+		d_delete(child);
+		dput(child);
+		usysfs_put(sd);
+	}
+
+	/**
+	 * Drop reference from dget() on entrance.
+	 */
+	dput(dentry);
+}
+
+static int create_default_set(struct kset *parent_kset,
+			      struct kset *kset)
+{
+	int ret;
+	struct qstr name;
+	struct dentry *child, *parent = parent_kset->kobj.dentry;
+	struct usysfs_dirent *sd;
+
+	if (!kset->kobj.k_name)
+		kset->kobj.k_name = kset->kobj.name;
+	name.name = kset->kobj.k_name;
+	name.len = strlen(name.name);
+	name.hash = full_name_hash(name.name, name.len);
+
+	ret = -ENOMEM;
+	child = d_alloc(parent, &name);
+	if (child) {
+		d_add(child, NULL);
+
+		ret = usysfs_instantiate_set(&parent_kset->kobj,
+					     &kset->kobj, child);
+		if (!ret) {
+			sd = child->d_fsdata;
+			sd->s_type = USYSFS_DEFAULT_DIR;
+		} else {
+			/*
+			 * XXX: fs/namei.c does d_delete() outside
+			 * of i_sem.  For easy error chaining, we're
+			 * doing it inside i_sem.  It doesn't appear
+			 * to be a problem, but someone smack me if I'm
+			 * wrong.
+			 */
+			d_delete(child);
+			dput(child);
+		}
+	}
+
+	return ret;
+}
+
+static int populate_sets(struct kset *kset)
+{
+	struct ukobj_type *uktype = to_uktype(kset->kobj.ktype);
+	struct kset *new_set;
+	struct dentry *dentry = kset->kobj.dentry;
+	int ret = 0;
+	int i;
+
+	if (uktype && uktype->default_sets) {
+		down(&dentry->d_inode->i_sem);
+
+		for (i = 0; uktype->default_sets[i]; i++) {
+			new_set = uktype->default_sets[i];
+
+			ret = create_default_set(kset, new_set);
+			if (ret)
+				break;
+		}
+
+		up(&dentry->d_inode->i_sem);
+	}
+
+	if (ret)
+		drop_sets(kset);
+
+	return ret;
+}
+
 /*
  * Remove an object from its kset and decrement the refcount.
  * This is used by both rmdir() and by mkdir() on error.
  */
 static void unlink_obj(struct kobject *kobj)
 {
-	struct ukobj_type *uktype;
-	struct module *owner = NULL;
-
 	if (kobj->kset) {
-		down(&usysfs_linkage_sem);
+		spin_lock(&usysfs_linkage_lock);
 		list_del_init(&kobj->entry);
-		up(&usysfs_linkage_sem);
+		spin_unlock(&usysfs_linkage_lock);
 		kobj->kset = NULL;
 		kobj->parent = NULL;
+
+		/* kobject_cleanup() drops parent ref from link_obj() */
+		kobject_put(kobj);
 	}
-	uktype = to_uktype(kobj->ktype);
-	if (uktype)
-		owner = uktype->owner;
-
-	/* kobject_cleanup() drops the parent ref from link_obj() */
-	kobject_put(kobj);
-	module_put(owner);
 }
 
-static int link_obj(struct kobject *parent_kobj, struct kobject *kobj)
+static void link_obj(struct kobject *parent_kobj, struct kobject *kobj)
 {
-	struct ukobj_type *uktype;
-	struct module *owner = NULL;
-	int rc = 1;
+	kobj->kset = kset_get(to_kset(parent_kobj));
 
-	uktype = to_uktype(kobj->ktype);
-	if (uktype) {
-		owner = uktype->owner;
-		if (try_module_get(owner)) {
-			kobj->kset = kset_get(to_kset(parent_kobj));
+	spin_lock(&usysfs_linkage_lock);
+	list_add_tail(&kobj->entry, &kobj->kset->list);
+	spin_unlock(&usysfs_linkage_lock);
 
-			down(&usysfs_linkage_sem);
-			list_add_tail(&kobj->entry, &kobj->kset->list);
-			up(&usysfs_linkage_sem);
-
-			kobj->parent = parent_kobj;
-			kobject_get(kobj);
-			rc = 0;
-		}
-	}
-
-	return rc;
+	kobj->parent = parent_kobj;
+	kobject_get(kobj);
 }
 
-static int usysfs_instantiate_object(struct kobject *kobj,
+static int usysfs_instantiate_object(struct kobject *parent_kobj,
+				     struct kobject *kobj,
 				     struct dentry *dentry)
 {
 	int ret;
 
+	link_obj(parent_kobj, kobj);
 	ret = usysfs_create_dir(kobj, dentry);
 	if (!ret) {
 		ret = populate_attrs(kobj);
 		if (ret) {
 			usysfs_remove_dir(kobj);
+			unlink_obj(kobj);
 			d_delete(dentry);
 		}
 	}
@@ -405,7 +494,38 @@
 	return ret;
 }
 
+static void usysfs_drop_object(struct kobject *kobj)
+{
+	drop_attrs(kobj);
+	usysfs_remove_dir(kobj);
+	unlink_obj(kobj);
+}
 
+static int usysfs_instantiate_set(struct kobject *parent_kobj,
+				  struct kobject *kobj,
+				  struct dentry *dentry)
+{
+	int ret;
+
+	ret = usysfs_instantiate_object(parent_kobj, kobj, dentry);
+	if (!ret) {
+		ret = populate_sets(to_kset(kobj));
+		if (ret) {
+			usysfs_drop_object(kobj);
+			d_delete(dentry);
+		}
+	}
+
+	return ret;
+}
+
+static void usysfs_drop_set(struct kobject *kobj)
+{
+	drop_sets(to_kset(kobj));
+	usysfs_drop_object(kobj);
+}
+
+
 static int usysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int ret;
@@ -413,6 +533,7 @@
 	struct kobject *kobj;
 	struct kobject *parent_kobj;
 	struct ukobj_type *uktype;
+	struct module *owner;
 	char *name;
 
 	if (dentry->d_parent == usysfs_sb->s_root)
@@ -444,17 +565,36 @@
 		return -ENOMEM;
 	}
 
-	if (link_obj(parent_kobj, kobj)) {
-		kobject_put(kobj);
-		kobject_put(parent_kobj);
-		return -ENOENT;
+	ret = -EINVAL;
+	uktype = to_uktype(kobj->ktype);
+	if (uktype) {
+		owner = uktype->owner;
+		if (try_module_get(owner)) {
+			ret = usysfs_instantiate_object(parent_kobj,
+							kobj, dentry);
+			if (ret) {
+				kobject_put(parent_kobj);
+				module_put(owner);
+			}
+		}
 	}
 
-	ret = usysfs_instantiate_object(kobj, dentry);
-	if (ret) {
-		unlink_obj(kobj);
-		kobject_put(parent_kobj);
-		return ret;
+	return ret;
+}
+
+static int is_set(struct kobject *kobj)
+{
+	int ret = 0;
+	struct ukobj_type *uktype;
+
+	uktype = to_uktype(kobj->ktype);
+	if (uktype) {
+		if (uktype->make_kset)
+			ret = 1;
+		else if (uktype->make_object)
+			ret = 1;
+		else if (uktype->default_sets)
+			ret = 1;
 	}
 
 	return ret;
@@ -464,11 +604,16 @@
 {
 	struct kobject *parent_kobj;
 	struct kobject *kobj;
-	struct ukobj_type *uktype;
+	struct ukobj_type *uktype, *child_uktype;
+	struct usysfs_dirent *sd;
+	struct module *owner = NULL;
 
 	if (dentry->d_parent == usysfs_sb->s_root)
 		return -EPERM;
 
+	sd = dentry->d_fsdata;
+	if (sd->s_type & USYSFS_DEFAULT_DIR)
+		return -EPERM;
 
 	parent_kobj = usysfs_get_kobject(dentry->d_parent);
 
@@ -488,15 +633,21 @@
 	/* Drop reference from above, kobj already holds one. */
 	kobject_put(parent_kobj); 
 
-	drop_attrs(kobj);
-	usysfs_remove_dir(kobj);
+	child_uktype = to_uktype(kobj->ktype);
+	if (child_uktype)
+		owner = child_uktype->owner;
 
+	if (is_set(kobj))
+		usysfs_drop_set(kobj);
+	else
+		usysfs_drop_object(kobj);
+
 	if (uktype->drop_object)
-		uktype->drop_object(kobj);
+		uktype->drop_object(to_kset(parent_kobj), kobj);
 	else 
 		kobject_put(kobj);
 
-	unlink_obj(kobj);
+	module_put(owner);
 
 	return 0;
 }
@@ -517,6 +668,7 @@
 	.lookup		= usysfs_lookup_compat,
 #endif
 };
+
 int usysfs_rename_dir(struct kobject * kobj, const char *new_name)
 {
 	int error = 0;
@@ -698,6 +850,8 @@
 	int err;
 	struct qstr name;
 	struct dentry *dentry;
+	struct usysfs_dirent *sd;
+	struct kset *root_set;
 
 	err = usysfs_pin_fs();
 	if (err)
@@ -720,7 +874,9 @@
 	
 	d_add(dentry, NULL);
 
-	err = usysfs_instantiate_object(&k->kobj, dentry);
+	sd = usysfs_sb->s_root->d_fsdata;
+	root_set = sd->s_element;
+	err = usysfs_instantiate_set(&root_set->kobj, &k->kobj, dentry);
 	if (!err)
 		dentry = NULL;
 	else
@@ -744,16 +900,11 @@
 		return;
 	}
 
-	if (!list_empty(&k->list)) {
-		printk(KERN_ERR "usysfs: Tried to unregister non-empty subsystem!\n");
-	}
-
 	down(&usysfs_sb->s_root->d_inode->i_sem);
 	if (!usysfs_empty_dir(k->kobj.dentry)) {
 		printk(KERN_ERR "usysfs: Tried to unregister non-empty subsystem!\n");
 	}
-	drop_attrs(&k->kobj);
-	usysfs_remove_dir(&k->kobj);
+	usysfs_drop_set(&k->kobj);
 	up(&usysfs_sb->s_root->d_inode->i_sem);
 
 	d_delete(k->kobj.dentry);

Modified: trunk/fs/usysfs/inode.c
===================================================================
--- trunk/fs/usysfs/inode.c	2005-03-09 01:11:15 UTC (rev 1966)
+++ trunk/fs/usysfs/inode.c	2005-03-10 01:41:42 UTC (rev 1967)
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
  * inode.c - basic inode and dentry operations.
  *
  * usysfs is Copyright (c) 2001-3 Patrick Mochel
@@ -104,6 +106,7 @@
 
 	switch (sd->s_type) {
 		case USYSFS_DIR:
+		case USYSFS_DEFAULT_DIR:
 			/* Always have a dentry so use that */
 			return sd->s_dentry->d_name.name;
 

Modified: trunk/fs/usysfs/mount.c
===================================================================
--- trunk/fs/usysfs/mount.c	2005-03-09 01:11:15 UTC (rev 1966)
+++ trunk/fs/usysfs/mount.c	2005-03-10 01:41:42 UTC (rev 1967)
@@ -34,13 +34,27 @@
 #endif
 };
 
+static struct kset usysfs_root_set = {
+	.kobj = {
+		.name	= "root",
+		.k_name	= usysfs_root_set.kobj.name,
+	},
+};
+
 static struct usysfs_dirent usysfs_root = {
 	.s_sibling	= LIST_HEAD_INIT(usysfs_root.s_sibling),
 	.s_children	= LIST_HEAD_INIT(usysfs_root.s_children),
-	.s_element	= NULL,
+	.s_element	= &usysfs_root_set,
 	.s_type		= USYSFS_ROOT,
 };
 
+/* Kernel idiots 1, universe 0 */
+void kset_init(struct kset *k)
+{
+	kobject_init(&k->kobj);
+	INIT_LIST_HEAD(&k->list);
+}
+
 static int usysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
@@ -69,6 +83,8 @@
 		iput(inode);
 		return -ENOMEM;
 	}
+	kset_init(&usysfs_root_set);
+	usysfs_root_set.kobj.dentry = root;
 	root->d_fsdata = &usysfs_root;
 	sb->s_root = root;
 	return 0;

Modified: trunk/fs/usysfs/usysfs.h
===================================================================
--- trunk/fs/usysfs/usysfs.h	2005-03-09 01:11:15 UTC (rev 1966)
+++ trunk/fs/usysfs/usysfs.h	2005-03-10 01:41:42 UTC (rev 1967)
@@ -52,7 +52,7 @@
 	struct kobject *(*make_object)(struct kset *kset, const char *name);
 	struct kset *(*make_kset)(struct kset *kset, const char *name);
 	int (*commit)(struct kobject *kobj);
-        void (*drop_object)(struct kobject *kobj);
+        void (*drop_object)(struct kset *kset, struct kobject *kobj);
 };
 
 static inline struct ukobj_type *to_uktype(struct kobj_type *ktype)



More information about the Ocfs2-commits mailing list