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 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)
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 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
368static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode) 368static 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
376static const struct dentry_operations sysfs_dentry_ops = { 373const 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
382struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) 379struct 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
776static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry, 773static 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;
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;