aboutsummaryrefslogtreecommitdiff
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 27d1785b764..a271c87c447 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -20,43 +20,6 @@
#include "sysfs.h"
-#define to_sattr(a) container_of(a,struct subsys_attribute, attr)
-
-/*
- * Subsystem file operations.
- * These operations allow subsystems to have files that can be
- * read/written.
- */
-static ssize_t
-subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
-{
- struct kset *kset = to_kset(kobj);
- struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = -EIO;
-
- if (sattr->show)
- ret = sattr->show(kset, page);
- return ret;
-}
-
-static ssize_t
-subsys_attr_store(struct kobject * kobj, struct attribute * attr,
- const char * page, size_t count)
-{
- struct kset *kset = to_kset(kobj);
- struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = -EIO;
-
- if (sattr->store)
- ret = sattr->store(kset, page, count);
- return ret;
-}
-
-static struct sysfs_ops subsys_sysfs_ops = {
- .show = subsys_attr_show,
- .store = subsys_attr_store,
-};
-
/*
* There's one sysfs_buffer for each open file and one
* sysfs_open_dirent for each sysfs_dirent with one or more open
@@ -66,7 +29,7 @@ static struct sysfs_ops subsys_sysfs_ops = {
* sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open
* is protected by sysfs_open_dirent_lock.
*/
-static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(sysfs_open_dirent_lock);
struct sysfs_open_dirent {
atomic_t refcnt;
@@ -119,7 +82,11 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
sysfs_put_active_two(attr_sd);
- BUG_ON(count > (ssize_t)PAGE_SIZE);
+ /*
+ * The code works fine with PAGE_SIZE return but it's likely to
+ * indicate truncated result or overflow in normal use cases.
+ */
+ BUG_ON(count >= (ssize_t)PAGE_SIZE);
if (count >= 0) {
buffer->needs_read_fill = 0;
buffer->count = count;
@@ -350,31 +317,23 @@ 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 sysfs_buffer * buffer;
- struct sysfs_ops * ops = NULL;
- int error;
+ struct sysfs_buffer *buffer;
+ struct sysfs_ops *ops;
+ int error = -EACCES;
/* need attr_sd for attr and ops, its parent for kobj */
if (!sysfs_get_active_two(attr_sd))
return -ENODEV;
- /* if the kobject has no ktype, then we assume that it is a subsystem
- * itself, and use ops for it.
- */
- if (kobj->kset && kobj->kset->ktype)
- ops = kobj->kset->ktype->sysfs_ops;
- else if (kobj->ktype)
+ /* every kobject with an attribute needs a ktype assigned */
+ if (kobj->ktype && kobj->ktype->sysfs_ops)
ops = kobj->ktype->sysfs_ops;
- else
- ops = &subsys_sysfs_ops;
-
- error = -EACCES;
-
- /* No sysfs operations, either from having no subsystem,
- * or the subsystem have no operations.
- */
- if (!ops)
+ else {
+ printk(KERN_ERR "missing sysfs attribute operations for "
+ "kobject: %s\n", kobject_name(kobj));
+ WARN_ON(1);
goto err_out;
+ }
/* File needs write support.
* The inode's perms must say it's ok,
@@ -564,7 +523,11 @@ int sysfs_add_file_to_group(struct kobject *kobj,
struct sysfs_dirent *dir_sd;
int error;
- dir_sd = sysfs_get_dirent(kobj->sd, group);
+ if (group)
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
+ else
+ dir_sd = sysfs_get(kobj->sd);
+
if (!dir_sd)
return -ENOENT;
@@ -652,7 +615,10 @@ void sysfs_remove_file_from_group(struct kobject *kobj,
{
struct sysfs_dirent *dir_sd;
- dir_sd = sysfs_get_dirent(kobj->sd, group);
+ if (group)
+ dir_sd = sysfs_get_dirent(kobj->sd, group);
+ else
+ dir_sd = sysfs_get(kobj->sd);
if (dir_sd) {
sysfs_hash_and_remove(dir_sd, attr->name);
sysfs_put(dir_sd);