aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/dir.c5
-rw-r--r--fs/sysfs/file.c35
-rw-r--r--fs/sysfs/group.c4
-rw-r--r--fs/sysfs/inode.c16
-rw-r--r--fs/sysfs/symlink.c6
-rw-r--r--fs/sysfs/sysfs.h1
6 files changed, 32 insertions, 35 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 37d7a6875d..59734ba1ee 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -8,6 +8,7 @@
8#include <linux/mount.h> 8#include <linux/mount.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/kobject.h> 10#include <linux/kobject.h>
11#include <linux/namei.h>
11#include "sysfs.h" 12#include "sysfs.h"
12 13
13DECLARE_RWSEM(sysfs_rename_sem); 14DECLARE_RWSEM(sysfs_rename_sem);
@@ -99,7 +100,7 @@ static int create_dir(struct kobject * k, struct dentry * p,
99 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; 100 umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
100 101
101 down(&p->d_inode->i_sem); 102 down(&p->d_inode->i_sem);
102 *d = sysfs_get_dentry(p,n); 103 *d = lookup_one_len(n, p, strlen(n));
103 if (!IS_ERR(*d)) { 104 if (!IS_ERR(*d)) {
104 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR); 105 error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
105 if (!error) { 106 if (!error) {
@@ -315,7 +316,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
315 316
316 down(&parent->d_inode->i_sem); 317 down(&parent->d_inode->i_sem);
317 318
318 new_dentry = sysfs_get_dentry(parent, new_name); 319 new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
319 if (!IS_ERR(new_dentry)) { 320 if (!IS_ERR(new_dentry)) {
320 if (!new_dentry->d_inode) { 321 if (!new_dentry->d_inode) {
321 error = kobject_set_name(kobj, "%s", new_name); 322 error = kobject_set_name(kobj, "%s", new_name);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 849aac1154..4013d7905e 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -3,8 +3,9 @@
3 */ 3 */
4 4
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/dnotify.h> 6#include <linux/fsnotify.h>
7#include <linux/kobject.h> 7#include <linux/kobject.h>
8#include <linux/namei.h>
8#include <asm/uaccess.h> 9#include <asm/uaccess.h>
9#include <asm/semaphore.h> 10#include <asm/semaphore.h>
10 11
@@ -13,7 +14,7 @@
13#define to_subsys(k) container_of(k,struct subsystem,kset.kobj) 14#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
14#define to_sattr(a) container_of(a,struct subsys_attribute,attr) 15#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
15 16
16/** 17/*
17 * Subsystem file operations. 18 * Subsystem file operations.
18 * These operations allow subsystems to have files that can be 19 * These operations allow subsystems to have files that can be
19 * read/written. 20 * read/written.
@@ -191,8 +192,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
191 192
192/** 193/**
193 * flush_write_buffer - push buffer to kobject. 194 * flush_write_buffer - push buffer to kobject.
194 * @file: file pointer. 195 * @dentry: dentry to the attribute
195 * @buffer: data buffer for file. 196 * @buffer: data buffer for file.
197 * @count: number of bytes
196 * 198 *
197 * Get the correct pointers for the kobject and the attribute we're 199 * Get the correct pointers for the kobject and the attribute we're
198 * dealing with, then call the store() method for the attribute, 200 * dealing with, then call the store() method for the attribute,
@@ -389,9 +391,6 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
389 * sysfs_update_file - update the modified timestamp on an object attribute. 391 * sysfs_update_file - update the modified timestamp on an object attribute.
390 * @kobj: object we're acting for. 392 * @kobj: object we're acting for.
391 * @attr: attribute descriptor. 393 * @attr: attribute descriptor.
392 *
393 * Also call dnotify for the dentry, which lots of userspace programs
394 * use.
395 */ 394 */
396int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) 395int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
397{ 396{
@@ -400,13 +399,13 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
400 int res = -ENOENT; 399 int res = -ENOENT;
401 400
402 down(&dir->d_inode->i_sem); 401 down(&dir->d_inode->i_sem);
403 victim = sysfs_get_dentry(dir, attr->name); 402 victim = lookup_one_len(attr->name, dir, strlen(attr->name));
404 if (!IS_ERR(victim)) { 403 if (!IS_ERR(victim)) {
405 /* make sure dentry is really there */ 404 /* make sure dentry is really there */
406 if (victim->d_inode && 405 if (victim->d_inode &&
407 (victim->d_parent->d_inode == dir->d_inode)) { 406 (victim->d_parent->d_inode == dir->d_inode)) {
408 victim->d_inode->i_mtime = CURRENT_TIME; 407 victim->d_inode->i_mtime = CURRENT_TIME;
409 dnotify_parent(victim, DN_MODIFY); 408 fsnotify_modify(victim);
410 409
411 /** 410 /**
412 * Drop reference from initial sysfs_get_dentry(). 411 * Drop reference from initial sysfs_get_dentry().
@@ -438,22 +437,24 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
438{ 437{
439 struct dentry *dir = kobj->dentry; 438 struct dentry *dir = kobj->dentry;
440 struct dentry *victim; 439 struct dentry *victim;
441 struct sysfs_dirent *sd; 440 struct inode * inode;
442 umode_t umode = (mode & S_IALLUGO) | S_IFREG; 441 struct iattr newattrs;
443 int res = -ENOENT; 442 int res = -ENOENT;
444 443
445 down(&dir->d_inode->i_sem); 444 down(&dir->d_inode->i_sem);
446 victim = sysfs_get_dentry(dir, attr->name); 445 victim = lookup_one_len(attr->name, dir, strlen(attr->name));
447 if (!IS_ERR(victim)) { 446 if (!IS_ERR(victim)) {
448 if (victim->d_inode && 447 if (victim->d_inode &&
449 (victim->d_parent->d_inode == dir->d_inode)) { 448 (victim->d_parent->d_inode == dir->d_inode)) {
450 sd = victim->d_fsdata; 449 inode = victim->d_inode;
451 attr->mode = mode; 450 down(&inode->i_sem);
452 sd->s_mode = umode; 451 newattrs.ia_mode = (mode & S_IALLUGO) |
453 victim->d_inode->i_mode = umode; 452 (inode->i_mode & ~S_IALLUGO);
454 dput(victim); 453 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
455 res = 0; 454 res = notify_change(victim, &newattrs);
455 up(&inode->i_sem);
456 } 456 }
457 dput(victim);
457 } 458 }
458 up(&dir->d_inode->i_sem); 459 up(&dir->d_inode->i_sem);
459 460
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index f11ac5ea70..122145b089 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -11,6 +11,7 @@
11#include <linux/kobject.h> 11#include <linux/kobject.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/dcache.h> 13#include <linux/dcache.h>
14#include <linux/namei.h>
14#include <linux/err.h> 15#include <linux/err.h>
15#include "sysfs.h" 16#include "sysfs.h"
16 17
@@ -68,7 +69,8 @@ void sysfs_remove_group(struct kobject * kobj,
68 struct dentry * dir; 69 struct dentry * dir;
69 70
70 if (grp->name) 71 if (grp->name)
71 dir = sysfs_get_dentry(kobj->dentry,grp->name); 72 dir = lookup_one_len(grp->name, kobj->dentry,
73 strlen(grp->name));
72 else 74 else
73 dir = dget(kobj->dentry); 75 dir = dget(kobj->dentry);
74 76
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 565cac1d42..970a33f032 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -85,7 +85,7 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
85 85
86 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 86 if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
87 mode &= ~S_ISGID; 87 mode &= ~S_ISGID;
88 sd_iattr->ia_mode = mode; 88 sd_iattr->ia_mode = sd->s_mode = mode;
89 } 89 }
90 90
91 return error; 91 return error;
@@ -166,16 +166,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
166 return error; 166 return error;
167} 167}
168 168
169struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
170{
171 struct qstr qstr;
172
173 qstr.name = name;
174 qstr.len = strlen(name);
175 qstr.hash = full_name_hash(name,qstr.len);
176 return lookup_hash(&qstr,parent);
177}
178
179/* 169/*
180 * Get the name for corresponding element represented by the given sysfs_dirent 170 * Get the name for corresponding element represented by the given sysfs_dirent
181 */ 171 */
@@ -238,6 +228,10 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
238 struct sysfs_dirent * sd; 228 struct sysfs_dirent * sd;
239 struct sysfs_dirent * parent_sd = dir->d_fsdata; 229 struct sysfs_dirent * parent_sd = dir->d_fsdata;
240 230
231 if (dir->d_inode == NULL)
232 /* no inode means this hasn't been made visible yet */
233 return;
234
241 down(&dir->d_inode->i_sem); 235 down(&dir->d_inode->i_sem);
242 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { 236 list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
243 if (!sd->s_element) 237 if (!sd->s_element)
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index fae57c83a7..de402fa915 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -151,17 +151,17 @@ static int sysfs_getlink(struct dentry *dentry, char * path)
151 151
152} 152}
153 153
154static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) 154static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
155{ 155{
156 int error = -ENOMEM; 156 int error = -ENOMEM;
157 unsigned long page = get_zeroed_page(GFP_KERNEL); 157 unsigned long page = get_zeroed_page(GFP_KERNEL);
158 if (page) 158 if (page)
159 error = sysfs_getlink(dentry, (char *) page); 159 error = sysfs_getlink(dentry, (char *) page);
160 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page); 160 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
161 return 0; 161 return NULL;
162} 162}
163 163
164static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) 164static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
165{ 165{
166 char *page = nd_get_link(nd); 166 char *page = nd_get_link(nd);
167 if (!IS_ERR(page)) 167 if (!IS_ERR(page))
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 29da6f5f07..3f8953e0e5 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -7,7 +7,6 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
7 7
8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, 8extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
9 umode_t, int); 9 umode_t, int);
10extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
11 10
12extern int sysfs_add_file(struct dentry *, const struct attribute *, int); 11extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
13extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); 12extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);