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.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index c9e4e5091da1..1f4a3f877262 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -19,10 +19,18 @@
19#include <linux/poll.h> 19#include <linux/poll.h>
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/mutex.h> 21#include <linux/mutex.h>
22#include <linux/limits.h>
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
24#include "sysfs.h" 25#include "sysfs.h"
25 26
27/* used in crash dumps to help with debugging */
28static char last_sysfs_file[PATH_MAX];
29void sysfs_printk_last_file(void)
30{
31 printk(KERN_EMERG "last sysfs file: %s\n", last_sysfs_file);
32}
33
26/* 34/*
27 * There's one sysfs_buffer for each open file and one 35 * There's one sysfs_buffer for each open file and one
28 * sysfs_open_dirent for each sysfs_dirent with one or more open 36 * sysfs_open_dirent for each sysfs_dirent with one or more open
@@ -328,6 +336,11 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
328 struct sysfs_buffer *buffer; 336 struct sysfs_buffer *buffer;
329 struct sysfs_ops *ops; 337 struct sysfs_ops *ops;
330 int error = -EACCES; 338 int error = -EACCES;
339 char *p;
340
341 p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
342 if (p)
343 memmove(last_sysfs_file, p, strlen(p) + 1);
331 344
332 /* need attr_sd for attr and ops, its parent for kobj */ 345 /* need attr_sd for attr and ops, its parent for kobj */
333 if (!sysfs_get_active_two(attr_sd)) 346 if (!sysfs_get_active_two(attr_sd))
@@ -440,7 +453,23 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
440 return POLLERR|POLLPRI; 453 return POLLERR|POLLPRI;
441} 454}
442 455
443void sysfs_notify(struct kobject *k, char *dir, char *attr) 456void sysfs_notify_dirent(struct sysfs_dirent *sd)
457{
458 struct sysfs_open_dirent *od;
459
460 spin_lock(&sysfs_open_dirent_lock);
461
462 od = sd->s_attr.open;
463 if (od) {
464 atomic_inc(&od->event);
465 wake_up_interruptible(&od->poll);
466 }
467
468 spin_unlock(&sysfs_open_dirent_lock);
469}
470EXPORT_SYMBOL_GPL(sysfs_notify_dirent);
471
472void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
444{ 473{
445 struct sysfs_dirent *sd = k->sd; 474 struct sysfs_dirent *sd = k->sd;
446 475
@@ -450,19 +479,8 @@ void sysfs_notify(struct kobject *k, char *dir, char *attr)
450 sd = sysfs_find_dirent(sd, dir); 479 sd = sysfs_find_dirent(sd, dir);
451 if (sd && attr) 480 if (sd && attr)
452 sd = sysfs_find_dirent(sd, attr); 481 sd = sysfs_find_dirent(sd, attr);
453 if (sd) { 482 if (sd)
454 struct sysfs_open_dirent *od; 483 sysfs_notify_dirent(sd);
455
456 spin_lock(&sysfs_open_dirent_lock);
457
458 od = sd->s_attr.open;
459 if (od) {
460 atomic_inc(&od->event);
461 wake_up_interruptible(&od->poll);
462 }
463
464 spin_unlock(&sysfs_open_dirent_lock);
465 }
466 484
467 mutex_unlock(&sysfs_mutex); 485 mutex_unlock(&sysfs_mutex);
468} 486}