summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/sysfs/file.c22
-rw-r--r--include/linux/sysfs.h25
2 files changed, 40 insertions, 7 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 6d39696b4306..785408861c01 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -91,9 +91,12 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
count = size - pos;
}
- if (!battr->read)
+ if (!battr->read && !battr->read_new)
return -EIO;
+ if (battr->read_new)
+ return battr->read_new(of->file, kobj, battr, buf, pos, count);
+
return battr->read(of->file, kobj, battr, buf, pos, count);
}
@@ -152,9 +155,12 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
if (!count)
return 0;
- if (!battr->write)
+ if (!battr->write && !battr->write_new)
return -EIO;
+ if (battr->write_new)
+ return battr->write_new(of->file, kobj, battr, buf, pos, count);
+
return battr->write(of->file, kobj, battr, buf, pos, count);
}
@@ -323,13 +329,19 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct kernfs_ops *ops;
struct kernfs_node *kn;
+ if (battr->read && battr->read_new)
+ return -EINVAL;
+
+ if (battr->write && battr->write_new)
+ return -EINVAL;
+
if (battr->mmap)
ops = &sysfs_bin_kfops_mmap;
- else if (battr->read && battr->write)
+ else if ((battr->read || battr->read_new) && (battr->write || battr->write_new))
ops = &sysfs_bin_kfops_rw;
- else if (battr->read)
+ else if (battr->read || battr->read_new)
ops = &sysfs_bin_kfops_ro;
- else if (battr->write)
+ else if (battr->write || battr->write_new)
ops = &sysfs_bin_kfops_wo;
else
ops = &sysfs_file_kfops_empty;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index d17c473c1ef2..d713a6445a62 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -305,8 +305,12 @@ struct bin_attribute {
struct address_space *(*f_mapping)(void);
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *,
+ char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ ssize_t (*write_new)(struct file *, struct kobject *,
+ const struct bin_attribute *, char *, loff_t, size_t);
loff_t (*llseek)(struct file *, struct kobject *, const struct bin_attribute *,
loff_t, int);
int (*mmap)(struct file *, struct kobject *, const struct bin_attribute *attr,
@@ -325,11 +329,28 @@ struct bin_attribute {
*/
#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
+typedef ssize_t __sysfs_bin_rw_handler_new(struct file *, struct kobject *,
+ const struct bin_attribute *, char *, loff_t, size_t);
+
/* macros to create static binary attributes easier */
#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \
.attr = { .name = __stringify(_name), .mode = _mode }, \
- .read = _read, \
- .write = _write, \
+ .read = _Generic(_read, \
+ __sysfs_bin_rw_handler_new * : NULL, \
+ default : _read \
+ ), \
+ .read_new = _Generic(_read, \
+ __sysfs_bin_rw_handler_new * : _read, \
+ default : NULL \
+ ), \
+ .write = _Generic(_write, \
+ __sysfs_bin_rw_handler_new * : NULL, \
+ default : _write \
+ ), \
+ .write_new = _Generic(_write, \
+ __sysfs_bin_rw_handler_new * : _write, \
+ default : NULL \
+ ), \
.size = _size, \
}