diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 59 | ||||
-rw-r--r-- | fs/sysfs/inode.c | 4 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 3 |
3 files changed, 30 insertions, 36 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index e0d377aaf2cc..01eeb4b954b1 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -142,14 +142,24 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | |||
142 | return NULL; | 142 | return NULL; |
143 | } | 143 | } |
144 | 144 | ||
145 | static void sysfs_attach_dentry(struct sysfs_dirent *sd, struct dentry *dentry) | ||
146 | { | ||
147 | dentry->d_op = &sysfs_dentry_ops; | ||
148 | dentry->d_fsdata = sysfs_get(sd); | ||
149 | |||
150 | /* protect sd->s_dentry against sysfs_d_iput */ | ||
151 | spin_lock(&sysfs_lock); | ||
152 | sd->s_dentry = dentry; | ||
153 | spin_unlock(&sysfs_lock); | ||
154 | |||
155 | d_rehash(dentry); | ||
156 | } | ||
157 | |||
145 | void sysfs_attach_dirent(struct sysfs_dirent *sd, | 158 | void sysfs_attach_dirent(struct sysfs_dirent *sd, |
146 | struct sysfs_dirent *parent_sd, struct dentry *dentry) | 159 | struct sysfs_dirent *parent_sd, struct dentry *dentry) |
147 | { | 160 | { |
148 | if (dentry) { | 161 | if (dentry) |
149 | sd->s_dentry = dentry; | 162 | sysfs_attach_dentry(sd, dentry); |
150 | dentry->d_fsdata = sysfs_get(sd); | ||
151 | dentry->d_op = &sysfs_dentry_ops; | ||
152 | } | ||
153 | 163 | ||
154 | if (parent_sd) { | 164 | if (parent_sd) { |
155 | sd->s_parent = sysfs_get(parent_sd); | 165 | sd->s_parent = sysfs_get(parent_sd); |
@@ -229,15 +239,13 @@ static int create_dir(struct kobject *kobj, struct dentry *parent, | |||
229 | if (!sd) | 239 | if (!sd) |
230 | goto out_drop; | 240 | goto out_drop; |
231 | sd->s_elem.dir.kobj = kobj; | 241 | sd->s_elem.dir.kobj = kobj; |
232 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); | ||
233 | 242 | ||
234 | error = sysfs_create(dentry, mode, init_dir); | 243 | error = sysfs_create(sd, dentry, mode, init_dir); |
235 | if (error) | 244 | if (error) |
236 | goto out_sput; | 245 | goto out_sput; |
237 | 246 | ||
238 | inc_nlink(parent->d_inode); | 247 | inc_nlink(parent->d_inode); |
239 | dentry->d_op = &sysfs_dentry_ops; | 248 | sysfs_attach_dirent(sd, parent->d_fsdata, dentry); |
240 | d_rehash(dentry); | ||
241 | 249 | ||
242 | *p_dentry = dentry; | 250 | *p_dentry = dentry; |
243 | error = 0; | 251 | error = 0; |
@@ -308,42 +316,28 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) | |||
308 | init = init_file; | 316 | init = init_file; |
309 | } | 317 | } |
310 | 318 | ||
311 | dentry->d_fsdata = sysfs_get(sd); | 319 | error = sysfs_create(sd, dentry, |
312 | /* protect sd->s_dentry against sysfs_d_iput */ | 320 | (attr->mode & S_IALLUGO) | S_IFREG, init); |
313 | spin_lock(&sysfs_lock); | 321 | if (error) |
314 | sd->s_dentry = dentry; | ||
315 | spin_unlock(&sysfs_lock); | ||
316 | error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); | ||
317 | if (error) { | ||
318 | sysfs_put(sd); | ||
319 | return error; | 322 | return error; |
320 | } | ||
321 | 323 | ||
322 | if (bin_attr) { | 324 | if (bin_attr) { |
323 | dentry->d_inode->i_size = bin_attr->size; | 325 | dentry->d_inode->i_size = bin_attr->size; |
324 | dentry->d_inode->i_fop = &bin_fops; | 326 | dentry->d_inode->i_fop = &bin_fops; |
325 | } | 327 | } |
326 | dentry->d_op = &sysfs_dentry_ops; | 328 | |
327 | d_rehash(dentry); | 329 | sysfs_attach_dentry(sd, dentry); |
328 | 330 | ||
329 | return 0; | 331 | return 0; |
330 | } | 332 | } |
331 | 333 | ||
332 | static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) | 334 | static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) |
333 | { | 335 | { |
334 | int err = 0; | 336 | int err; |
335 | 337 | ||
336 | dentry->d_fsdata = sysfs_get(sd); | 338 | err = sysfs_create(sd, dentry, S_IFLNK|S_IRWXUGO, init_symlink); |
337 | /* protect sd->s_dentry against sysfs_d_iput */ | 339 | if (!err) |
338 | spin_lock(&sysfs_lock); | 340 | sysfs_attach_dentry(sd, dentry); |
339 | sd->s_dentry = dentry; | ||
340 | spin_unlock(&sysfs_lock); | ||
341 | err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); | ||
342 | if (!err) { | ||
343 | dentry->d_op = &sysfs_dentry_ops; | ||
344 | d_rehash(dentry); | ||
345 | } else | ||
346 | sysfs_put(sd); | ||
347 | 341 | ||
348 | return err; | 342 | return err; |
349 | } | 343 | } |
@@ -773,7 +767,6 @@ struct dentry *sysfs_create_shadow_dir(struct kobject *kobj) | |||
773 | d_instantiate(shadow, igrab(inode)); | 767 | d_instantiate(shadow, igrab(inode)); |
774 | inc_nlink(inode); | 768 | inc_nlink(inode); |
775 | inc_nlink(parent->d_inode); | 769 | inc_nlink(parent->d_inode); |
776 | shadow->d_op = &sysfs_dentry_ops; | ||
777 | 770 | ||
778 | dget(shadow); /* Extra count - pin the dentry in core */ | 771 | dget(shadow); /* Extra count - pin the dentry in core */ |
779 | 772 | ||
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index d9ccc830b73a..88857a399d0c 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -156,13 +156,13 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) | |||
156 | return inode; | 156 | return inode; |
157 | } | 157 | } |
158 | 158 | ||
159 | int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *)) | 159 | int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry, int mode, |
160 | int (*init)(struct inode *)) | ||
160 | { | 161 | { |
161 | int error = 0; | 162 | int error = 0; |
162 | struct inode * inode = NULL; | 163 | struct inode * inode = NULL; |
163 | if (dentry) { | 164 | if (dentry) { |
164 | if (!dentry->d_inode) { | 165 | if (!dentry->d_inode) { |
165 | struct sysfs_dirent * sd = dentry->d_fsdata; | ||
166 | if ((inode = sysfs_new_inode(mode, sd))) { | 166 | if ((inode = sysfs_new_inode(mode, sd))) { |
167 | if (dentry->d_parent && dentry->d_parent->d_inode) { | 167 | if (dentry->d_parent && dentry->d_parent->d_inode) { |
168 | struct inode *p_inode = dentry->d_parent->d_inode; | 168 | struct inode *p_inode = dentry->d_parent->d_inode; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 8b09e9d882c2..9fa77d648aa5 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -58,7 +58,8 @@ extern struct kmem_cache *sysfs_dir_cachep; | |||
58 | 58 | ||
59 | extern void sysfs_delete_inode(struct inode *inode); | 59 | extern void sysfs_delete_inode(struct inode *inode); |
60 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); | 60 | extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *); |
61 | extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); | 61 | extern int sysfs_create(struct sysfs_dirent *sd, struct dentry *dentry, |
62 | int mode, int (*init)(struct inode *)); | ||
62 | 63 | ||
63 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); | 64 | extern void release_sysfs_dirent(struct sysfs_dirent * sd); |
64 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); | 65 | extern int sysfs_dirent_exist(struct sysfs_dirent *, const unsigned char *); |