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.c248
1 files changed, 170 insertions, 78 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 3e1cc062a740..d3be1e7fb48b 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -1,15 +1,22 @@
1/* 1/*
2 * file.c - operations for regular (text) files. 2 * fs/sysfs/file.c - sysfs regular (text) file implementation
3 *
4 * Copyright (c) 2001-3 Patrick Mochel
5 * Copyright (c) 2007 SUSE Linux Products GmbH
6 * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
7 *
8 * This file is released under the GPLv2.
9 *
10 * Please see Documentation/filesystems/sysfs.txt for more information.
3 */ 11 */
4 12
5#include <linux/module.h> 13#include <linux/module.h>
6#include <linux/fsnotify.h>
7#include <linux/kobject.h> 14#include <linux/kobject.h>
8#include <linux/namei.h> 15#include <linux/namei.h>
9#include <linux/poll.h> 16#include <linux/poll.h>
10#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/mutex.h>
11#include <asm/uaccess.h> 19#include <asm/uaccess.h>
12#include <asm/semaphore.h>
13 20
14#include "sysfs.h" 21#include "sysfs.h"
15 22
@@ -50,14 +57,33 @@ static struct sysfs_ops subsys_sysfs_ops = {
50 .store = subsys_attr_store, 57 .store = subsys_attr_store,
51}; 58};
52 59
60/*
61 * There's one sysfs_buffer for each open file and one
62 * sysfs_open_dirent for each sysfs_dirent with one or more open
63 * files.
64 *
65 * filp->private_data points to sysfs_buffer and
66 * sysfs_dirent->s_attr.open points to sysfs_open_dirent. s_attr.open
67 * is protected by sysfs_open_dirent_lock.
68 */
69static spinlock_t sysfs_open_dirent_lock = SPIN_LOCK_UNLOCKED;
70
71struct sysfs_open_dirent {
72 atomic_t refcnt;
73 atomic_t event;
74 wait_queue_head_t poll;
75 struct list_head buffers; /* goes through sysfs_buffer.list */
76};
77
53struct sysfs_buffer { 78struct sysfs_buffer {
54 size_t count; 79 size_t count;
55 loff_t pos; 80 loff_t pos;
56 char * page; 81 char * page;
57 struct sysfs_ops * ops; 82 struct sysfs_ops * ops;
58 struct semaphore sem; 83 struct mutex mutex;
59 int needs_read_fill; 84 int needs_read_fill;
60 int event; 85 int event;
86 struct list_head list;
61}; 87};
62 88
63/** 89/**
@@ -74,7 +100,7 @@ struct sysfs_buffer {
74static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer) 100static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer)
75{ 101{
76 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 102 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
77 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; 103 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
78 struct sysfs_ops * ops = buffer->ops; 104 struct sysfs_ops * ops = buffer->ops;
79 int ret = 0; 105 int ret = 0;
80 ssize_t count; 106 ssize_t count;
@@ -88,8 +114,8 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
88 if (!sysfs_get_active_two(attr_sd)) 114 if (!sysfs_get_active_two(attr_sd))
89 return -ENODEV; 115 return -ENODEV;
90 116
91 buffer->event = atomic_read(&attr_sd->s_event); 117 buffer->event = atomic_read(&attr_sd->s_attr.open->event);
92 count = ops->show(kobj, attr_sd->s_elem.attr.attr, buffer->page); 118 count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
93 119
94 sysfs_put_active_two(attr_sd); 120 sysfs_put_active_two(attr_sd);
95 121
@@ -128,7 +154,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
128 struct sysfs_buffer * buffer = file->private_data; 154 struct sysfs_buffer * buffer = file->private_data;
129 ssize_t retval = 0; 155 ssize_t retval = 0;
130 156
131 down(&buffer->sem); 157 mutex_lock(&buffer->mutex);
132 if (buffer->needs_read_fill) { 158 if (buffer->needs_read_fill) {
133 retval = fill_read_buffer(file->f_path.dentry,buffer); 159 retval = fill_read_buffer(file->f_path.dentry,buffer);
134 if (retval) 160 if (retval)
@@ -139,7 +165,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
139 retval = simple_read_from_buffer(buf, count, ppos, buffer->page, 165 retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
140 buffer->count); 166 buffer->count);
141out: 167out:
142 up(&buffer->sem); 168 mutex_unlock(&buffer->mutex);
143 return retval; 169 return retval;
144} 170}
145 171
@@ -189,7 +215,7 @@ static int
189flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count) 215flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t count)
190{ 216{
191 struct sysfs_dirent *attr_sd = dentry->d_fsdata; 217 struct sysfs_dirent *attr_sd = dentry->d_fsdata;
192 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; 218 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
193 struct sysfs_ops * ops = buffer->ops; 219 struct sysfs_ops * ops = buffer->ops;
194 int rc; 220 int rc;
195 221
@@ -197,7 +223,7 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
197 if (!sysfs_get_active_two(attr_sd)) 223 if (!sysfs_get_active_two(attr_sd))
198 return -ENODEV; 224 return -ENODEV;
199 225
200 rc = ops->store(kobj, attr_sd->s_elem.attr.attr, buffer->page, count); 226 rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
201 227
202 sysfs_put_active_two(attr_sd); 228 sysfs_put_active_two(attr_sd);
203 229
@@ -228,20 +254,102 @@ sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t
228 struct sysfs_buffer * buffer = file->private_data; 254 struct sysfs_buffer * buffer = file->private_data;
229 ssize_t len; 255 ssize_t len;
230 256
231 down(&buffer->sem); 257 mutex_lock(&buffer->mutex);
232 len = fill_write_buffer(buffer, buf, count); 258 len = fill_write_buffer(buffer, buf, count);
233 if (len > 0) 259 if (len > 0)
234 len = flush_write_buffer(file->f_path.dentry, buffer, len); 260 len = flush_write_buffer(file->f_path.dentry, buffer, len);
235 if (len > 0) 261 if (len > 0)
236 *ppos += len; 262 *ppos += len;
237 up(&buffer->sem); 263 mutex_unlock(&buffer->mutex);
238 return len; 264 return len;
239} 265}
240 266
267/**
268 * sysfs_get_open_dirent - get or create sysfs_open_dirent
269 * @sd: target sysfs_dirent
270 * @buffer: sysfs_buffer for this instance of open
271 *
272 * If @sd->s_attr.open exists, increment its reference count;
273 * otherwise, create one. @buffer is chained to the buffers
274 * list.
275 *
276 * LOCKING:
277 * Kernel thread context (may sleep).
278 *
279 * RETURNS:
280 * 0 on success, -errno on failure.
281 */
282static int sysfs_get_open_dirent(struct sysfs_dirent *sd,
283 struct sysfs_buffer *buffer)
284{
285 struct sysfs_open_dirent *od, *new_od = NULL;
286
287 retry:
288 spin_lock(&sysfs_open_dirent_lock);
289
290 if (!sd->s_attr.open && new_od) {
291 sd->s_attr.open = new_od;
292 new_od = NULL;
293 }
294
295 od = sd->s_attr.open;
296 if (od) {
297 atomic_inc(&od->refcnt);
298 list_add_tail(&buffer->list, &od->buffers);
299 }
300
301 spin_unlock(&sysfs_open_dirent_lock);
302
303 if (od) {
304 kfree(new_od);
305 return 0;
306 }
307
308 /* not there, initialize a new one and retry */
309 new_od = kmalloc(sizeof(*new_od), GFP_KERNEL);
310 if (!new_od)
311 return -ENOMEM;
312
313 atomic_set(&new_od->refcnt, 0);
314 atomic_set(&new_od->event, 1);
315 init_waitqueue_head(&new_od->poll);
316 INIT_LIST_HEAD(&new_od->buffers);
317 goto retry;
318}
319
320/**
321 * sysfs_put_open_dirent - put sysfs_open_dirent
322 * @sd: target sysfs_dirent
323 * @buffer: associated sysfs_buffer
324 *
325 * Put @sd->s_attr.open and unlink @buffer from the buffers list.
326 * If reference count reaches zero, disassociate and free it.
327 *
328 * LOCKING:
329 * None.
330 */
331static void sysfs_put_open_dirent(struct sysfs_dirent *sd,
332 struct sysfs_buffer *buffer)
333{
334 struct sysfs_open_dirent *od = sd->s_attr.open;
335
336 spin_lock(&sysfs_open_dirent_lock);
337
338 list_del(&buffer->list);
339 if (atomic_dec_and_test(&od->refcnt))
340 sd->s_attr.open = NULL;
341 else
342 od = NULL;
343
344 spin_unlock(&sysfs_open_dirent_lock);
345
346 kfree(od);
347}
348
241static int sysfs_open_file(struct inode *inode, struct file *file) 349static int sysfs_open_file(struct inode *inode, struct file *file)
242{ 350{
243 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; 351 struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
244 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; 352 struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
245 struct sysfs_buffer * buffer; 353 struct sysfs_buffer * buffer;
246 struct sysfs_ops * ops = NULL; 354 struct sysfs_ops * ops = NULL;
247 int error; 355 int error;
@@ -294,33 +402,38 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
294 if (!buffer) 402 if (!buffer)
295 goto err_out; 403 goto err_out;
296 404
297 init_MUTEX(&buffer->sem); 405 mutex_init(&buffer->mutex);
298 buffer->needs_read_fill = 1; 406 buffer->needs_read_fill = 1;
299 buffer->ops = ops; 407 buffer->ops = ops;
300 file->private_data = buffer; 408 file->private_data = buffer;
301 409
302 /* open succeeded, put active references and pin attr_sd */ 410 /* make sure we have open dirent struct */
411 error = sysfs_get_open_dirent(attr_sd, buffer);
412 if (error)
413 goto err_free;
414
415 /* open succeeded, put active references */
303 sysfs_put_active_two(attr_sd); 416 sysfs_put_active_two(attr_sd);
304 sysfs_get(attr_sd);
305 return 0; 417 return 0;
306 418
419 err_free:
420 kfree(buffer);
307 err_out: 421 err_out:
308 sysfs_put_active_two(attr_sd); 422 sysfs_put_active_two(attr_sd);
309 return error; 423 return error;
310} 424}
311 425
312static int sysfs_release(struct inode * inode, struct file * filp) 426static int sysfs_release(struct inode *inode, struct file *filp)
313{ 427{
314 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; 428 struct sysfs_dirent *sd = filp->f_path.dentry->d_fsdata;
315 struct sysfs_buffer *buffer = filp->private_data; 429 struct sysfs_buffer *buffer = filp->private_data;
316 430
317 sysfs_put(attr_sd); 431 sysfs_put_open_dirent(sd, buffer);
432
433 if (buffer->page)
434 free_page((unsigned long)buffer->page);
435 kfree(buffer);
318 436
319 if (buffer) {
320 if (buffer->page)
321 free_page((unsigned long)buffer->page);
322 kfree(buffer);
323 }
324 return 0; 437 return 0;
325} 438}
326 439
@@ -335,24 +448,24 @@ static int sysfs_release(struct inode * inode, struct file * filp)
335 * again will not get new data, or reset the state of 'poll'. 448 * again will not get new data, or reset the state of 'poll'.
336 * Reminder: this only works for attributes which actively support 449 * Reminder: this only works for attributes which actively support
337 * it, and it is not possible to test an attribute from userspace 450 * it, and it is not possible to test an attribute from userspace
338 * to see if it supports poll (Nether 'poll' or 'select' return 451 * to see if it supports poll (Neither 'poll' nor 'select' return
339 * an appropriate error code). When in doubt, set a suitable timeout value. 452 * an appropriate error code). When in doubt, set a suitable timeout value.
340 */ 453 */
341static unsigned int sysfs_poll(struct file *filp, poll_table *wait) 454static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
342{ 455{
343 struct sysfs_buffer * buffer = filp->private_data; 456 struct sysfs_buffer * buffer = filp->private_data;
344 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata; 457 struct sysfs_dirent *attr_sd = filp->f_path.dentry->d_fsdata;
345 struct kobject *kobj = attr_sd->s_parent->s_elem.dir.kobj; 458 struct sysfs_open_dirent *od = attr_sd->s_attr.open;
346 459
347 /* need parent for the kobj, grab both */ 460 /* need parent for the kobj, grab both */
348 if (!sysfs_get_active_two(attr_sd)) 461 if (!sysfs_get_active_two(attr_sd))
349 goto trigger; 462 goto trigger;
350 463
351 poll_wait(filp, &kobj->poll, wait); 464 poll_wait(filp, &od->poll, wait);
352 465
353 sysfs_put_active_two(attr_sd); 466 sysfs_put_active_two(attr_sd);
354 467
355 if (buffer->event != atomic_read(&attr_sd->s_event)) 468 if (buffer->event != atomic_read(&od->event))
356 goto trigger; 469 goto trigger;
357 470
358 return 0; 471 return 0;
@@ -373,8 +486,17 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
373 if (sd && attr) 486 if (sd && attr)
374 sd = sysfs_find_dirent(sd, attr); 487 sd = sysfs_find_dirent(sd, attr);
375 if (sd) { 488 if (sd) {
376 atomic_inc(&sd->s_event); 489 struct sysfs_open_dirent *od;
377 wake_up_interruptible(&k->poll); 490
491 spin_lock(&sysfs_open_dirent_lock);
492
493 od = sd->s_attr.open;
494 if (od) {
495 atomic_inc(&od->event);
496 wake_up_interruptible(&od->poll);
497 }
498
499 spin_unlock(&sysfs_open_dirent_lock);
378 } 500 }
379 501
380 mutex_unlock(&sysfs_mutex); 502 mutex_unlock(&sysfs_mutex);
@@ -397,25 +519,21 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
397 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; 519 umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG;
398 struct sysfs_addrm_cxt acxt; 520 struct sysfs_addrm_cxt acxt;
399 struct sysfs_dirent *sd; 521 struct sysfs_dirent *sd;
522 int rc;
400 523
401 sd = sysfs_new_dirent(attr->name, mode, type); 524 sd = sysfs_new_dirent(attr->name, mode, type);
402 if (!sd) 525 if (!sd)
403 return -ENOMEM; 526 return -ENOMEM;
404 sd->s_elem.attr.attr = (void *)attr; 527 sd->s_attr.attr = (void *)attr;
405 528
406 sysfs_addrm_start(&acxt, dir_sd); 529 sysfs_addrm_start(&acxt, dir_sd);
530 rc = sysfs_add_one(&acxt, sd);
531 sysfs_addrm_finish(&acxt);
407 532
408 if (!sysfs_find_dirent(dir_sd, attr->name)) { 533 if (rc)
409 sysfs_add_one(&acxt, sd);
410 sysfs_link_sibling(sd);
411 }
412
413 if (!sysfs_addrm_finish(&acxt)) {
414 sysfs_put(sd); 534 sysfs_put(sd);
415 return -EEXIST;
416 }
417 535
418 return 0; 536 return rc;
419} 537}
420 538
421 539
@@ -457,42 +575,6 @@ int sysfs_add_file_to_group(struct kobject *kobj,
457} 575}
458EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); 576EXPORT_SYMBOL_GPL(sysfs_add_file_to_group);
459 577
460
461/**
462 * sysfs_update_file - update the modified timestamp on an object attribute.
463 * @kobj: object we're acting for.
464 * @attr: attribute descriptor.
465 */
466int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
467{
468 struct sysfs_dirent *victim_sd = NULL;
469 struct dentry *victim = NULL;
470 int rc;
471
472 rc = -ENOENT;
473 victim_sd = sysfs_get_dirent(kobj->sd, attr->name);
474 if (!victim_sd)
475 goto out;
476
477 victim = sysfs_get_dentry(victim_sd);
478 if (IS_ERR(victim)) {
479 rc = PTR_ERR(victim);
480 victim = NULL;
481 goto out;
482 }
483
484 mutex_lock(&victim->d_inode->i_mutex);
485 victim->d_inode->i_mtime = CURRENT_TIME;
486 fsnotify_modify(victim);
487 mutex_unlock(&victim->d_inode->i_mutex);
488 rc = 0;
489 out:
490 dput(victim);
491 sysfs_put(victim_sd);
492 return rc;
493}
494
495
496/** 578/**
497 * sysfs_chmod_file - update the modified mode value on an object attribute. 579 * sysfs_chmod_file - update the modified mode value on an object attribute.
498 * @kobj: object we're acting for. 580 * @kobj: object we're acting for.
@@ -513,7 +595,9 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
513 if (!victim_sd) 595 if (!victim_sd)
514 goto out; 596 goto out;
515 597
598 mutex_lock(&sysfs_rename_mutex);
516 victim = sysfs_get_dentry(victim_sd); 599 victim = sysfs_get_dentry(victim_sd);
600 mutex_unlock(&sysfs_rename_mutex);
517 if (IS_ERR(victim)) { 601 if (IS_ERR(victim)) {
518 rc = PTR_ERR(victim); 602 rc = PTR_ERR(victim);
519 victim = NULL; 603 victim = NULL;
@@ -521,10 +605,19 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
521 } 605 }
522 606
523 inode = victim->d_inode; 607 inode = victim->d_inode;
608
524 mutex_lock(&inode->i_mutex); 609 mutex_lock(&inode->i_mutex);
610
525 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 611 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
526 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; 612 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
527 rc = notify_change(victim, &newattrs); 613 rc = notify_change(victim, &newattrs);
614
615 if (rc == 0) {
616 mutex_lock(&sysfs_mutex);
617 victim_sd->s_mode = newattrs.ia_mode;
618 mutex_unlock(&sysfs_mutex);
619 }
620
528 mutex_unlock(&inode->i_mutex); 621 mutex_unlock(&inode->i_mutex);
529 out: 622 out:
530 dput(victim); 623 dput(victim);
@@ -632,4 +725,3 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
632 725
633EXPORT_SYMBOL_GPL(sysfs_create_file); 726EXPORT_SYMBOL_GPL(sysfs_create_file);
634EXPORT_SYMBOL_GPL(sysfs_remove_file); 727EXPORT_SYMBOL_GPL(sysfs_remove_file);
635EXPORT_SYMBOL_GPL(sysfs_update_file);