aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs/dir.c')
-rw-r--r--fs/sysfs/dir.c31
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)
300static int sysfs_dentry_delete(const struct dentry *dentry) 300static 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
306static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd) 306static 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
358static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) 358static 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
366static const struct dentry_operations sysfs_dentry_ops = { 363const 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
372struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 369struct 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
766static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 763static 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;