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 e6bb9b2a4cbe..a5cf784f9cc2 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -300,15 +300,15 @@ 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 | 310 | ||
311 | if (nd->flags & LOOKUP_RCU) | 311 | if (flags & LOOKUP_RCU) |
312 | return -ECHILD; | 312 | return -ECHILD; |
313 | 313 | ||
314 | sd = dentry->d_fsdata; | 314 | sd = dentry->d_fsdata; |
@@ -355,18 +355,15 @@ out_bad: | |||
355 | return 0; | 355 | return 0; |
356 | } | 356 | } |
357 | 357 | ||
358 | static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 358 | static void sysfs_dentry_release(struct dentry *dentry) |
359 | { | 359 | { |
360 | struct sysfs_dirent * sd = dentry->d_fsdata; | 360 | sysfs_put(dentry->d_fsdata); |
361 | |||
362 | sysfs_put(sd); | ||
363 | iput(inode); | ||
364 | } | 361 | } |
365 | 362 | ||
366 | static const struct dentry_operations sysfs_dentry_ops = { | 363 | const struct dentry_operations sysfs_dentry_ops = { |
367 | .d_revalidate = sysfs_dentry_revalidate, | 364 | .d_revalidate = sysfs_dentry_revalidate, |
368 | .d_delete = sysfs_dentry_delete, | 365 | .d_delete = sysfs_dentry_delete, |
369 | .d_iput = sysfs_dentry_iput, | 366 | .d_release = sysfs_dentry_release, |
370 | }; | 367 | }; |
371 | 368 | ||
372 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) | 369 | struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) |
@@ -764,7 +761,7 @@ int sysfs_create_dir(struct kobject * kobj) | |||
764 | } | 761 | } |
765 | 762 | ||
766 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | 763 | static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, |
767 | struct nameidata *nd) | 764 | unsigned int flags) |
768 | { | 765 | { |
769 | struct dentry *ret = NULL; | 766 | struct dentry *ret = NULL; |
770 | struct dentry *parent = dentry->d_parent; | 767 | struct dentry *parent = dentry->d_parent; |
@@ -786,6 +783,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
786 | ret = ERR_PTR(-ENOENT); | 783 | ret = ERR_PTR(-ENOENT); |
787 | goto out_unlock; | 784 | goto out_unlock; |
788 | } | 785 | } |
786 | dentry->d_fsdata = sysfs_get(sd); | ||
789 | 787 | ||
790 | /* attach dentry and inode */ | 788 | /* attach dentry and inode */ |
791 | inode = sysfs_get_inode(dir->i_sb, sd); | 789 | inode = sysfs_get_inode(dir->i_sb, sd); |
@@ -795,16 +793,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, | |||
795 | } | 793 | } |
796 | 794 | ||
797 | /* instantiate and hash dentry */ | 795 | /* instantiate and hash dentry */ |
798 | ret = d_find_alias(inode); | 796 | ret = d_materialise_unique(dentry, inode); |
799 | if (!ret) { | ||
800 | d_set_d_op(dentry, &sysfs_dentry_ops); | ||
801 | dentry->d_fsdata = sysfs_get(sd); | ||
802 | d_add(dentry, inode); | ||
803 | } else { | ||
804 | d_move(ret, dentry); | ||
805 | iput(inode); | ||
806 | } | ||
807 | |||
808 | out_unlock: | 797 | out_unlock: |
809 | mutex_unlock(&sysfs_mutex); | 798 | mutex_unlock(&sysfs_mutex); |
810 | return ret; | 799 | return ret; |