[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