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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Mar 10 19:12:49 CST 2005


Author: jlbec
Signed-off-by: zab
Signed-off-by: manish
Date: 2005-03-10 19:12:47 -0600 (Thu, 10 Mar 2005)
New Revision: 1970

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

o Create ukset wrapper to kset
o Move default_attrs from ukobj_type to ukset
o Fix dcache handling (d_drop() is your friend).

Signed-off-by: zab
Signed-off-by: manish



Modified: trunk/fs/usysfs/bobtest.c
===================================================================
--- trunk/fs/usysfs/bobtest.c	2005-03-10 23:56:53 UTC (rev 1969)
+++ trunk/fs/usysfs/bobtest.c	2005-03-11 01:12:47 UTC (rev 1970)
@@ -10,8 +10,12 @@
 #include "usysfs.h"
 
 
+
+/*
+ * Bobs - default_set as part of subsystem.
+ */
 struct robert {
-	struct kset kset;
+	struct ukset ukset;
 };
 
 struct robert_attribute {
@@ -21,7 +25,9 @@
 
 static inline struct robert *to_robert(struct kobject *kobj)
 {
-	return kobj ? container_of(to_kset(kobj), struct robert, kset) : NULL;
+	return kobj ?
+		container_of(to_ukset(to_kset(kobj)), struct robert, ukset) :
+		NULL;
 }
 
 static ssize_t robert_print_read(struct robert *robert, char *page)
@@ -76,10 +82,12 @@
 };
 
 static struct robert robert = {
-	.kset = {
-		.kobj = {
-			.name = "robert",
-			.ktype = &uktype_robert.ktype,
+	.ukset = {
+		.kset = {
+			.kobj = {
+				.name = "robert",
+				.ktype = &uktype_robert.ktype,
+			},
 		},
 	},
 };
@@ -200,7 +208,7 @@
 
 
 struct bobset {
-	struct kset kset;
+	struct ukset ukset;
 	int n_bobs;
 };
 
@@ -211,7 +219,9 @@
 
 static inline struct bobset *to_bobset(struct kset *kset)
 {
-	return kset ? container_of(kset, struct bobset, kset) : NULL;
+	return kset ?
+		container_of(to_ukset(kset), struct bobset, ukset) :
+		NULL;
 }
 
 static ssize_t bobset_attr_show(struct kobject *kobj,
@@ -248,7 +258,7 @@
 };
 
 static struct kset *bobset_sets[] = {
-	&robert.kset,
+	&robert.ukset.kset,
 	NULL,
 };
 
@@ -263,8 +273,7 @@
 
 	memset(bob, 0, sizeof(struct bob));
 
-	strcpy(bob->kobj.name, name);
-	bob->kobj.k_name = bob->kobj.name;
+	kobject_set_name(&bob->kobj, name);
 	bob->kobj.ktype = &uktype_bob.ktype;
 	kobject_init(&bob->kobj);
 
@@ -290,32 +299,391 @@
 	},
 	.make_object	= make_bob,
 	.drop_object	= drop_bob,
-	.default_sets	= bobset_sets,
 };
 
 static struct bobset bobset = {
-	.kset = {
-		.kobj = {
-			.name = "bobset",
-			.ktype = &uktype_bobset.ktype,
+	.ukset = {
+		.kset = {
+			.kobj = {
+				.name = "bobset",
+				.ktype = &uktype_bobset.ktype,
+			},
 		},
+		.default_sets = bobset_sets,
 	},
 	.n_bobs = 0,
 };
 
-void kset_init(struct kset *k)
+/*
+ * Toms - default_set as part of a created set.
+ */
+struct jerry {
+	struct ukset ukset;
+	int showme;
+	int storeme;
+};
+
+struct jerry_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct jerry *, char *);
+	ssize_t (*store)(struct jerry *, const char *, size_t);
+};
+
+static inline struct jerry *to_jerry(struct kobject *kobj)
 {
-	kobject_init(&k->kobj);
-	INIT_LIST_HEAD(&k->list);
+	return kobj ?
+		container_of(to_ukset(to_kset(kobj)), struct jerry, ukset) :
+		NULL;
 }
 
+static ssize_t jerry_showme_read(struct jerry *jerry, char *page)
+{
+	ssize_t pos;
+
+	pos = sprintf(page, "%d\n", jerry->showme);
+	jerry->showme++;
+
+	return pos;
+}
+
+static ssize_t jerry_storeme_read(struct jerry *jerry, char *page)
+{
+	return sprintf(page, "%d\n", jerry->storeme);
+}
+
+static ssize_t jerry_storeme_write(struct jerry *jerry, const char *page,
+				 size_t count)
+{
+	unsigned long tmp;
+	char *p = (char *) page;
+
+	tmp = simple_strtoul(p, &p, 10);
+	if (!p || (*p && (*p != '\n')))
+		return -EINVAL;
+
+	if (tmp > INT_MAX)
+		return -ERANGE;
+
+	jerry->storeme = tmp;
+
+	return count;
+}
+
+static struct jerry_attribute jerry_attr_showme = {
+	.attr	= { .name = "showme", .mode = S_IRUGO },
+	.show	= jerry_showme_read,
+};
+static struct jerry_attribute jerry_attr_storeme = {
+	.attr	= { .name = "storeme", .mode = S_IRUGO | S_IWUSR },
+	.show	= jerry_storeme_read,
+	.store	= jerry_storeme_write,
+};
+static struct attribute *jerry_attrs[] = {
+	&jerry_attr_showme.attr,
+	&jerry_attr_storeme.attr,
+	NULL,
+};
+
+static ssize_t jerry_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *page)
+{
+	struct jerry *jerry = to_jerry(kobj);
+	struct jerry_attribute *jerry_attr =
+		container_of(attr, struct jerry_attribute, attr);
+	ssize_t ret = 0;
+
+	if (jerry_attr->show)
+		ret = jerry_attr->show(jerry, page);
+	return ret;
+}
+
+static ssize_t jerry_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *page, size_t count)
+{
+	struct jerry *jerry = to_jerry(kobj);
+	struct jerry_attribute *jerry_attr =
+		container_of(attr, struct jerry_attribute, attr);
+	ssize_t ret = -EINVAL;
+
+	if (jerry_attr->store)
+		ret = jerry_attr->store(jerry, page, count);
+	return ret;
+}
+
+struct sysfs_ops jerry_sysfs_ops = {
+	.show	= &jerry_attr_show,
+	.store	= &jerry_attr_store,
+};
+
+static void jerry_release(struct kobject *kobj)
+{
+	kfree(to_jerry(kobj));
+}
+
+static struct ukobj_type uktype_jerry = {
+	.ktype	= {
+		.release	= jerry_release,
+		.sysfs_ops	= &jerry_sysfs_ops,
+		.default_attrs	= jerry_attrs,
+	},
+	.owner	= THIS_MODULE,
+};
+
+
+struct tom {
+	struct ukset ukset;
+	int showme;
+	int storeme;
+};
+
+struct tom_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct tom *, char *);
+	ssize_t (*store)(struct tom *, const char *, size_t);
+};
+
+static inline struct tom *to_tom(struct kobject *kobj)
+{
+	return kobj ?
+		container_of(to_ukset(to_kset(kobj)), struct tom, ukset) :
+			NULL;
+}
+
+static ssize_t tom_showme_read(struct tom *tom, char *page)
+{
+	ssize_t pos;
+
+	pos = sprintf(page, "%d\n", tom->showme);
+	tom->showme++;
+
+	return pos;
+}
+
+static ssize_t tom_storeme_read(struct tom *tom, char *page)
+{
+	return sprintf(page, "%d\n", tom->storeme);
+}
+
+static ssize_t tom_storeme_write(struct tom *tom, const char *page,
+				 size_t count)
+{
+	unsigned long tmp;
+	char *p = (char *) page;
+
+	tmp = simple_strtoul(p, &p, 10);
+	if (!p || (*p && (*p != '\n')))
+		return -EINVAL;
+
+	if (tmp > INT_MAX)
+		return -ERANGE;
+
+	tom->storeme = tmp;
+
+	return count;
+}
+
+static struct tom_attribute tom_attr_showme = {
+	.attr	= { .name = "showme", .mode = S_IRUGO },
+	.show	= tom_showme_read,
+};
+static struct tom_attribute tom_attr_storeme = {
+	.attr	= { .name = "storeme", .mode = S_IRUGO | S_IWUSR },
+	.show	= tom_storeme_read,
+	.store	= tom_storeme_write,
+};
+static struct attribute *tom_attrs[] = {
+	&tom_attr_showme.attr,
+	&tom_attr_storeme.attr,
+	NULL,
+};
+
+static ssize_t tom_attr_show(struct kobject *kobj,
+			     struct attribute *attr,
+			     char *page)
+{
+	struct tom *tom = to_tom(kobj);
+	struct tom_attribute *tom_attr =
+		container_of(attr, struct tom_attribute, attr);
+	ssize_t ret = 0;
+
+	if (tom_attr->show)
+		ret = tom_attr->show(tom, page);
+	return ret;
+}
+
+static ssize_t tom_attr_store(struct kobject *kobj,
+			      struct attribute *attr,
+			      const char *page, size_t count)
+{
+	struct tom *tom = to_tom(kobj);
+	struct tom_attribute *tom_attr =
+		container_of(attr, struct tom_attribute, attr);
+	ssize_t ret = -EINVAL;
+
+	if (tom_attr->store)
+		ret = tom_attr->store(tom, page, count);
+	return ret;
+}
+
+struct sysfs_ops tom_sysfs_ops = {
+	.show	= &tom_attr_show,
+	.store	= &tom_attr_store,
+};
+
+static void tom_release(struct kobject *kobj)
+{
+	struct tom *tom = to_tom(kobj);
+	kfree(to_jerry(&tom->ukset.default_sets[0]->kobj));
+	kfree(tom);
+}
+
+static struct ukobj_type uktype_tom = {
+	.ktype	= {
+		.release	= tom_release,
+		.sysfs_ops	= &tom_sysfs_ops,
+		.default_attrs	= tom_attrs,
+	},
+	.make_object = usysfs_make_no_object,
+	.owner	= THIS_MODULE,
+};
+
+
+struct tomset {
+	struct ukset ukset;
+	int n_toms;
+};
+
+struct tomset_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct tomset *, char *);
+};
+
+static inline struct tomset *to_tomset(struct kset *kset)
+{
+	return kset ?
+		container_of(to_ukset(kset), struct tomset, ukset) :
+		NULL;
+}
+
+static ssize_t tomset_attr_show(struct kobject *kobj,
+			       struct attribute *attr,
+			       char *page)
+{
+	struct tomset *tomset = to_tomset(to_kset(kobj));
+	struct tomset_attribute *tomset_attr =
+		container_of(attr, struct tomset_attribute, attr);
+	ssize_t ret = 0;
+
+	if (tomset_attr->show)
+		ret = tomset_attr->show(tomset, page);
+	return ret;
+}
+
+static struct sysfs_ops tomset_sysfs_ops = {
+	.show	= &tomset_attr_show,
+};
+
+static ssize_t tomset_toms_read(struct tomset *tomset, char *page)
+{
+	return sprintf(page, "%d Toms love you\n", tomset->n_toms);
+}
+
+static struct tomset_attribute tomset_attr_toms = {
+	.attr	= { .name = "toms", .mode = S_IRUGO },
+	.show	= tomset_toms_read
+};
+
+static struct attribute *tomset_attrs[] = {
+	&tomset_attr_toms.attr,
+	NULL,
+};
+
+static struct kset *make_tom(struct kset *kset, const char *name)
+{
+	struct tomset *tomset = to_tomset(kset);
+	struct tom *tom;
+	struct jerry *jerry;
+
+	tom = kmalloc(sizeof(struct tom), GFP_KERNEL);
+	if (!tom)
+		return NULL;
+
+	memset(tom, 0, sizeof(struct tom));
+	tom->ukset.default_sets = kmalloc(sizeof(struct kset *) * 2,
+		       			  GFP_KERNEL);
+	if (!tom->ukset.default_sets) {
+		kfree(tom);
+		return NULL;
+	}
+
+	jerry = kmalloc(sizeof(struct jerry), GFP_KERNEL);
+	if (!jerry) {
+		kfree(tom->ukset.default_sets);
+		kfree(tom);
+		return NULL;
+	}
+
+	memset(jerry, 0, sizeof(struct jerry));
+
+	kobject_set_name(&tom->ukset.kset.kobj, name);
+	tom->ukset.kset.kobj.ktype = &uktype_tom.ktype;
+	ukset_init(&tom->ukset);
+
+	tom->showme = 0;
+	tom->storeme = 0;
+	tomset->n_toms++;
+
+	kobject_set_name(&jerry->ukset.kset.kobj, "jer");
+	jerry->ukset.kset.kobj.ktype = &uktype_jerry.ktype;
+	ukset_init(&jerry->ukset);
+
+	tom->ukset.default_sets[0] = &jerry->ukset.kset;
+	tom->ukset.default_sets[1] = NULL;
+
+	return &tom->ukset.kset;
+}
+
+static void drop_tom(struct kset *kset, struct kobject *kobj)
+{
+	struct tomset *tomset = to_tomset(kset);
+
+	tomset->n_toms--;
+	kobject_put(kobj);
+}
+
+static struct ukobj_type uktype_tomset = {
+	.ktype = {
+		.sysfs_ops	= &tomset_sysfs_ops,
+		.default_attrs	= tomset_attrs,
+	},
+	.make_kset	= make_tom,
+	.drop_object	= drop_tom,
+};
+
+static struct tomset tomset = {
+	.ukset = {
+		.kset = {
+			.kobj = {
+				.name = "tomset",
+				.ktype = &uktype_tomset.ktype,
+			},
+		},
+	},
+	.n_toms = 0,
+};
+
 static int __init bobtest_init(void)
 {
 	int ret;
 
-	kset_init(&bobset.kset);
-	kset_init(&robert.kset);
-	ret = usysfs_register_subsystem(&bobset.kset);
+	ukset_init(&bobset.ukset);
+	ukset_init(&robert.ukset);
+	ukset_init(&tomset.ukset);
+	ret = usysfs_register_subsystem(&bobset.ukset.kset);
+	if (!ret)
+		ret = usysfs_register_subsystem(&tomset.ukset.kset);
 	if (ret)
 		printk(KERN_ERR "bobtest: Registration returned %d\n", ret);
 
@@ -324,7 +692,8 @@
 
 static void __exit bobtest_exit(void)
 {
-	usysfs_unregister_subsystem(&bobset.kset);
+	usysfs_unregister_subsystem(&tomset.ukset.kset);
+	usysfs_unregister_subsystem(&bobset.ukset.kset);
 }
 
 module_init(bobtest_init);

Modified: trunk/fs/usysfs/dir.c
===================================================================
--- trunk/fs/usysfs/dir.c	2005-03-10 23:56:53 UTC (rev 1969)
+++ trunk/fs/usysfs/dir.c	2005-03-11 01:12:47 UTC (rev 1970)
@@ -364,8 +364,21 @@
 			continue;
 		list_del_init(&sd->s_sibling);
 		child = sd->s_dentry;
+		down(&child->d_inode->i_sem);
 		usysfs_drop_set(sd->s_element);
-		d_delete(child);
+		up(&child->d_inode->i_sem);
+
+		/*
+		 * This is important.  If the child is still hashed,
+		 * dput() will just put it somewhere safe.  So there
+		 * will not be a chain back to dput()ing the parent.
+		 * At least, not until umount.  This means dentries
+		 * hanging about.  Bad Idea Jeans.  d_delete() would
+		 * leave it hashed, but negative.  That's good for
+		 * stuff coming from the VFS, not for our hand-built
+		 * default_sets.  d_drop unhashes.  Bingo!
+		 */
+		d_drop(child);
 		dput(child);
 		usysfs_put(sd);
 	}
@@ -376,13 +389,19 @@
 	dput(dentry);
 }
 
+/*
+ * This fakes mkdir(2) on a default_sets[] entry.  It
+ * creates a dentry, instantiates it, and then does fixup
+ * on the sd->s_type.
+ */
 static int create_default_set(struct kset *parent_kset,
 			      struct kset *kset)
 {
 	int ret;
 	struct qstr name;
+	struct usysfs_dirent *sd;
+	/* We trust the caller holds a reference to parent */
 	struct dentry *child, *parent = parent_kset->kobj.dentry;
-	struct usysfs_dirent *sd;
 
 	if (!kset->kobj.k_name)
 		kset->kobj.k_name = kset->kobj.name;
@@ -401,14 +420,7 @@
 			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);
+			d_drop(child);
 			dput(child);
 		}
 	}
@@ -418,17 +430,17 @@
 
 static int populate_sets(struct kset *kset)
 {
-	struct ukobj_type *uktype = to_uktype(kset->kobj.ktype);
+	struct ukset *ukset = to_ukset(kset);
 	struct kset *new_set;
 	struct dentry *dentry = kset->kobj.dentry;
 	int ret = 0;
 	int i;
 
-	if (uktype && uktype->default_sets) {
+	if (ukset && ukset->default_sets) {
 		down(&dentry->d_inode->i_sem);
 
-		for (i = 0; uktype->default_sets[i]; i++) {
-			new_set = uktype->default_sets[i];
+		for (i = 0; ukset->default_sets[i]; i++) {
+			new_set = ukset->default_sets[i];
 
 			ret = create_default_set(kset, new_set);
 			if (ret)
@@ -474,6 +486,21 @@
 	kobject_get(kobj);
 }
 
+/*
+ * The goal is that usysfs_instantiate_object() (and
+ * usysfs_instantiate_set()) can be called from either the VFS or this
+ * module.  That is, they assume that the objects have been created,
+ * the dentry allocated, and the dcache is all ready to go.
+ * 
+ * If they fail, they must clean up after themselves as if they
+ * had never been called.  The caller (VFS or local function) will
+ * handle cleaning up the dcache bits.
+ *
+ * usysfs_drop_set() and usysfs_drop_object() behave similarly on the
+ * way out.  They assume that the proper semaphores are held, they
+ * clean up the usysfs objects, and they expect their callers will
+ * handle the dcache bits.
+ */
 static int usysfs_instantiate_object(struct kobject *parent_kobj,
 				     struct kobject *kobj,
 				     struct dentry *dentry)
@@ -555,8 +582,9 @@
 	snprintf(name, dentry->d_name.len + 1, "%s", dentry->d_name.name);
 	if (uktype->make_kset) {
 		kset = uktype->make_kset(to_kset(parent_kobj), name);
-		kobj = &kset->kobj;
+		kobj = kset ? &kset->kobj : NULL;
 	} else {
+		kset = NULL;
 		kobj = uktype->make_object(to_kset(parent_kobj), name);
 	}
 	kfree(name);
@@ -570,9 +598,15 @@
 	if (uktype) {
 		owner = uktype->owner;
 		if (try_module_get(owner)) {
-			ret = usysfs_instantiate_object(parent_kobj,
-							kobj, dentry);
+			if (kset)
+				ret = usysfs_instantiate_set(parent_kobj,
+							     kobj,
+							     dentry);
+			else
+				ret = usysfs_instantiate_object(parent_kobj,
+								kobj, dentry);
 			if (ret) {
+				/* XXX: Should be ->drop_object() */
 				kobject_put(parent_kobj);
 				module_put(owner);
 			}
@@ -582,6 +616,7 @@
 	return ret;
 }
 
+/* Sets must have make_kset() or make_object() */
 static int is_set(struct kobject *kobj)
 {
 	int ret = 0;
@@ -593,8 +628,6 @@
 			ret = 1;
 		else if (uktype->make_object)
 			ret = 1;
-		else if (uktype->default_sets)
-			ret = 1;
 	}
 
 	return ret;
@@ -851,7 +884,6 @@
 	struct qstr name;
 	struct dentry *dentry;
 	struct usysfs_dirent *sd;
-	struct kset *root_set;
 
 	err = usysfs_pin_fs();
 	if (err)
@@ -875,12 +907,11 @@
 	d_add(dentry, NULL);
 
 	sd = usysfs_sb->s_root->d_fsdata;
-	root_set = sd->s_element;
-	err = usysfs_instantiate_set(&root_set->kobj, &k->kobj, dentry);
+	err = usysfs_instantiate_set(sd->s_element, &k->kobj, dentry);
 	if (!err)
 		dentry = NULL;
 	else
-		d_delete(dentry);
+		d_drop(dentry);
 
 	up(&usysfs_sb->s_root->d_inode->i_sem);
 
@@ -905,9 +936,11 @@
 		printk(KERN_ERR "usysfs: Tried to unregister non-empty subsystem!\n");
 	}
 	usysfs_drop_set(&k->kobj);
+	/* See comment in drop_sets() regarding d_drop() */
+	d_drop(k->kobj.dentry);
+
 	up(&usysfs_sb->s_root->d_inode->i_sem);
 
-	d_delete(k->kobj.dentry);
 	dput(k->kobj.dentry);
 	usysfs_release_fs();
 }

Modified: trunk/fs/usysfs/mount.c
===================================================================
--- trunk/fs/usysfs/mount.c	2005-03-10 23:56:53 UTC (rev 1969)
+++ trunk/fs/usysfs/mount.c	2005-03-11 01:12:47 UTC (rev 1970)
@@ -34,27 +34,36 @@
 #endif
 };
 
-static struct kset usysfs_root_set = {
-	.kobj = {
-		.name	= "root",
-		.k_name	= usysfs_root_set.kobj.name,
+static struct ukset usysfs_root_set = {
+	.kset = {
+		.kobj = {
+			.name	= "root",
+			.k_name	= usysfs_root_set.kset.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	= &usysfs_root_set,
+	.s_element	= &usysfs_root_set.kset.kobj,
 	.s_type		= USYSFS_ROOT,
 };
 
 /* Kernel idiots 1, universe 0 */
-void kset_init(struct kset *k)
+static void kset_init_copy(struct kset *k)
 {
 	kobject_init(&k->kobj);
 	INIT_LIST_HEAD(&k->list);
 }
 
+void ukset_init(struct ukset *ukset)
+{
+	kset_init_copy(&ukset->kset);
+}
+
+EXPORT_SYMBOL_GPL(ukset_init);
+
 static int usysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct inode *inode;
@@ -83,8 +92,8 @@
 		iput(inode);
 		return -ENOMEM;
 	}
-	kset_init(&usysfs_root_set);
-	usysfs_root_set.kobj.dentry = root;
+	ukset_init(&usysfs_root_set);
+	usysfs_root_set.kset.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-10 23:56:53 UTC (rev 1969)
+++ trunk/fs/usysfs/usysfs.h	2005-03-11 01:12:47 UTC (rev 1970)
@@ -35,19 +35,20 @@
 /*
  * Usysfs objects must have a ->ktype of type ukobj_type.
  * If allow_link() exists, the object can symlink(2) out to other
- * objects.  If the object is a kset, it may support mkdir(2).  If the
+ * objects.  If the object is a kset, it may support mkdir(2).  Kset
+ * objects must supply one of make_kset() and make_object().  If the
  * object supports make_kset(), one can create kset children.  If it
  * supports make_object(), one can create kobject children.  If it has
- * default_sets, it has automatically created kset children.
- * default_sets may coexist alongsize make_kset() or make_object(), but
- * an object can only have one or zero of mkae_kset() and make_object().
- * If the kset has commit(), it supports pending and commited (active)
- * objects.
+ * default_sets on ukset->default_sets, it has automatically created
+ * kset children.  default_sets may coexist alongsize make_kset() or
+ * make_object(), but if the kset wishes to have only default_sets 
+ * children (disallowing mkdir(2)), it must provide
+ * usysfs_make_no_object() as the value for make_object().  If the kset
+ * has commit(), it supports pending and commited (active) objects.
  */
 struct ukobj_type {
 	struct kobj_type ktype;
 	struct module *owner;
-	struct kset **default_sets;
 	int (*allow_link)(struct kobject *src, struct kobject *target);
 	struct kobject *(*make_object)(struct kset *kset, const char *name);
 	struct kset *(*make_kset)(struct kset *kset, const char *name);
@@ -62,7 +63,30 @@
 		NULL;
 }
 
+static inline struct kobject *usysfs_make_no_object(struct kset *kset,
+						    const char *name)
+{
+	return NULL;
+}
 
+
+/*
+ * Usysfs ksets must actually be of type ukset.  This allows default
+ * child sets to be created.
+ */
+struct ukset {
+	struct kset kset;
+	struct kset **default_sets;
+};
+
+static inline struct ukset *to_ukset(struct kset *kset)
+{
+	return kset ? container_of(kset, struct ukset, kset) : NULL;
+}
+
+extern void ukset_init(struct ukset *ukset);
+
+
 /**
  * Use these macros to make defining attributes easier. See include/linux/device.h
  * for examples..



More information about the Ocfs2-commits mailing list