aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:10:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-14 19:10:09 -0500
commite6b5be2be4e30037eb551e0ed09dd97bd00d85d3 (patch)
tree88801365987a0dc64d62d47e8a11f3b44691c37f /fs/kernfs
parent37da7bbbe84fe9e8862940d3f9194fd27dce59bb (diff)
parentf1c488a78d9f1a22cdb15648c15e70fd82ed229a (diff)
Merge tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core update from Greg KH: "Here's the set of driver core patches for 3.19-rc1. They are dominated by the removal of the .owner field in platform drivers. They touch a lot of files, but they are "simple" changes, just removing a line in a structure. Other than that, a few minor driver core and debugfs changes. There are some ath9k patches coming in through this tree that have been acked by the wireless maintainers as they relied on the debugfs changes. Everything has been in linux-next for a while" * tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (324 commits) Revert "ath: ath9k: use debugfs_create_devm_seqfile() helper for seq_file entries" fs: debugfs: add forward declaration for struct device type firmware class: Deletion of an unnecessary check before the function call "vunmap" firmware loader: fix hung task warning dump devcoredump: provide a one-way disable function device: Add dev_<level>_once variants ath: ath9k: use debugfs_create_devm_seqfile() helper for seq_file entries ath: use seq_file api for ath9k debugfs files debugfs: add helper function to create device related seq_file drivers/base: cacheinfo: remove noisy error boot message Revert "core: platform: add warning if driver has no owner" drivers: base: support cpu cache information interface to userspace via sysfs drivers: base: add cpu_device_create to support per-cpu devices topology: replace custom attribute macros with standard DEVICE_ATTR* cpumask: factor out show_cpumap into separate helper function driver core: Fix unbalanced device reference in drivers_probe driver core: fix race with userland in device_add() sysfs/kernfs: make read requests on pre-alloc files use the buffer. sysfs/kernfs: allow attributes to request write buffer be pre-allocated. fs: sysfs: return EGBIG on write if offset is larger than file size ...
Diffstat (limited to 'fs/kernfs')
-rw-r--r--fs/kernfs/file.c73
1 files changed, 50 insertions, 23 deletions
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 4429d6d9217f..697390ea47b8 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -106,7 +106,7 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
106 const struct kernfs_ops *ops; 106 const struct kernfs_ops *ops;
107 107
108 /* 108 /*
109 * @of->mutex nests outside active ref and is just to ensure that 109 * @of->mutex nests outside active ref and is primarily to ensure that
110 * the ops aren't called concurrently for the same open file. 110 * the ops aren't called concurrently for the same open file.
111 */ 111 */
112 mutex_lock(&of->mutex); 112 mutex_lock(&of->mutex);
@@ -189,13 +189,16 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
189 const struct kernfs_ops *ops; 189 const struct kernfs_ops *ops;
190 char *buf; 190 char *buf;
191 191
192 buf = kmalloc(len, GFP_KERNEL); 192 buf = of->prealloc_buf;
193 if (!buf)
194 buf = kmalloc(len, GFP_KERNEL);
193 if (!buf) 195 if (!buf)
194 return -ENOMEM; 196 return -ENOMEM;
195 197
196 /* 198 /*
197 * @of->mutex nests outside active ref and is just to ensure that 199 * @of->mutex nests outside active ref and is used both to ensure that
198 * the ops aren't called concurrently for the same open file. 200 * the ops aren't called concurrently for the same open file, and
201 * to provide exclusive access to ->prealloc_buf (when that exists).
199 */ 202 */
200 mutex_lock(&of->mutex); 203 mutex_lock(&of->mutex);
201 if (!kernfs_get_active(of->kn)) { 204 if (!kernfs_get_active(of->kn)) {
@@ -210,21 +213,22 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
210 else 213 else
211 len = -EINVAL; 214 len = -EINVAL;
212 215
213 kernfs_put_active(of->kn);
214 mutex_unlock(&of->mutex);
215
216 if (len < 0) 216 if (len < 0)
217 goto out_free; 217 goto out_unlock;
218 218
219 if (copy_to_user(user_buf, buf, len)) { 219 if (copy_to_user(user_buf, buf, len)) {
220 len = -EFAULT; 220 len = -EFAULT;
221 goto out_free; 221 goto out_unlock;
222 } 222 }
223 223
224 *ppos += len; 224 *ppos += len;
225 225
226 out_unlock:
227 kernfs_put_active(of->kn);
228 mutex_unlock(&of->mutex);
226 out_free: 229 out_free:
227 kfree(buf); 230 if (buf != of->prealloc_buf)
231 kfree(buf);
228 return len; 232 return len;
229} 233}
230 234
@@ -278,19 +282,16 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
278 len = min_t(size_t, count, PAGE_SIZE); 282 len = min_t(size_t, count, PAGE_SIZE);
279 } 283 }
280 284
281 buf = kmalloc(len + 1, GFP_KERNEL); 285 buf = of->prealloc_buf;
286 if (!buf)
287 buf = kmalloc(len + 1, GFP_KERNEL);
282 if (!buf) 288 if (!buf)
283 return -ENOMEM; 289 return -ENOMEM;
284 290
285 if (copy_from_user(buf, user_buf, len)) {
286 len = -EFAULT;
287 goto out_free;
288 }
289 buf[len] = '\0'; /* guarantee string termination */
290
291 /* 291 /*
292 * @of->mutex nests outside active ref and is just to ensure that 292 * @of->mutex nests outside active ref and is used both to ensure that
293 * the ops aren't called concurrently for the same open file. 293 * the ops aren't called concurrently for the same open file, and
294 * to provide exclusive access to ->prealloc_buf (when that exists).
294 */ 295 */
295 mutex_lock(&of->mutex); 296 mutex_lock(&of->mutex);
296 if (!kernfs_get_active(of->kn)) { 297 if (!kernfs_get_active(of->kn)) {
@@ -299,19 +300,27 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
299 goto out_free; 300 goto out_free;
300 } 301 }
301 302
303 if (copy_from_user(buf, user_buf, len)) {
304 len = -EFAULT;
305 goto out_unlock;
306 }
307 buf[len] = '\0'; /* guarantee string termination */
308
302 ops = kernfs_ops(of->kn); 309 ops = kernfs_ops(of->kn);
303 if (ops->write) 310 if (ops->write)
304 len = ops->write(of, buf, len, *ppos); 311 len = ops->write(of, buf, len, *ppos);
305 else 312 else
306 len = -EINVAL; 313 len = -EINVAL;
307 314
308 kernfs_put_active(of->kn);
309 mutex_unlock(&of->mutex);
310
311 if (len > 0) 315 if (len > 0)
312 *ppos += len; 316 *ppos += len;
317
318out_unlock:
319 kernfs_put_active(of->kn);
320 mutex_unlock(&of->mutex);
313out_free: 321out_free:
314 kfree(buf); 322 if (buf != of->prealloc_buf)
323 kfree(buf);
315 return len; 324 return len;
316} 325}
317 326
@@ -685,6 +694,22 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
685 */ 694 */
686 of->atomic_write_len = ops->atomic_write_len; 695 of->atomic_write_len = ops->atomic_write_len;
687 696
697 error = -EINVAL;
698 /*
699 * ->seq_show is incompatible with ->prealloc,
700 * as seq_read does its own allocation.
701 * ->read must be used instead.
702 */
703 if (ops->prealloc && ops->seq_show)
704 goto err_free;
705 if (ops->prealloc) {
706 int len = of->atomic_write_len ?: PAGE_SIZE;
707 of->prealloc_buf = kmalloc(len + 1, GFP_KERNEL);
708 error = -ENOMEM;
709 if (!of->prealloc_buf)
710 goto err_free;
711 }
712
688 /* 713 /*
689 * Always instantiate seq_file even if read access doesn't use 714 * Always instantiate seq_file even if read access doesn't use
690 * seq_file or is not requested. This unifies private data access 715 * seq_file or is not requested. This unifies private data access
@@ -715,6 +740,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
715err_close: 740err_close:
716 seq_release(inode, file); 741 seq_release(inode, file);
717err_free: 742err_free:
743 kfree(of->prealloc_buf);
718 kfree(of); 744 kfree(of);
719err_out: 745err_out:
720 kernfs_put_active(kn); 746 kernfs_put_active(kn);
@@ -728,6 +754,7 @@ static int kernfs_fop_release(struct inode *inode, struct file *filp)
728 754
729 kernfs_put_open_node(kn, of); 755 kernfs_put_open_node(kn, of);
730 seq_release(inode, filp); 756 seq_release(inode, filp);
757 kfree(of->prealloc_buf);
731 kfree(of); 758 kfree(of);
732 759
733 return 0; 760 return 0;