aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/dir.c31
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/sysfs.h1
3 files changed, 13 insertions, 23 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;
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 52c3bdb66a84..71eb7e253927 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -68,6 +68,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
68 } 68 }
69 root->d_fsdata = &sysfs_root; 69 root->d_fsdata = &sysfs_root;
70 sb->s_root = root; 70 sb->s_root = root;
71 sb->s_d_op = &sysfs_dentry_ops;
71 return 0; 72 return 0;
72} 73}
73 74
@@ -117,13 +118,12 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
117 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) 118 for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
118 info->ns[type] = kobj_ns_grab_current(type); 119 info->ns[type] = kobj_ns_grab_current(type);
119 120
120 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); 121 sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
121 if (IS_ERR(sb) || sb->s_fs_info != info) 122 if (IS_ERR(sb) || sb->s_fs_info != info)
122 free_sysfs_super_info(info); 123 free_sysfs_super_info(info);
123 if (IS_ERR(sb)) 124 if (IS_ERR(sb))
124 return ERR_CAST(sb); 125 return ERR_CAST(sb);
125 if (!sb->s_root) { 126 if (!sb->s_root) {
126 sb->s_flags = flags;
127 error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); 127 error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
128 if (error) { 128 if (error) {
129 deactivate_locked_super(sb); 129 deactivate_locked_super(sb);
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 661a9639570b..d73c0932bbd6 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -157,6 +157,7 @@ extern struct kmem_cache *sysfs_dir_cachep;
157 */ 157 */
158extern struct mutex sysfs_mutex; 158extern struct mutex sysfs_mutex;
159extern spinlock_t sysfs_assoc_lock; 159extern spinlock_t sysfs_assoc_lock;
160extern const struct dentry_operations sysfs_dentry_ops;
160 161
161extern const struct file_operations sysfs_dir_operations; 162extern const struct file_operations sysfs_dir_operations;
162extern const struct inode_operations sysfs_dir_inode_operations; 163extern const struct inode_operations sysfs_dir_inode_operations;