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.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 4ad3721a991c..dfe928a9540f 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -102,6 +102,22 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
102 return battr->read(of->file, kobj, battr, buf, pos, count); 102 return battr->read(of->file, kobj, battr, buf, pos, count);
103} 103}
104 104
105/* kernfs read callback for regular sysfs files with pre-alloc */
106static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf,
107 size_t count, loff_t pos)
108{
109 const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
110 struct kobject *kobj = of->kn->parent->priv;
111
112 /*
113 * If buf != of->prealloc_buf, we don't know how
114 * large it is, so cannot safely pass it to ->show
115 */
116 if (pos || WARN_ON_ONCE(buf != of->prealloc_buf))
117 return 0;
118 return ops->show(kobj, of->kn->priv, buf);
119}
120
105/* kernfs write callback for regular sysfs files */ 121/* kernfs write callback for regular sysfs files */
106static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf, 122static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
107 size_t count, loff_t pos) 123 size_t count, loff_t pos)
@@ -184,13 +200,18 @@ static const struct kernfs_ops sysfs_file_kfops_rw = {
184 .write = sysfs_kf_write, 200 .write = sysfs_kf_write,
185}; 201};
186 202
203static const struct kernfs_ops sysfs_prealloc_kfops_ro = {
204 .read = sysfs_kf_read,
205 .prealloc = true,
206};
207
187static const struct kernfs_ops sysfs_prealloc_kfops_wo = { 208static const struct kernfs_ops sysfs_prealloc_kfops_wo = {
188 .write = sysfs_kf_write, 209 .write = sysfs_kf_write,
189 .prealloc = true, 210 .prealloc = true,
190}; 211};
191 212
192static const struct kernfs_ops sysfs_prealloc_kfops_rw = { 213static const struct kernfs_ops sysfs_prealloc_kfops_rw = {
193 .seq_show = sysfs_kf_seq_show, 214 .read = sysfs_kf_read,
194 .write = sysfs_kf_write, 215 .write = sysfs_kf_write,
195 .prealloc = true, 216 .prealloc = true,
196}; 217};
@@ -238,9 +259,12 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
238 ops = &sysfs_prealloc_kfops_rw; 259 ops = &sysfs_prealloc_kfops_rw;
239 else 260 else
240 ops = &sysfs_file_kfops_rw; 261 ops = &sysfs_file_kfops_rw;
241 } else if (sysfs_ops->show) 262 } else if (sysfs_ops->show) {
242 ops = &sysfs_file_kfops_ro; 263 if (mode & SYSFS_PREALLOC)
243 else if (sysfs_ops->store) { 264 ops = &sysfs_prealloc_kfops_ro;
265 else
266 ops = &sysfs_file_kfops_ro;
267 } else if (sysfs_ops->store) {
244 if (mode & SYSFS_PREALLOC) 268 if (mode & SYSFS_PREALLOC)
245 ops = &sysfs_prealloc_kfops_wo; 269 ops = &sysfs_prealloc_kfops_wo;
246 else 270 else