diff options
-rw-r--r-- | fs/sysfs/dir.c | 82 | ||||
-rw-r--r-- | fs/sysfs/file.c | 21 | ||||
-rw-r--r-- | fs/sysfs/symlink.c | 7 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 7 |
4 files changed, 50 insertions, 67 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 90bed5df254f..f16aa7e3eafc 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -85,10 +85,7 @@ static struct dentry_operations sysfs_dentry_ops = { | |||
85 | .d_iput = sysfs_d_iput, | 85 | .d_iput = sysfs_d_iput, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* | 88 | struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, int type) |
89 | * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent | ||
90 | */ | ||
91 | static struct sysfs_dirent * __sysfs_new_dirent(void * element) | ||
92 | { | 89 | { |
93 | struct sysfs_dirent * sd; | 90 | struct sysfs_dirent * sd; |
94 | 91 | ||
@@ -105,25 +102,25 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element) | |||
105 | atomic_set(&sd->s_event, 1); | 102 | atomic_set(&sd->s_event, 1); |
106 | INIT_LIST_HEAD(&sd->s_children); | 103 | INIT_LIST_HEAD(&sd->s_children); |
107 | INIT_LIST_HEAD(&sd->s_sibling); | 104 | INIT_LIST_HEAD(&sd->s_sibling); |
105 | |||
108 | sd->s_element = element; | 106 | sd->s_element = element; |
107 | sd->s_mode = mode; | ||
108 | sd->s_type = type; | ||
109 | 109 | ||
110 | return sd; | 110 | return sd; |
111 | } | 111 | } |
112 | 112 | ||
113 | static void __sysfs_list_dirent(struct sysfs_dirent *parent_sd, | 113 | void sysfs_attach_dirent(struct sysfs_dirent *sd, |
114 | struct sysfs_dirent *sd) | 114 | struct sysfs_dirent *parent_sd, struct dentry *dentry) |
115 | { | 115 | { |
116 | if (sd) | 116 | if (dentry) { |
117 | list_add(&sd->s_sibling, &parent_sd->s_children); | 117 | sd->s_dentry = dentry; |
118 | } | 118 | dentry->d_fsdata = sysfs_get(sd); |
119 | dentry->d_op = &sysfs_dentry_ops; | ||
120 | } | ||
119 | 121 | ||
120 | static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent *parent_sd, | 122 | if (parent_sd) |
121 | void * element) | 123 | list_add(&sd->s_sibling, &parent_sd->s_children); |
122 | { | ||
123 | struct sysfs_dirent *sd; | ||
124 | sd = __sysfs_new_dirent(element); | ||
125 | __sysfs_list_dirent(parent_sd, sd); | ||
126 | return sd; | ||
127 | } | 124 | } |
128 | 125 | ||
129 | /* | 126 | /* |
@@ -151,39 +148,6 @@ int sysfs_dirent_exist(struct sysfs_dirent *parent_sd, | |||
151 | return 0; | 148 | return 0; |
152 | } | 149 | } |
153 | 150 | ||
154 | |||
155 | static struct sysfs_dirent * | ||
156 | __sysfs_make_dirent(struct dentry *dentry, void *element, mode_t mode, int type) | ||
157 | { | ||
158 | struct sysfs_dirent * sd; | ||
159 | |||
160 | sd = __sysfs_new_dirent(element); | ||
161 | if (!sd) | ||
162 | goto out; | ||
163 | |||
164 | sd->s_mode = mode; | ||
165 | sd->s_type = type; | ||
166 | sd->s_dentry = dentry; | ||
167 | if (dentry) { | ||
168 | dentry->d_fsdata = sysfs_get(sd); | ||
169 | dentry->d_op = &sysfs_dentry_ops; | ||
170 | } | ||
171 | |||
172 | out: | ||
173 | return sd; | ||
174 | } | ||
175 | |||
176 | int sysfs_make_dirent(struct sysfs_dirent * parent_sd, struct dentry * dentry, | ||
177 | void * element, umode_t mode, int type) | ||
178 | { | ||
179 | struct sysfs_dirent *sd; | ||
180 | |||
181 | sd = __sysfs_make_dirent(dentry, element, mode, type); | ||
182 | __sysfs_list_dirent(parent_sd, sd); | ||
183 | |||
184 | return sd ? 0 : -ENOMEM; | ||
185 | } | ||
186 | |||
187 | static int init_dir(struct inode * inode) | 151 | static int init_dir(struct inode * inode) |
188 | { | 152 | { |
189 | inode->i_op = &sysfs_dir_inode_operations; | 153 | inode->i_op = &sysfs_dir_inode_operations; |
@@ -227,10 +191,11 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
227 | if (sysfs_dirent_exist(parent->d_fsdata, name)) | 191 | if (sysfs_dirent_exist(parent->d_fsdata, name)) |
228 | goto out_dput; | 192 | goto out_dput; |
229 | 193 | ||
230 | error = sysfs_make_dirent(parent->d_fsdata, dentry, kobj, mode, | 194 | error = -ENOMEM; |
231 | SYSFS_DIR); | 195 | sd = sysfs_new_dirent(kobj, mode, SYSFS_DIR); |
232 | if (error) | 196 | if (!sd) |
233 | goto out_drop; | 197 | goto out_drop; |
198 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); | ||
234 | 199 | ||
235 | error = sysfs_create(dentry, mode, init_dir); | 200 | error = sysfs_create(dentry, mode, init_dir); |
236 | if (error) | 201 | if (error) |
@@ -245,7 +210,6 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
245 | goto out_dput; | 210 | goto out_dput; |
246 | 211 | ||
247 | out_sput: | 212 | out_sput: |
248 | sd = dentry->d_fsdata; | ||
249 | list_del_init(&sd->s_sibling); | 213 | list_del_init(&sd->s_sibling); |
250 | sysfs_put(sd); | 214 | sysfs_put(sd); |
251 | out_drop: | 215 | out_drop: |
@@ -557,13 +521,16 @@ static int sysfs_dir_open(struct inode *inode, struct file *file) | |||
557 | { | 521 | { |
558 | struct dentry * dentry = file->f_path.dentry; | 522 | struct dentry * dentry = file->f_path.dentry; |
559 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; | 523 | struct sysfs_dirent * parent_sd = dentry->d_fsdata; |
524 | struct sysfs_dirent * sd; | ||
560 | 525 | ||
561 | mutex_lock(&dentry->d_inode->i_mutex); | 526 | mutex_lock(&dentry->d_inode->i_mutex); |
562 | file->private_data = sysfs_new_dirent(parent_sd, NULL); | 527 | sd = sysfs_new_dirent(NULL, 0, 0); |
528 | if (sd) | ||
529 | sysfs_attach_dirent(sd, parent_sd, NULL); | ||
563 | mutex_unlock(&dentry->d_inode->i_mutex); | 530 | mutex_unlock(&dentry->d_inode->i_mutex); |
564 | 531 | ||
565 | return file->private_data ? 0 : -ENOMEM; | 532 | file->private_data = sd; |
566 | 533 | return sd ? 0 : -ENOMEM; | |
567 | } | 534 | } |
568 | 535 | ||
569 | static int sysfs_dir_close(struct inode *inode, struct file *file) | 536 | static int sysfs_dir_close(struct inode *inode, struct file *file) |
@@ -736,9 +703,10 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | |||
736 | if (!shadow) | 703 | if (!shadow) |
737 | goto nomem; | 704 | goto nomem; |
738 | 705 | ||
739 | sd = __sysfs_make_dirent(shadow, kobj, inode->i_mode, SYSFS_DIR); | 706 | sd = sysfs_new_dirent(kobj, inode->i_mode, SYSFS_DIR); |
740 | if (!sd) | 707 | if (!sd) |
741 | goto nomem; | 708 | goto nomem; |
709 | sysfs_attach_dirent(sd, NULL, shadow); | ||
742 | 710 | ||
743 | d_instantiate(shadow, igrab(inode)); | 711 | d_instantiate(shadow, igrab(inode)); |
744 | inc_nlink(inode); | 712 | inc_nlink(inode); |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index b502c7197ec0..fd4b6dc03d2d 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -444,14 +444,25 @@ int sysfs_add_file(struct dentry * dir, const struct attribute * attr, int type) | |||
444 | { | 444 | { |
445 | struct sysfs_dirent * parent_sd = dir->d_fsdata; | 445 | struct sysfs_dirent * parent_sd = dir->d_fsdata; |
446 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; | 446 | umode_t mode = (attr->mode & S_IALLUGO) | S_IFREG; |
447 | int error = -EEXIST; | 447 | struct sysfs_dirent *sd; |
448 | int error = 0; | ||
448 | 449 | ||
449 | mutex_lock(&dir->d_inode->i_mutex); | 450 | mutex_lock(&dir->d_inode->i_mutex); |
450 | if (!sysfs_dirent_exist(parent_sd, attr->name)) | ||
451 | error = sysfs_make_dirent(parent_sd, NULL, (void *)attr, | ||
452 | mode, type); | ||
453 | mutex_unlock(&dir->d_inode->i_mutex); | ||
454 | 451 | ||
452 | if (sysfs_dirent_exist(parent_sd, attr->name)) { | ||
453 | error = -EEXIST; | ||
454 | goto out_unlock; | ||
455 | } | ||
456 | |||
457 | sd = sysfs_new_dirent((void *)attr, mode, type); | ||
458 | if (!sd) { | ||
459 | error = -ENOMEM; | ||
460 | goto out_unlock; | ||
461 | } | ||
462 | sysfs_attach_dirent(sd, parent_sd, NULL); | ||
463 | |||
464 | out_unlock: | ||
465 | mutex_unlock(&dir->d_inode->i_mutex); | ||
455 | return error; | 466 | return error; |
456 | } | 467 | } |
457 | 468 | ||
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index b463f17f6638..d96bb9cbc9d4 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -49,6 +49,7 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj | |||
49 | { | 49 | { |
50 | struct sysfs_dirent * parent_sd = parent->d_fsdata; | 50 | struct sysfs_dirent * parent_sd = parent->d_fsdata; |
51 | struct sysfs_symlink * sl; | 51 | struct sysfs_symlink * sl; |
52 | struct sysfs_dirent * sd; | ||
52 | int error; | 53 | int error; |
53 | 54 | ||
54 | error = -ENOMEM; | 55 | error = -ENOMEM; |
@@ -63,10 +64,10 @@ static int sysfs_add_link(struct dentry * parent, const char * name, struct kobj | |||
63 | strcpy(sl->link_name, name); | 64 | strcpy(sl->link_name, name); |
64 | sl->target_kobj = kobject_get(target); | 65 | sl->target_kobj = kobject_get(target); |
65 | 66 | ||
66 | error = sysfs_make_dirent(parent_sd, NULL, sl, S_IFLNK|S_IRWXUGO, | 67 | sd = sysfs_new_dirent(sl, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); |
67 | SYSFS_KOBJ_LINK); | 68 | if (!sd) |
68 | if (error) | ||
69 | goto err_out; | 69 | goto err_out; |
70 | sysfs_attach_dirent(sd, parent_sd, NULL); | ||
70 | 71 | ||
71 | return 0; | 72 | return 0; |
72 | 73 | ||
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index f4fdbbffd571..f8f49cc5c852 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -20,8 +20,11 @@ extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | |||
20 | 20 | ||
21 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | 21 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |
22 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | 22 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); |
23 | extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *, | 23 | extern struct sysfs_dirent *sysfs_new_dirent(void *element, umode_t mode, |
24 | umode_t, int); | 24 | int type); |
25 | extern void sysfs_attach_dirent(struct sysfs_dirent *sd, | ||
26 | struct sysfs_dirent *parent_sd, | ||
27 | struct dentry *dentry); | ||
25 | 28 | ||
26 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); | 29 | extern int sysfs_add_file(struct dentry *, const struct attribute *, int); |
27 | extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); | 30 | extern int sysfs_hash_and_remove(struct dentry * dir, const char * name); |