diff options
Diffstat (limited to 'fs/sysfs/file.c')
-rw-r--r-- | fs/sysfs/file.c | 32 |
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 */ | ||
106 | static 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 */ |
106 | static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf, | 122 | static 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 | ||
203 | static const struct kernfs_ops sysfs_prealloc_kfops_ro = { | ||
204 | .read = sysfs_kf_read, | ||
205 | .prealloc = true, | ||
206 | }; | ||
207 | |||
187 | static const struct kernfs_ops sysfs_prealloc_kfops_wo = { | 208 | static 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 | ||
192 | static const struct kernfs_ops sysfs_prealloc_kfops_rw = { | 213 | static 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 |