diff options
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r-- | fs/sysfs/dir.c | 31 |
1 files changed, 10 insertions, 21 deletions
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 1cdfb53199aa..6b0bb00d4d2b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -300,16 +300,16 @@ void release_sysfs_dirent(struct sysfs_dirent * sd) | |||
300 | static int sysfs_dentry_delete(const struct dentry *dentry) | 300 | static int sysfs_dentry_delete(const struct dentry *dentry) |
301 | { | 301 | { |
302 | struct sysfs_dirent *sd = dentry->d_fsdata; | 302 | struct sysfs_dirent *sd = dentry->d_fsdata; |
303 | return !!(sd->s_flags & SYSFS_FLAG_REMOVED); | 303 | return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED)); |
304 | } | 304 | } |
305 | 305 | ||
306 | static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) | 306 | static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags) |
307 | { | 307 | { |
308 | struct sysfs_dirent *sd; | 308 | struct sysfs_dirent *sd; |
309 | int is_dir; | 309 | int is_dir; |
310 | int type; | 310 | int type; |
311 | 311 | ||
312 | if (nd->flags & LOOKUP_RCU) | 312 | if (flags & LOOKUP_RCU) |
313 | return -ECHILD; | 313 | return -ECHILD; |
314 | 314 | ||
315 | sd = dentry->d_fsdata; | 315 | sd = dentry->d_fsdata; |
@@ -365,18 +365,15 @@ out_bad: | |||
365 | return 0; | 365 | return 0; |
366 | } | 366 | } |
367 | 367 | ||
368 | static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 368 | static void sysfs_dentry_release(struct dentry *dentry) |
369 | { | 369 | { |
370 | struct sysfs_dirent * sd = dentry->d_fsdata; | 370 | sysfs_put(dentry->d_fsdata); |
371 | |||
372 | sysfs_put(sd); | ||
373 | iput(inode); | ||
374 | } | 371 | } |
375 | 372 | ||
376 | static const struct dentry_operations sysfs_dentry_ops = { | 373 | const struct dentry_operations sysfs_dentry_ops = { |
377 | .d_revalidate = sysfs_dentry_revalidate, | 374 | .d_revalidate = sysfs_dentry_revalidate, |
378 | .d_delete = sysfs_dentry_delete, | 375 | .d_delete = sysfs_dentry_delete, |
379 | .d_iput = sysfs_dentry_iput, | 376 | .d_release = sysfs_dentry_release, |
380 | }; | 377 | }; |
381 | 378 | ||
382 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | 379 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
@@ -774,7 +771,7 @@ int sysfs_create_dir(struct kobject * kobj) | |||
774 | } | 771 | } |
775 | 772 | ||
776 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | 773 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, |
777 | struct nameidata *nd) | 774 | unsigned int flags) |
778 | { | 775 | { |
779 | struct dentry *ret = NULL; | 776 | struct dentry *ret = NULL; |
780 | struct dentry *parent = dentry->d_parent; | 777 | struct dentry *parent = dentry->d_parent; |
@@ -796,6 +793,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
796 | ret = ERR_PTR(-ENOENT); | 793 | ret = ERR_PTR(-ENOENT); |
797 | goto out_unlock; | 794 | goto out_unlock; |
798 | } | 795 | } |
796 | dentry->d_fsdata = sysfs_get(sd); | ||
799 | 797 | ||
800 | /* attach dentry and inode */ | 798 | /* attach dentry and inode */ |
801 | inode = sysfs_get_inode(dir->i_sb, sd); | 799 | inode = sysfs_get_inode(dir->i_sb, sd); |
@@ -805,16 +803,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
805 | } | 803 | } |
806 | 804 | ||
807 | /* instantiate and hash dentry */ | 805 | /* instantiate and hash dentry */ |
808 | ret = d_find_alias(inode); | 806 | ret = d_materialise_unique(dentry, inode); |
809 | if (!ret) { | ||
810 | d_set_d_op(dentry, &sysfs_dentry_ops); | ||
811 | dentry->d_fsdata = sysfs_get(sd); | ||
812 | d_add(dentry, inode); | ||
813 | } else { | ||
814 | d_move(ret, dentry); | ||
815 | iput(inode); | ||
816 | } | ||
817 | |||
818 | out_unlock: | 807 | out_unlock: |
819 | mutex_unlock(&sysfs_mutex); | 808 | mutex_unlock(&sysfs_mutex); |
820 | return ret; | 809 | return ret; |