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.c84
1 files changed, 25 insertions, 59 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 27d1785b7644..a271c87c4472 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -20,43 +20,6 @@
20 20
21#include "sysfs.h" 21#include "sysfs.h"
22 22
23#define to_sattr(a) container_of(a,struct subsys_attribute, attr)
24
25/*
26 * Subsystem file operations.
27 * These operations allow subsystems to have files that can be
28 * read/written.
29 */
30static ssize_t
31subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
32{
33 struct kset *kset = to_kset(kobj);
34 struct subsys_attribute * sattr = to_sattr(attr);
35 ssize_t ret = -EIO;
36
37 if (sattr->show)
38 ret = sattr->show(kset, page);
39 return ret;
40}
41
42static ssize_t
43subsys_attr_store(struct kobject * kobj, struct attribute * attr,
44 const char * page, size_t count)
45{
46 struct kset *kset = to_kset(kobj);
47 struct subsys_attribute * sattr = to_sattr(attr);
48 ssize_t ret = -EIO;
49
50 if (sattr->store)
51 ret = sattr->store(kset, page, count);
52 return ret;
53}
54
55static struct sysfs_ops subsys_sysfs_ops = {
56 .show = subsys_attr_show,
57 .store = subsys_attr_store,
58};
59
60/* 23/*
61 * There's one sysfs_buffer for each open file and one 24 * There's one sysfs_buffer for each open file and one
62 * sysfs_open_dirent for each sysfs_dirent with one or more open 25 * sysfs_open_dirent for each sysfs_dirent with one or more open
@@ -66,7 +29,7 @@ static struct sysfs_ops subsys_sysfs_ops = {
66 * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open 29 * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open
67 * is protected by sysfs_open_dirent_lock. 30 * is protected by sysfs_open_dirent_lock.
68 */ 31 */
69static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED; 32static DEFINE_SPINLOCK(sysfs_open_dirent_lock);
70 33
71struct sysfs_open_dirent { 34struct sysfs_open_dirent {
72 atomic_t refcnt; 35 atomic_t refcnt;
@@ -119,7 +82,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
119 82
120 sysfs_put_active_two(attr_sd); 83 sysfs_put_active_two(attr_sd);
121 84
122 BUG_ON(count > (ssize_t)PAGE_SIZE); 85 /*
86 * The code works fine with PAGE_SIZE return but it's likely to
87 * indicate truncated result or overflow in normal use cases.
88 */
89 BUG_ON(count >= (ssize_t)PAGE_SIZE);
123 if (count >= 0) { 90 if (count >= 0) {
124 buffer->needs_read_fill = 0; 91 buffer->needs_read_fill = 0;
125 buffer->count = count; 92 buffer->count = count;
@@ -350,31 +317,23 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
350{ 317{
351 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 318 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
352 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; 319 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
353 struct sysfs_buffer * buffer; 320 struct sysfs_buffer *buffer;
354 struct sysfs_ops * ops = NULL; 321 struct sysfs_ops *ops;
355 int error; 322 int error = -EACCES;
356 323
357 /* need attr_sd for attr and ops, its parent for kobj */ 324 /* need attr_sd for attr and ops, its parent for kobj */
358 if (!sysfs_get_active_two(attr_sd)) 325 if (!sysfs_get_active_two(attr_sd))
359 return -ENODEV; 326 return -ENODEV;
360 327
361 /* if the kobject has no ktype, then we assume that it is a subsystem 328 /* every kobject with an attribute needs a ktype assigned */
362 * itself, and use ops for it. 329 if (kobj->ktype && kobj->ktype->sysfs_ops)
363 */
364 if (kobj->kset && kobj->kset->ktype)
365 ops = kobj->kset->ktype->sysfs_ops;
366 else if (kobj->ktype)
367 ops = kobj->ktype->sysfs_ops; 330 ops = kobj->ktype->sysfs_ops;
368 else 331 else {
369 ops = &subsys_sysfs_ops; 332 printk(KERN_ERR "missing sysfs attribute operations for "
370 333 "kobject: %s\n", kobject_name(kobj));
371 error = -EACCES; 334 WARN_ON(1);
372
373 /* No sysfs operations, either from having no subsystem,
374 * or the subsystem have no operations.
375 */
376 if (!ops)
377 goto err_out; 335 goto err_out;
336 }
378 337
379 /* File needs write support. 338 /* File needs write support.
380 * The inode's perms must say it's ok, 339 * The inode's perms must say it's ok,
@@ -564,7 +523,11 @@ int sysfs_add_file_to_group(struct kobject *kobj,
564 struct sysfs_dirent *dir_sd; 523 struct sysfs_dirent *dir_sd;
565 int error; 524 int error;
566 525
567 dir_sd = sysfs_get_dirent(kobj->sd, group); 526 if (group)
527 dir_sd = sysfs_get_dirent(kobj->sd, group);
528 else
529 dir_sd = sysfs_get(kobj->sd);
530
568 if (!dir_sd) 531 if (!dir_sd)
569 return -ENOENT; 532 return -ENOENT;
570 533
@@ -652,7 +615,10 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
652{ 615{
653 struct sysfs_dirent *dir_sd; 616 struct sysfs_dirent *dir_sd;
654 617
655 dir_sd = sysfs_get_dirent(kobj->sd, group); 618 if (group)
619 dir_sd = sysfs_get_dirent(kobj->sd, group);
620 else
621 dir_sd = sysfs_get(kobj->sd);
656 if (dir_sd) { 622 if (dir_sd) {
657 sysfs_hash_and_remove(dir_sd, attr->name); 623 sysfs_hash_and_remove(dir_sd, attr->name);
658 sysfs_put(dir_sd); 624 sysfs_put(dir_sd);