diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 5 | ||||
-rw-r--r-- | fs/sysfs/file.c | 35 | ||||
-rw-r--r-- | fs/sysfs/group.c | 4 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 16 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 6 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 |
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 | ||
13 | DECLARE_RWSEM(sysfs_rename_sem); | 14 | DECLARE_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 | */ |
396 | int sysfs_update_file(struct kobject * kobj, const struct attribute * attr) | 395 | int 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 | ||
169 | struct 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 | ||
154 | static int sysfs_follow_link(struct dentry *dentry, struct nameidata *nd) | 154 | static 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 | ||
164 | static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd) | 164 | static 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 | ||
8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 8 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, |
9 | umode_t, int); | 9 | umode_t, int); |
10 | extern struct dentry * sysfs_get_dentry(struct dentry *, const char *); | ||
11 | 10 | ||
12 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); | 11 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); |
13 | extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); | 12 | extern void sysfs_hash_and_remove(struct dentry * dir, const char * name); |