diff options
author | Tejun Heo <tj@kernel.org> | 2013-10-01 17:42:06 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-05 20:27:40 -0400 |
commit | 2f0c6b7593a590eef7fa35344da57380fcee7581 (patch) | |
tree | b729d523dbb3fcdade4a6ce3a72027230a6b3fbb /fs | |
parent | f9b9a6217cf10fd5d3002627cc13c4789a777213 (diff) |
sysfs: add sysfs_bin_read()
sysfs bin file handling will be merged into the regular file support.
This patch prepares the read path.
Copy fs/sysfs/bin.c::read() to fs/sysfs/file.c and make it use
sysfs_open_file instead of bin_buffer. The function is identical copy
except for the use of sysfs_open_file.
The new function is added to sysfs_bin_operations. This isn't used
yet but will eventually replace fs/sysfs/bin.c.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/sysfs/file.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index b36473f21824..9ba492a3d932 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -139,6 +139,70 @@ static int sysfs_seq_show(struct seq_file *sf, void *v) | |||
139 | return 0; | 139 | return 0; |
140 | } | 140 | } |
141 | 141 | ||
142 | /* | ||
143 | * Read method for bin files. As reading a bin file can have side-effects, | ||
144 | * the exact offset and bytes specified in read(2) call should be passed to | ||
145 | * the read callback making it difficult to use seq_file. Implement | ||
146 | * simplistic custom buffering for bin files. | ||
147 | */ | ||
148 | static ssize_t sysfs_bin_read(struct file *file, char __user *userbuf, | ||
149 | size_t bytes, loff_t *off) | ||
150 | { | ||
151 | struct sysfs_open_file *of = sysfs_of(file); | ||
152 | struct bin_attribute *battr = of->sd->s_bin_attr.bin_attr; | ||
153 | struct kobject *kobj = of->sd->s_parent->s_dir.kobj; | ||
154 | int size = file_inode(file)->i_size; | ||
155 | int count = min_t(size_t, bytes, PAGE_SIZE); | ||
156 | loff_t offs = *off; | ||
157 | char *buf; | ||
158 | |||
159 | if (!bytes) | ||
160 | return 0; | ||
161 | |||
162 | if (size) { | ||
163 | if (offs > size) | ||
164 | return 0; | ||
165 | if (offs + count > size) | ||
166 | count = size - offs; | ||
167 | } | ||
168 | |||
169 | buf = kmalloc(count, GFP_KERNEL); | ||
170 | if (!buf) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | /* need of->sd for battr, its parent for kobj */ | ||
174 | mutex_lock(&of->mutex); | ||
175 | if (!sysfs_get_active(of->sd)) { | ||
176 | count = -ENODEV; | ||
177 | mutex_unlock(&of->mutex); | ||
178 | goto out_free; | ||
179 | } | ||
180 | |||
181 | if (battr->read) | ||
182 | count = battr->read(file, kobj, battr, buf, offs, count); | ||
183 | else | ||
184 | count = -EIO; | ||
185 | |||
186 | sysfs_put_active(of->sd); | ||
187 | mutex_unlock(&of->mutex); | ||
188 | |||
189 | if (count < 0) | ||
190 | goto out_free; | ||
191 | |||
192 | if (copy_to_user(userbuf, buf, count)) { | ||
193 | count = -EFAULT; | ||
194 | goto out_free; | ||
195 | } | ||
196 | |||
197 | pr_debug("offs = %lld, *off = %lld, count = %d\n", offs, *off, count); | ||
198 | |||
199 | *off = offs + count; | ||
200 | |||
201 | out_free: | ||
202 | kfree(buf); | ||
203 | return count; | ||
204 | } | ||
205 | |||
142 | /** | 206 | /** |
143 | * flush_write_buffer - push buffer to kobject | 207 | * flush_write_buffer - push buffer to kobject |
144 | * @of: open file | 208 | * @of: open file |
@@ -495,6 +559,7 @@ const struct file_operations sysfs_file_operations = { | |||
495 | }; | 559 | }; |
496 | 560 | ||
497 | const struct file_operations sysfs_bin_operations = { | 561 | const struct file_operations sysfs_bin_operations = { |
562 | .read = sysfs_bin_read, | ||
498 | .write = sysfs_write_file, | 563 | .write = sysfs_write_file, |
499 | .llseek = generic_file_llseek, | 564 | .llseek = generic_file_llseek, |
500 | }; | 565 | }; |