]> git.neil.brown.name Git - history.git/commitdiff
driverfs: define struct driverfs_ops and remove struct device dependencies
authorPatrick Mochel <mochel@osdl.org>
Thu, 1 Aug 2002 05:07:33 +0000 (22:07 -0700)
committerPatrick Mochel <mochel@osdl.org>
Thu, 1 Aug 2002 05:07:33 +0000 (22:07 -0700)
In order to read/write attributes, you have to deal directly with the object that owns them. driverfs really
wants to be generic and not deal directly with those objects. So, we create an intermediate layer that
subsystems must implement that converts between the generic objects and the specific objects that own the
attributes.

This allows allows attributes to be exported for any object type.

In doing so, it places the responsibility on the subsystems to do the following:

- define their own object-specific attribute structures
- define their own driverfs_ops
- set the ops pointer in struct driver_dir_entry when creating an object's directory
- do object reference counting on open() and close()
- call the show() and store() callbacks of their attribute structure
- convert between the generic objects and the specific objects from the struct driver_dir_entry and
  struct attribute pointers (using container_of)

The implementation of this layer for struct device is intended to be used as an example of the interface.

Because this layer of abstraction is now in place, we can move the device attribute structure into
include/linux/device.h, and driverfs should be free of references to it completely.

drivers/base/fs.c
fs/driverfs/inode.c
include/linux/device.h
include/linux/driverfs_fs.h

index a50586b8c45aea2ee1082603407a8230a0858cc0..62df2c48be3fc7e1e91cc451769e8e5584559b21 100644 (file)
 
 extern struct device_attribute * device_default_files[];
 
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+
+#define to_device(d) container_of(d, struct device, dir)
+
+
+/* driverfs ops for device attribute files */
+
+static int
+dev_attr_open(struct driver_dir_entry * dir)
+{
+       struct device * dev = to_device(dir);
+       get_device(dev);
+       return 0;
+}
+
+static int
+dev_attr_close(struct driver_dir_entry * dir)
+{
+       struct device * dev = to_device(dir);
+       put_device(dev);
+       return 0;
+}
+
+static ssize_t
+dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
+             char * buf, size_t count, loff_t off)
+{
+       struct device_attribute * dev_attr = to_dev_attr(attr);
+       struct device * dev = to_device(dir);
+       ssize_t ret = 0;
+
+       if (dev_attr->show)
+               ret = dev_attr->show(dev,buf,count,off);
+       return ret;
+}
+
+static ssize_t
+dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
+              const char * buf, size_t count, loff_t off)
+{
+       struct device_attribute * dev_attr = to_dev_attr(attr);
+       struct device * dev = to_device(dir);
+       ssize_t ret = 0;
+
+       if (dev_attr->store)
+               ret = dev_attr->store(dev,buf,count,off);
+       return ret;
+}
+
+static struct driverfs_ops dev_attr_ops = {
+       open:   dev_attr_open,
+       close:  dev_attr_close,
+       show:   dev_attr_show,
+       store:  dev_attr_store,
+};
+
 /**
  * device_create_file - create a driverfs file for a device
  * @dev:       device requesting file
@@ -159,6 +215,7 @@ int device_make_dir(struct device * dev)
        if (dev->parent)
                parent = &dev->parent->dir;
        dev->dir.name = dev->bus_id;
+       dev->dir.ops = &dev_attr_ops;
 
        if ((error = device_create_dir(&dev->dir,parent)))
                return error;
index 7df47ce2f4d3ddb7c74c9289668db91222550adf..49b27f479355707761df2d57e0d3909bda0677e0 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/namei.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/device.h>
+#include <linux/driverfs_fs.h>
 
 #include <asm/uaccess.h>
 
@@ -275,26 +275,18 @@ static int driverfs_rmdir(struct inode *dir, struct dentry *dentry)
 static ssize_t
 driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-       struct device_attribute * entry;
+       struct attribute * attr = file->f_dentry->d_fsdata;
        struct driver_dir_entry * dir;
        unsigned char *page;
        ssize_t retval = 0;
-       struct device * dev;
 
        dir = file->f_dentry->d_parent->d_fsdata;
-       entry = to_dev_attr(file->f_dentry->d_fsdata);
-       if (!entry) {
-               DBG("%s: file entry is NULL\n",__FUNCTION__);
-               return -ENOENT;
-       }
-       if (!entry->show)
+       if (!dir->ops->show)
                return 0;
 
        if (count > PAGE_SIZE)
                count = PAGE_SIZE;
 
-       dev = to_device(dir);
-
        page = (unsigned char*)__get_free_page(GFP_KERNEL);
        if (!page)
                return -ENOMEM;
@@ -302,7 +294,7 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
        while (count > 0) {
                ssize_t len;
 
-               len = entry->show(dev,page,count,*ppos);
+               len = dir->ops->show(dir,attr,page,count,*ppos);
 
                if (len <= 0) {
                        if (len < 0)
@@ -341,24 +333,13 @@ driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
 static ssize_t
 driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-       struct device_attribute * entry;
+       struct attribute * attr = file->f_dentry->d_fsdata;
        struct driver_dir_entry * dir;
-       struct device * dev;
        ssize_t retval = 0;
        char * page;
 
        dir = file->f_dentry->d_parent->d_fsdata;
 
-       entry = to_dev_attr(file->f_dentry->d_fsdata);
-       if (!entry) {
-               DBG("%s: file entry is NULL\n",__FUNCTION__);
-               return -ENOENT;
-       }
-       if (!entry->store)
-               return 0;
-
-       dev = to_device(dir);
-
        page = (char *)__get_free_page(GFP_KERNEL);
        if (!page)
                return -ENOMEM;
@@ -372,7 +353,7 @@ driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *pp
        while (count > 0) {
                ssize_t len;
 
-               len = entry->store(dev,page + retval,count,*ppos);
+               len = dir->ops->store(dir,attr,page + retval,count,*ppos);
 
                if (len <= 0) {
                        if (len < 0)
@@ -418,24 +399,28 @@ driverfs_file_lseek(struct file *file, loff_t offset, int orig)
 static int driverfs_open_file(struct inode * inode, struct file * filp)
 {
        struct driver_dir_entry * dir;
-       struct device * dev;
+       int error = 0;
 
        dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
-       if (!dir)
-               return -EFAULT;
-       dev = to_device(dir);
-       get_device(dev);
-       return 0;
+       if (dir) {
+               struct attribute * attr = filp->f_dentry->d_fsdata;
+               if (attr && dir->ops) {
+                       if (dir->ops->open)
+                               error = dir->ops->open(dir);
+                       goto Done;
+               }
+       }
+       error = -EINVAL;
+ Done:
+       return error;
 }
 
 static int driverfs_release(struct inode * inode, struct file * filp)
 {
        struct driver_dir_entry * dir;
-       struct device * dev;
-
        dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
-       dev = to_device(dir);
-       put_device(dev);
+       if (dir->ops->close)
+               dir->ops->close(dir);
        return 0;
 }
 
index 670be49d17188673b0b718dbac4cde35f1656e0a..5dfa05c2dd3a5bbd4034a1a37863649d2ded1990 100644 (file)
@@ -160,8 +160,6 @@ struct device {
        void    (*release)(struct device * dev);
 };
 
-#define to_device(d) container_of(d, struct device, dir)
-
 static inline struct device *
 list_to_dev(struct list_head *node)
 {
@@ -179,6 +177,22 @@ g_list_to_dev(struct list_head *g_list)
  */
 extern int device_register(struct device * dev);
 
+
+/* driverfs interface for exporting device attributes */
+
+struct device_attribute {
+       struct attribute        attr;
+       ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+       ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+#define DEVICE_ATTR(_name,_str,_mode,_show,_store)     \
+struct device_attribute dev_attr_##_name = {           \
+       .attr = {.name  = _str, .mode   = _mode },      \
+       .show   = _show,                                \
+       .store  = _store,                               \
+};
+
 extern int device_create_file(struct device *device, struct device_attribute * entry);
 extern void device_remove_file(struct device * dev, struct device_attribute * attr);
 
index d00ee61fce0727654b225fce4f02f4011589d51c..d859f8c2e041b43f38020fdf971c8c9b619abe8f 100644 (file)
 #ifndef _DRIVER_FS_H_
 #define _DRIVER_FS_H_
 
+struct driver_dir_entry;
+struct attribute;
+
+struct driverfs_ops {
+       int     (*open)(struct driver_dir_entry *);
+       int     (*close)(struct driver_dir_entry *);
+       ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+       ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
 struct driver_dir_entry {
        char                    * name;
        struct dentry           * dentry;
        mode_t                  mode;
+       struct driverfs_ops     * ops;
 };
 
 struct attribute {
@@ -37,23 +48,6 @@ struct attribute {
        mode_t                  mode;
 };
 
-struct device;
-
-struct device_attribute {
-       struct attribute        attr;
-       ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
-       ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
-};
-
-#define DEVICE_ATTR(_name,_str,_mode,_show,_store)     \
-struct device_attribute dev_attr_##_name = {           \
-       .attr = {.name  = _str, .mode   = _mode },      \
-       .show   = _show,                                \
-       .store  = _store,                               \
-};
-
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
-
 extern int
 driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);