aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r--fs/sysfs/file.c82
1 files changed, 38 insertions, 44 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d2bb7ed8fa74..15ef5eb13663 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -20,7 +20,7 @@
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/mutex.h> 21#include <linux/mutex.h>
22#include <linux/limits.h> 22#include <linux/limits.h>
23#include <asm/uaccess.h> 23#include <linux/uaccess.h>
24 24
25#include "sysfs.h" 25#include "sysfs.h"
26 26
@@ -45,8 +45,8 @@ struct sysfs_open_dirent {
45struct sysfs_buffer { 45struct sysfs_buffer {
46 size_t count; 46 size_t count;
47 loff_t pos; 47 loff_t pos;
48 char * page; 48 char *page;
49 const struct sysfs_ops * ops; 49 const struct sysfs_ops *ops;
50 struct mutex mutex; 50 struct mutex mutex;
51 int needs_read_fill; 51 int needs_read_fill;
52 int event; 52 int event;
@@ -59,16 +59,16 @@ struct sysfs_buffer {
59 * @buffer: data buffer for file. 59 * @buffer: data buffer for file.
60 * 60 *
61 * Allocate @buffer->page, if it hasn't been already, then call the 61 * Allocate @buffer->page, if it hasn't been already, then call the
62 * kobject's show() method to fill the buffer with this attribute's 62 * kobject's show() method to fill the buffer with this attribute's
63 * data. 63 * data.
64 * This is called only once, on the file's first read unless an error 64 * This is called only once, on the file's first read unless an error
65 * is returned. 65 * is returned.
66 */ 66 */
67static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) 67static int fill_read_buffer(struct dentry *dentry, struct sysfs_buffer *buffer)
68{ 68{
69 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 69 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
70 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 70 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
71 const struct sysfs_ops * ops = buffer->ops; 71 const struct sysfs_ops *ops = buffer->ops;
72 int ret = 0; 72 int ret = 0;
73 ssize_t count; 73 ssize_t count;
74 74
@@ -106,7 +106,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
106} 106}
107 107
108/** 108/**
109 * sysfs_read_file - read an attribute. 109 * sysfs_read_file - read an attribute.
110 * @file: file pointer. 110 * @file: file pointer.
111 * @buf: buffer to fill. 111 * @buf: buffer to fill.
112 * @count: number of bytes to read. 112 * @count: number of bytes to read.
@@ -127,12 +127,12 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
127static ssize_t 127static ssize_t
128sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) 128sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
129{ 129{
130 struct sysfs_buffer * buffer = file->private_data; 130 struct sysfs_buffer *buffer = file->private_data;
131 ssize_t retval = 0; 131 ssize_t retval = 0;
132 132
133 mutex_lock(&buffer->mutex); 133 mutex_lock(&buffer->mutex);
134 if (buffer->needs_read_fill || *ppos == 0) { 134 if (buffer->needs_read_fill || *ppos == 0) {
135 retval = fill_read_buffer(file->f_path.dentry,buffer); 135 retval = fill_read_buffer(file->f_path.dentry, buffer);
136 if (retval) 136 if (retval)
137 goto out; 137 goto out;
138 } 138 }
@@ -154,9 +154,8 @@ out:
154 * Allocate @buffer->page if it hasn't been already, then 154 * Allocate @buffer->page if it hasn't been already, then
155 * copy the user-supplied buffer into it. 155 * copy the user-supplied buffer into it.
156 */ 156 */
157 157static int fill_write_buffer(struct sysfs_buffer *buffer,
158static int 158 const char __user *buf, size_t count)
159fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t count)
160{ 159{
161 int error; 160 int error;
162 161
@@ -167,7 +166,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
167 166
168 if (count >= PAGE_SIZE) 167 if (count >= PAGE_SIZE)
169 count = PAGE_SIZE - 1; 168 count = PAGE_SIZE - 1;
170 error = copy_from_user(buffer->page,buf,count); 169 error = copy_from_user(buffer->page, buf, count);
171 buffer->needs_read_fill = 1; 170 buffer->needs_read_fill = 1;
172 /* if buf is assumed to contain a string, terminate it by \0, 171 /* if buf is assumed to contain a string, terminate it by \0,
173 so e.g. sscanf() can scan the string easily */ 172 so e.g. sscanf() can scan the string easily */
@@ -183,16 +182,15 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
183 * @count: number of bytes 182 * @count: number of bytes
184 * 183 *
185 * Get the correct pointers for the kobject and the attribute we're 184 * Get the correct pointers for the kobject and the attribute we're
186 * dealing with, then call the store() method for the attribute, 185 * dealing with, then call the store() method for the attribute,
187 * passing the buffer that we acquired in fill_write_buffer(). 186 * passing the buffer that we acquired in fill_write_buffer().
188 */ 187 */
189 188static int flush_write_buffer(struct dentry *dentry,
190static int 189 struct sysfs_buffer *buffer, size_t count)
191flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
192{ 190{
193 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 191 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
194 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 192 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
195 const struct sysfs_ops * ops = buffer->ops; 193 const struct sysfs_ops *ops = buffer->ops;
196 int rc; 194 int rc;
197 195
198 /* need attr_sd for attr and ops, its parent for kobj */ 196 /* need attr_sd for attr and ops, its parent for kobj */
@@ -219,15 +217,14 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
219 * then push it to the kobject in flush_write_buffer(). 217 * then push it to the kobject in flush_write_buffer().
220 * There is no easy way for us to know if userspace is only doing a partial 218 * There is no easy way for us to know if userspace is only doing a partial
221 * write, so we don't support them. We expect the entire buffer to come 219 * write, so we don't support them. We expect the entire buffer to come
222 * on the first write. 220 * on the first write.
223 * Hint: if you're writing a value, first read the file, modify only the 221 * Hint: if you're writing a value, first read the file, modify only the
224 * the value you're changing, then write entire buffer back. 222 * the value you're changing, then write entire buffer back.
225 */ 223 */
226 224static ssize_t sysfs_write_file(struct file *file, const char __user *buf,
227static ssize_t 225 size_t count, loff_t *ppos)
228sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
229{ 226{
230 struct sysfs_buffer * buffer = file->private_data; 227 struct sysfs_buffer *buffer = file->private_data;
231 ssize_t len; 228 ssize_t len;
232 229
233 mutex_lock(&buffer->mutex); 230 mutex_lock(&buffer->mutex);
@@ -339,13 +336,14 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
339 if (kobj->ktype && kobj->ktype->sysfs_ops) 336 if (kobj->ktype && kobj->ktype->sysfs_ops)
340 ops = kobj->ktype->sysfs_ops; 337 ops = kobj->ktype->sysfs_ops;
341 else { 338 else {
342 WARN(1, KERN_ERR "missing sysfs attribute operations for " 339 WARN(1, KERN_ERR
343 "kobject: %s\n", kobject_name(kobj)); 340 "missing sysfs attribute operations for kobject: %s\n",
341 kobject_name(kobj));
344 goto err_out; 342 goto err_out;
345 } 343 }
346 344
347 /* File needs write support. 345 /* File needs write support.
348 * The inode's perms must say it's ok, 346 * The inode's perms must say it's ok,
349 * and we must have a store method. 347 * and we must have a store method.
350 */ 348 */
351 if (file->f_mode & FMODE_WRITE) { 349 if (file->f_mode & FMODE_WRITE) {
@@ -420,7 +418,7 @@ static int sysfs_release(struct inode *inode, struct file *filp)
420 */ 418 */
421static unsigned int sysfs_poll(struct file *filp, poll_table *wait) 419static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
422{ 420{
423 struct sysfs_buffer * buffer = filp->private_data; 421 struct sysfs_buffer *buffer = filp->private_data;
424 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; 422 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
425 struct sysfs_open_dirent *od = attr_sd->s_attr.open; 423 struct sysfs_open_dirent *od = attr_sd->s_attr.open;
426 424
@@ -518,8 +516,9 @@ static int sysfs_attr_ns(struct kobject *kobj, const struct attribute *attr,
518 ns = ops->namespace(kobj, attr); 516 ns = ops->namespace(kobj, attr);
519out: 517out:
520 if (err) { 518 if (err) {
521 WARN(1, KERN_ERR "missing sysfs namespace attribute operation for " 519 WARN(1, KERN_ERR
522 "kobject: %s\n", kobject_name(kobj)); 520 "missing sysfs namespace attribute operation for kobject: %s\n",
521 kobject_name(kobj));
523 } 522 }
524 *pns = ns; 523 *pns = ns;
525 return err; 524 return err;
@@ -566,17 +565,17 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
566 565
567/** 566/**
568 * sysfs_create_file - create an attribute file for an object. 567 * sysfs_create_file - create an attribute file for an object.
569 * @kobj: object we're creating for. 568 * @kobj: object we're creating for.
570 * @attr: attribute descriptor. 569 * @attr: attribute descriptor.
571 */ 570 */
572 571int sysfs_create_file(struct kobject *kobj, const struct attribute *attr)
573int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
574{ 572{
575 BUG_ON(!kobj || !kobj->sd || !attr); 573 BUG_ON(!kobj || !kobj->sd || !attr);
576 574
577 return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR); 575 return sysfs_add_file(kobj->sd, attr, SYSFS_KOBJ_ATTR);
578 576
579} 577}
578EXPORT_SYMBOL_GPL(sysfs_create_file);
580 579
581int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr) 580int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
582{ 581{
@@ -590,6 +589,7 @@ int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
590 sysfs_remove_file(kobj, ptr[i]); 589 sysfs_remove_file(kobj, ptr[i]);
591 return err; 590 return err;
592} 591}
592EXPORT_SYMBOL_GPL(sysfs_create_files);
593 593
594/** 594/**
595 * sysfs_add_file_to_group - add an attribute file to a pre-existing group. 595 * sysfs_add_file_to_group - add an attribute file to a pre-existing group.
@@ -654,7 +654,6 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr,
654} 654}
655EXPORT_SYMBOL_GPL(sysfs_chmod_file); 655EXPORT_SYMBOL_GPL(sysfs_chmod_file);
656 656
657
658/** 657/**
659 * sysfs_remove_file - remove an object attribute. 658 * sysfs_remove_file - remove an object attribute.
660 * @kobj: object we're acting for. 659 * @kobj: object we're acting for.
@@ -662,8 +661,7 @@ EXPORT_SYMBOL_GPL(sysfs_chmod_file);
662 * 661 *
663 * Hash the attribute name and kill the victim. 662 * Hash the attribute name and kill the victim.
664 */ 663 */
665 664void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr)
666void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
667{ 665{
668 const void *ns; 666 const void *ns;
669 667
@@ -672,13 +670,15 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
672 670
673 sysfs_hash_and_remove(kobj->sd, ns, attr->name); 671 sysfs_hash_and_remove(kobj->sd, ns, attr->name);
674} 672}
673EXPORT_SYMBOL_GPL(sysfs_remove_file);
675 674
676void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr) 675void sysfs_remove_files(struct kobject *kobj, const struct attribute **ptr)
677{ 676{
678 int i; 677 int i;
679 for (i = 0; ptr[i]; i++) 678 for (i = 0; ptr[i]; i++)
680 sysfs_remove_file(kobj, ptr[i]); 679 sysfs_remove_file(kobj, ptr[i]);
681} 680}
681EXPORT_SYMBOL_GPL(sysfs_remove_files);
682 682
683/** 683/**
684 * sysfs_remove_file_from_group - remove an attribute file from a group. 684 * sysfs_remove_file_from_group - remove an attribute file from a group.
@@ -793,9 +793,3 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
793 return 0; 793 return 0;
794} 794}
795EXPORT_SYMBOL_GPL(sysfs_schedule_callback); 795EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
796
797
798EXPORT_SYMBOL_GPL(sysfs_create_file);
799EXPORT_SYMBOL_GPL(sysfs_remove_file);
800EXPORT_SYMBOL_GPL(sysfs_remove_files);
801EXPORT_SYMBOL_GPL(sysfs_create_files);