Convert sd->s_dir.kobj to sd->s_dir.data and make it void *, and
implement sd based directory creation function sysfs_add_dir().  Using
this function the caller can create directory node with arbitrary user
data.  Also, name copying is not implicit.  Name is copied iff
SYSFS_COPY_NAME should be specified in @mode.

* sysfs_root is exported.  To be used as @parent when creating a node
  below the sysfs root.

* Kobject-based sysfs_create_dir() is reimplemented in terms of
  sysfs_add_dir() and moved to fs/sysfs/kobject.c.

* Users of sysfs_create_dir() in sysfs are converted to use
  sysfs_add_dir().

* attr and bin_attr still can cope only with kobject sd->s_dir.data,
  so sysfs_add_dir() can't be used with arbitrary pointer yet.  This
  will be changed by following patches.

This patch doesn't introduce any behavior change to the original API.

Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
---
 fs/sysfs/bin.c        |    6 +-
 fs/sysfs/dir.c        |  108 +++++++++++++++++++++++++++----------------------
 fs/sysfs/file.c       |    6 +-
 fs/sysfs/group.c      |    8 ++--
 fs/sysfs/kobject.c    |   26 ++++++++++++
 fs/sysfs/mount.c      |    2 +
 fs/sysfs/sysfs.h      |    8 +--
 include/linux/sysfs.h |   16 +++++++
 8 files changed, 117 insertions(+), 63 deletions(-)

diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index 1c12cf0..91e573f 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -31,7 +31,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, 
size_t count)
 {
        struct sysfs_dirent *attr_sd = dentry->d_fsdata;
        struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        int rc;
 
        /* need attr_sd for attr, its parent for kobj */
@@ -88,7 +88,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t 
offset, size_t count)
 {
        struct sysfs_dirent *attr_sd = dentry->d_fsdata;
        struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        int rc;
 
        /* need attr_sd for attr, its parent for kobj */
@@ -141,7 +141,7 @@ static int mmap(struct file *file, struct vm_area_struct 
*vma)
        struct bin_buffer *bb = file->private_data;
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
        struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        int rc;
 
        mutex_lock(&bb->mutex);
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 7cb3f1e..b15ade7 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -7,7 +7,6 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/module.h>
-#include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/idr.h>
 #include <linux/completion.h>
@@ -639,6 +638,40 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
 }
 
 /**
+ *     sysfs_insert_one - shortcut function to add single sysfs_dirent
+ *     @parent: parent to add sysfs_dirent under
+ *     @sd: sysfs_dirent to add
+ *
+ *     A shortcut function to perform sysfs_addrm_start, add_one,
+ *     addrm_finish sequence and error handling for a single
+ *     sysfs_dirent.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Pointer to the new sysfs_dirent on success, ERR_PTR() value on
+ *     failure.
+ */
+struct sysfs_dirent *sysfs_insert_one(struct sysfs_dirent *parent,
+                                     struct sysfs_dirent *sd)
+{
+       struct sysfs_addrm_cxt acxt;
+       int rc;
+
+       sysfs_addrm_start(&acxt);
+       rc = sysfs_add_one(&acxt, parent, sd);
+       sysfs_addrm_finish(&acxt);
+
+       if (rc) {
+               sysfs_put(sd);
+               return ERR_PTR(rc);
+       }
+
+       return sd;
+}
+
+/**
  *     sysfs_find_dirent - find sysfs_dirent with the given name
  *     @parent_sd: sysfs_dirent to search under
  *     @name: name to look for
@@ -722,60 +755,39 @@ struct sysfs_dirent *sysfs_find_child(struct sysfs_dirent 
*parent,
 }
 EXPORT_SYMBOL_GPL(sysfs_find_child);
 
-static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
-                     const char *name, struct sysfs_dirent **p_sd)
-{
-       umode_t mode = S_IRWXU | S_IRUGO | S_IXUGO;
-       struct sysfs_addrm_cxt acxt;
-       struct sysfs_dirent *sd;
-       int rc;
-
-       /* allocate */
-       sd = sysfs_new_dirent(name, mode | SYSFS_COPY_NAME, SYSFS_DIR);
-       if (!sd)
-               return -ENOMEM;
-       sd->s_dir.kobj = kobj;
-
-       /* link in */
-       sysfs_addrm_start(&acxt);
-       rc = sysfs_add_one(&acxt, parent_sd, sd);
-       sysfs_addrm_finish(&acxt);
-
-       if (rc == 0)
-               *p_sd = sd;
-       else
-               sysfs_put(sd);
-
-       return rc;
-}
-
-int sysfs_create_subdir(struct kobject *kobj, const char *name,
-                       struct sysfs_dirent **p_sd)
-{
-       return create_dir(kobj, kobj->sd, name, p_sd);
-}
-
 /**
- *     sysfs_create_dir - create a directory for an object.
- *     @kobj:          object we're creating directory for. 
+ *     sysfs_add_dir - add a new sysfs directory
+ *     @parent: sysfs_dirent to add the directory under
+ *     @name: name of the new directory
+ *     @mode: mode and SYSFS_* flags for the new directory
+ *     @data: s_dir.data for the new directory
+ *
+ *     Add a new directory under @parent with the specified
+ *     parameters.  If SYSFS_COPY_NAME is set in @mode, @name is
+ *     copied before being used.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ *
+ *     RETURNS:
+ *     Pointer to the new sysfs_dirent on success, ERR_PTR() value on
+ *     error.
  */
-int sysfs_create_dir(struct kobject * kobj)
+struct sysfs_dirent *sysfs_add_dir(struct sysfs_dirent *parent,
+                                  const char *name, mode_t mode, void *data)
 {
-       struct sysfs_dirent *parent_sd, *sd;
-       int error = 0;
+       struct sysfs_dirent *sd;
 
-       BUG_ON(!kobj);
+       /* allocate and initialize */
+       sd = sysfs_new_dirent(name, mode, SYSFS_DIR);
+       if (!sd)
+               return ERR_PTR(-ENOMEM);
 
-       if (kobj->parent)
-               parent_sd = kobj->parent->sd;
-       else
-               parent_sd = sysfs_root;
+       sd->s_dir.data = data;
 
-       error = create_dir(kobj, parent_sd, kobject_name(kobj), &sd);
-       if (!error)
-               kobj->sd = sd;
-       return error;
+       return sysfs_insert_one(parent, sd);
 }
+EXPORT_SYMBOL_GPL(sysfs_add_dir);
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
                                struct nameidata *nd)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1faba5f..8154fbb 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -145,7 +145,7 @@ void sysfs_file_check_suicide(struct sysfs_dirent *sd)
 static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * 
buffer)
 {
        struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        struct sysfs_ops * ops = buffer->ops;
        int ret = 0;
        ssize_t count;
@@ -265,7 +265,7 @@ static int
 flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, 
size_t count)
 {
        struct sysfs_dirent *attr_sd = dentry->d_fsdata;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        struct sysfs_ops * ops = buffer->ops;
        int rc;
 
@@ -404,7 +404,7 @@ static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
 static int sysfs_open_file(struct inode *inode, struct file *file)
 {
        struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
-       struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
+       struct kobject *kobj = attr_sd->s_parent->s_dir.data;
        struct sysfs_buffer * buffer;
        struct sysfs_ops * ops = NULL;
        int error;
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index cef0376..e4993fd 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -39,7 +39,7 @@ static int create_files(struct sysfs_dirent *dir_sd,
 }
 
 
-int sysfs_create_group(struct kobject * kobj, 
+int sysfs_create_group(struct kobject * kobj,
                       const struct attribute_group * grp)
 {
        struct sysfs_dirent *sd;
@@ -48,9 +48,9 @@ int sysfs_create_group(struct kobject * kobj,
        BUG_ON(!kobj || !kobj->sd);
 
        if (grp->name) {
-               error = sysfs_create_subdir(kobj, grp->name, &sd);
-               if (error)
-                       return error;
+               sd = sysfs_add_dir(kobj->sd, grp->name, SYSFS_DIR_MODE, kobj);
+               if (IS_ERR(sd))
+                       return PTR_ERR(sd);
        } else
                sd = kobj->sd;
        sysfs_get(sd);
diff --git a/fs/sysfs/kobject.c b/fs/sysfs/kobject.c
index 9415f18..8e4677c 100644
--- a/fs/sysfs/kobject.c
+++ b/fs/sysfs/kobject.c
@@ -30,6 +30,32 @@ static int sysfs_remove_child(struct sysfs_dirent *parent, 
const char *name)
 }
 
 /**
+ *     sysfs_create_dir - create a directory for an object.
+ *     @kobj:  object we're creating directory for.
+ */
+int sysfs_create_dir(struct kobject *kobj)
+{
+       struct sysfs_dirent *parent, *sd;
+
+       BUG_ON(!kobj);
+
+       if (kobj->parent) {
+               parent = kobj->parent->sd;
+               if (!parent)
+                       return -EFAULT;
+       } else
+               parent = sysfs_root;
+
+       sd = sysfs_add_dir(parent, kobject_name(kobj),
+                          SYSFS_DIR_MODE | SYSFS_COPY_NAME, kobj);
+       if (IS_ERR(sd))
+               return PTR_ERR(sd);
+
+       kobj->sd = sd;
+       return 0;
+}
+
+/**
  *     sysfs_remove_dir - remove an object's directory.
  *     @kobj:  object.
  *
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index d00d4b9..d61eb08 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -8,6 +8,7 @@
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include "sysfs.h"
 
@@ -32,6 +33,7 @@ static struct sysfs_dirent sysfs_root_storage = {
 };
 
 struct sysfs_dirent * const sysfs_root = &sysfs_root_storage;
+EXPORT_SYMBOL_GPL(sysfs_root);
 
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
 {
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 9494f3d..82ade38 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,7 +2,7 @@ struct sysfs_open_dirent;
 
 /* type-specific structures for sysfs_dirent->s_* union members */
 struct sysfs_elem_dir {
-       struct kobject          *kobj;
+       void                    *data;
        /* children list starts here and goes through sd->s_sibling */
        struct sysfs_dirent     *children;
 };
@@ -78,7 +78,6 @@ struct sysfs_addrm_cxt {
 /*
  * mount.c
  */
-extern struct sysfs_dirent * const sysfs_root;
 extern struct super_block *sysfs_sb;
 extern struct kmem_cache *sysfs_dir_cachep;
 
@@ -102,6 +101,8 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct 
sysfs_dirent *parent,
                  struct sysfs_dirent *sd);
 void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
 void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
+struct sysfs_dirent *sysfs_insert_one(struct sysfs_dirent *parent,
+                                     struct sysfs_dirent *sd);
 
 struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
                                       const unsigned char *name);
@@ -113,9 +114,6 @@ void __sysfs_remove(struct sysfs_dirent *sd, int recurse);
 
 void release_sysfs_dirent(struct sysfs_dirent *sd);
 
-int sysfs_create_subdir(struct kobject *kobj, const char *name,
-                       struct sysfs_dirent **p_sd);
-
 static inline struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd)
 {
        if (sd) {
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 4ad2874..3c64b4a 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -17,6 +17,8 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/err.h>
 
 struct sysfs_dirent;
 struct vm_area_struct;
@@ -26,6 +28,7 @@ struct vm_area_struct;
  * valid as real mode bits.  Bits in S_IFMT are used to set sysfs
  * specific flags.
  */
+#define SYSFS_DIR_MODE         (S_IRWXU | S_IRUGO | S_IXUGO)
 #define SYSFS_COPY_NAME                010000  /* copy passed @name */
 
 /* collection of all flags for verification */
@@ -33,6 +36,11 @@ struct vm_area_struct;
 
 #ifdef CONFIG_SYSFS
 
+extern struct sysfs_dirent * const sysfs_root;
+
+struct sysfs_dirent *sysfs_add_dir(struct sysfs_dirent *parent,
+                       const char *name, mode_t mode, void *data);
+
 struct sysfs_dirent *sysfs_find_child(struct sysfs_dirent *parent,
                                      const char *name);
 void sysfs_remove(struct sysfs_dirent *sd);
@@ -41,6 +49,14 @@ int __must_check sysfs_init(void);
 
 #else /* CONFIG_SYSFS */
 
+#define sysfs_root             ((struct sysfs_dirent *)NULL)
+
+static inline struct sysfs_dirent *sysfs_add_dir(struct sysfs_dirent *parent,
+                       const char *name, mode_t mode, void *data)
+{
+       return NULL;
+}
+
 static inline struct sysfs_dirent *sysfs_find_child(struct sysfs_dirent 
*parent,
                                                    const char *name)
 {
-- 
1.5.0.3


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to