From: Andrew Morton Signed-off-by: Andrew Morton --- fs/sysfs/file.c | 44 ++++++++------------------------------------ fs/sysfs/inode.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 36 deletions(-) diff -puN fs/sysfs/file.c~revert-gregkh-driver-fix-up-the-sysfs-pollable-patch fs/sysfs/file.c --- devel/fs/sysfs/file.c~revert-gregkh-driver-fix-up-the-sysfs-pollable-patch 2006-03-01 02:05:42.000000000 -0800 +++ devel-akpm/fs/sysfs/file.c 2006-03-01 02:05:42.000000000 -0800 @@ -388,50 +388,22 @@ static unsigned int sysfs_poll(struct fi poll_wait(filp, &kobj->poll, wait); - if (buffer->event != atomic_read(&sd->s_event)) { + if (buffer->event != atomic_read(&sd->s_event)) res = POLLERR|POLLPRI; - buffer->needs_read_fill = 1; - } return res; } - -static struct dentry *step_down(struct dentry *dir, const char * name) -{ - struct dentry * de; - - if (dir == NULL || dir->d_inode == NULL) - return NULL; - - mutex_lock(&dir->d_inode->i_mutex); - de = lookup_one_len(name, dir, strlen(name)); - mutex_unlock(&dir->d_inode->i_mutex); - dput(dir); - if (IS_ERR(de)) - return NULL; - if (de->d_inode == NULL) { - dput(de); - return NULL; - } - return de; -} - void sysfs_notify(struct kobject * k, char *dir, char *attr) { - struct dentry *de = k->dentry; - if (de) - dget(de); - if (de && dir) - de = step_down(de, dir); - if (de && attr) - de = step_down(de, attr); - if (de) { - struct sysfs_dirent * sd = de->d_fsdata; - if (sd) - atomic_inc(&sd->s_event); + struct sysfs_dirent * sd = k->dentry->d_fsdata; + if (sd && dir) + sd = sysfs_find(sd, dir); + if (sd && attr) + sd = sysfs_find(sd, attr); + if (sd) { + atomic_inc(&sd->s_event); wake_up_interruptible(&k->poll); - dput(de); } } EXPORT_SYMBOL_GPL(sysfs_notify); diff -puN fs/sysfs/inode.c~revert-gregkh-driver-fix-up-the-sysfs-pollable-patch fs/sysfs/inode.c --- devel/fs/sysfs/inode.c~revert-gregkh-driver-fix-up-the-sysfs-pollable-patch 2006-03-01 02:05:42.000000000 -0800 +++ devel-akpm/fs/sysfs/inode.c 2006-03-01 02:05:42.000000000 -0800 @@ -250,3 +250,24 @@ void sysfs_hash_and_remove(struct dentry } mutex_unlock(&dir->d_inode->i_mutex); } + +struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name) +{ + struct sysfs_dirent * sd, * rv = NULL; + + if (dir->s_dentry == NULL || + dir->s_dentry->d_inode == NULL) + return NULL; + + mutex_lock(&dir->s_dentry->d_inode->i_mutex); + list_for_each_entry(sd, &dir->s_children, s_sibling) { + if (!sd->s_element) + continue; + if (!strcmp(sysfs_get_name(sd), name)) { + rv = sd; + break; + } + } + mutex_unlock(&dir->s_dentry->d_inode->i_mutex); + return rv; +} _