[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