lkml.org 
[lkml]   [2007]   [Sep]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 08/22] sysfs: implement sysfs_dirent based directory interface
    Date
    From
    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 <htejun@gmail.com>
    ---
    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 majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-09-20 10:11    [W:3.523 / U:0.264 seconds]
    ©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site