[Ocfs2-commits] jlbec commits r1792 - trunk/usysfs
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Jan 18 23:09:35 CST 2005
Author: jlbec
Date: 2005-01-18 23:09:33 -0600 (Tue, 18 Jan 2005)
New Revision: 1792
Modified:
trunk/usysfs/bobtest.c
trunk/usysfs/dir.c
trunk/usysfs/usysfs.h
Log:
o mkdir/rmdir pairs work, and so now one can unload modules.
Modified: trunk/usysfs/bobtest.c
===================================================================
--- trunk/usysfs/bobtest.c 2005-01-18 22:53:05 UTC (rev 1791)
+++ trunk/usysfs/bobtest.c 2005-01-19 05:09:33 UTC (rev 1792)
@@ -106,11 +106,18 @@
.store = &bob_attr_store,
};
+static void bob_release(struct kobject *kobj)
+{
+ kfree(to_bob(kobj));
+}
+
static struct ukobj_type uktype_bob = {
- .ktype = {
+ .ktype = {
+ .release = bob_release,
.sysfs_ops = &bob_sysfs_ops,
.default_attrs = bob_attrs,
},
+ .owner = THIS_MODULE,
};
@@ -185,12 +192,21 @@
return &bob->kobj;
}
+static void drop_bob(struct kobject *kobj)
+{
+ struct bobset *bobset = to_bobset(kobj->kset);
+
+ bobset->n_bobs--;
+ kobject_put(kobj);
+}
+
static struct ukobj_type uktype_bobset = {
.ktype = {
.sysfs_ops = &bobset_sysfs_ops,
.default_attrs = bobset_attrs,
},
.make_object = make_bob,
+ .drop_object = drop_bob,
};
static struct bobset bobset = {
Modified: trunk/usysfs/dir.c
===================================================================
--- trunk/usysfs/dir.c 2005-01-18 22:53:05 UTC (rev 1791)
+++ trunk/usysfs/dir.c 2005-01-19 05:09:33 UTC (rev 1792)
@@ -218,7 +218,7 @@
if (!found) {
/*
* If it doesn't exist and it isn't a NOT_PINNED item,
- * it must be negative
+ * it must be negative.
*/
return simple_lookup(dir, dentry, nd);
}
@@ -226,6 +226,24 @@
return ERR_PTR(err);
}
+/*
+ * Only subdirectories count here. Files (SYSFS_NOT_PINNED) are
+ * attributes and are removed by rmdir().
+ */
+static int usysfs_empty_dir(struct dentry *dentry)
+{
+ struct usysfs_dirent *parent_sd = dentry->d_fsdata;
+ struct usysfs_dirent *sd;
+
+ list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
+ if (sd->s_type & SYSFS_NOT_PINNED)
+ continue;
+ return 0;
+ }
+
+ return 1;
+}
+
static int populate_dir(struct kobject *kobj)
{
struct kobj_type *t = get_ktype(kobj);
@@ -251,12 +269,20 @@
*/
static void unlink(struct kobject *kobj)
{
+ struct ukobj_type *uktype;
+ struct module *owner = NULL;
+
if (kobj->kset) {
down(&usysfs_linkage_sem);
list_del_init(&kobj->entry);
up(&usysfs_linkage_sem);
}
+ uktype = to_uktype(kobj->ktype);
+ if (uktype)
+ owner = uktype->owner;
+
kobject_put(kobj);
+ module_put(owner);
}
static int usysfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -274,7 +300,6 @@
parent_kobj = usysfs_get_kobject(dentry->d_parent);
uktype = to_uktype(parent_kobj->ktype);
- printk("In mkdir %s\n", parent_kobj->k_name);
if (!uktype || (!uktype->make_kset && !uktype->make_object)) {
kobject_put(parent_kobj);
return -EPERM; /* What lack-of-mkdir returns */
@@ -298,7 +323,14 @@
return -ENOMEM;
}
- kobj->kset = to_kset(parent_kobj);
+ uktype = to_uktype(kobj->ktype);
+ if (!uktype || !try_module_get(uktype->owner)) {
+ kobject_put(kobj);
+ kobject_put(parent_kobj);
+ return -ENOENT;
+ }
+
+ kobj->kset = kset_get(to_kset(parent_kobj));
down(&usysfs_linkage_sem);
list_add_tail(&kobj->entry, &kobj->kset->list);
up(&usysfs_linkage_sem);
@@ -312,14 +344,59 @@
}
ret = populate_dir(kobj);
- if (ret)
+ if (ret) {
usysfs_remove_dir(kobj);
+ d_delete(dentry);
+ unlink(kobj);
+ kobject_put(parent_kobj);
+ }
return ret;
}
+static int usysfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ struct kobject *parent_kobj;
+ struct kobject *kobj;
+ struct ukobj_type *uktype;
+
+ if (dentry->d_parent == usysfs_sb->s_root)
+ return -EPERM;
+
+
+ parent_kobj = usysfs_get_kobject(dentry->d_parent);
+
+ uktype = to_uktype(parent_kobj->ktype);
+ if (!uktype) {
+ kobject_put(parent_kobj);
+ return -EINVAL;
+ }
+
+ if (!usysfs_empty_dir(dentry)) {
+ kobject_put(parent_kobj);
+ return -ENOTEMPTY;
+ }
+
+ kobj = usysfs_get_kobject(dentry);
+
+ /* Drop reference from above, kobj already holds one. */
+ kobject_put(parent_kobj);
+
+ usysfs_remove_dir(kobj);
+
+ if (uktype->drop_object)
+ uktype->drop_object(kobj);
+ else
+ kobject_put(kobj);
+
+ unlink(kobj);
+
+ return 0;
+}
+
struct inode_operations usysfs_dir_inode_operations = {
.mkdir = usysfs_mkdir,
+ .rmdir = usysfs_rmdir,
.lookup = usysfs_lookup,
};
@@ -328,8 +405,6 @@
struct dentry * parent = dget(d->d_parent);
struct usysfs_dirent * sd;
- down(&parent->d_inode->i_sem);
- d_delete(d);
sd = d->d_fsdata;
list_del_init(&sd->s_sibling);
usysfs_put(sd);
@@ -339,7 +414,6 @@
pr_debug(" o %s removing done (%d)\n",d->d_name.name,
atomic_read(&d->d_count));
- up(&parent->d_inode->i_sem);
dput(parent);
}
@@ -368,7 +442,6 @@
return;
pr_debug("usysfs %s: removing dir\n",dentry->d_name.name);
- down(&dentry->d_inode->i_sem);
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 & SYSFS_NOT_PINNED))
@@ -377,7 +450,6 @@
usysfs_drop_dentry(sd, dentry);
usysfs_put(sd);
}
- up(&dentry->d_inode->i_sem);
remove_dir(dentry);
/**
@@ -572,34 +644,66 @@
if (err)
return err;
- err = -ENOMEM;
+ k->kobj.kset = k;
if (!k->kobj.k_name)
k->kobj.k_name = k->kobj.name;
+
+ down(&usysfs_sb->s_root->d_inode->i_sem);
+
name.name = k->kobj.k_name;
name.len = strlen(name.name);
name.hash = full_name_hash(name.name, name.len);
+
+ err = -ENOMEM;
dentry = d_alloc(usysfs_sb->s_root, &name);
- if (dentry) {
- err = usysfs_create_dir(&k->kobj, dentry);
- }
+ if (!dentry)
+ goto out_release;
+
+ err = usysfs_create_dir(&k->kobj, dentry);
+ if (err)
+ goto out_dput;
- if (!err) {
- d_rehash(dentry);
- err = populate_dir(&k->kobj);
- if (err)
- usysfs_remove_dir(&k->kobj);
+ d_rehash(dentry);
+ up(&usysfs_sb->s_root->d_inode->i_sem);
+
+ err = populate_dir(&k->kobj);
+ if (err) {
+ down(&usysfs_sb->s_root->d_inode->i_sem);
+ usysfs_remove_dir(&k->kobj);
+ up(&usysfs_sb->s_root->d_inode->i_sem);
+ d_delete(dentry);
+ goto out_dput;
}
- if (err)
- usysfs_release_fs();
+ return 0;
+out_dput:
+ dput(dentry);
+out_release:
+ usysfs_release_fs();
+
return err;
}
void usysfs_unregister_subsystem(struct kset *k)
{
- printk("Unregister is broken\n");
+ if (k->kobj.dentry->d_parent != usysfs_sb->s_root) {
+ printk(KERN_ERR "usysfs: Tried to unregister non-subsystem!\n");
+ 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");
+ }
usysfs_remove_dir(&k->kobj);
+ up(&usysfs_sb->s_root->d_inode->i_sem);
+ d_delete(k->kobj.dentry);
+ dput(k->kobj.dentry);
usysfs_release_fs();
}
Modified: trunk/usysfs/usysfs.h
===================================================================
--- trunk/usysfs/usysfs.h 2005-01-18 22:53:05 UTC (rev 1791)
+++ trunk/usysfs/usysfs.h 2005-01-19 05:09:33 UTC (rev 1792)
@@ -42,10 +42,12 @@
*/
struct ukobj_type {
struct kobj_type ktype;
+ struct module *owner;
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);
int (*commit)(struct kobject *kobj);
+ void (*drop_object)(struct kobject *kobj);
};
static inline struct ukobj_type *to_uktype(struct kobj_type *ktype)
More information about the Ocfs2-commits
mailing list