sysfs: remove sysfs_buffer->ops
authorTejun Heo <tj@kernel.org>
Tue, 1 Oct 2013 21:41:57 +0000 (17:41 -0400)
committerMaciej Wereski <m.wereski@partner.samsung.com>
Tue, 9 Jun 2015 09:31:12 +0000 (11:31 +0200)
Currently, sysfs_ops is fetched during sysfs_open_file() and cached in
sysfs_buffer->ops to be used while the file is open.  This patch
removes the caching and makes each operation directly fetch sysfs_ops.

This patch doesn't introduce any behavior difference and is to prepare
for merging regular and bin file supports.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/sysfs/file.c

index e2fafc0..7dfcc33 100644 (file)
@@ -45,12 +45,23 @@ struct sysfs_open_dirent {
 struct sysfs_buffer {
        size_t                  count;
        char                    *page;
-       const struct sysfs_ops  *ops;
        struct mutex            mutex;
        int                     event;
        struct list_head        list;
 };
 
+/*
+ * Determine ktype->sysfs_ops for the given sysfs_dirent.  This function
+ * must be called while holding an active reference.
+ */
+static const struct sysfs_ops *sysfs_file_ops(struct sysfs_dirent *sd)
+{
+       struct kobject *kobj = sd->s_parent->s_dir.kobj;
+
+       lockdep_assert_held(sd);
+       return kobj->ktype ? kobj->ktype->sysfs_ops : NULL;
+}
+
 /**
  *     fill_read_buffer - allocate and fill buffer from object.
  *     @dentry:        dentry pointer.
@@ -66,7 +77,7 @@ 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;
-       const struct sysfs_ops *ops = buffer->ops;
+       const struct sysfs_ops *ops;
        int ret = 0;
        ssize_t count;
 
@@ -80,6 +91,8 @@ static int fill_read_buffer(struct dentry *dentry, struct sysfs_buffer *buffer)
                return -ENODEV;
 
        buffer->event = atomic_read(&attr_sd->s_attr.open->event);
+
+       ops = sysfs_file_ops(attr_sd);
        count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
 
        sysfs_put_active(attr_sd);
@@ -191,13 +204,14 @@ static int flush_write_buffer(struct dentry *dentry,
 {
        struct sysfs_dirent *attr_sd = dentry->d_fsdata;
        struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
-       const struct sysfs_ops *ops = buffer->ops;
+       const struct sysfs_ops *ops;
        int rc;
 
        /* need attr_sd for attr and ops, its parent for kobj */
        if (!sysfs_get_active(attr_sd))
                return -ENODEV;
 
+       ops = sysfs_file_ops(attr_sd);
        rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
 
        sysfs_put_active(attr_sd);
@@ -205,7 +219,6 @@ static int flush_write_buffer(struct dentry *dentry,
        return rc;
 }
 
-
 /**
  *     sysfs_write_file - write an attribute.
  *     @file:  file pointer
@@ -334,14 +347,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
                return -ENODEV;
 
        /* every kobject with an attribute needs a ktype assigned */
-       if (kobj->ktype && kobj->ktype->sysfs_ops)
-               ops = kobj->ktype->sysfs_ops;
-       else {
-               WARN(1, KERN_ERR
-                    "missing sysfs attribute operations for kobject: %s\n",
-                    kobject_name(kobj));
+       ops = sysfs_file_ops(attr_sd);
+       if (WARN(!ops, KERN_ERR
+                "missing sysfs attribute operations for kobject: %s\n",
+                kobject_name(kobj)))
                goto err_out;
-       }
 
        /* File needs write support.
         * The inode's perms must say it's ok,
@@ -370,7 +380,6 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
                goto err_out;
 
        mutex_init(&buffer->mutex);
-       buffer->ops = ops;
        file->private_data = buffer;
 
        /* make sure we have open dirent struct */