diff options
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/dir.c | 31 | ||||
-rw-r--r-- | fs/sysfs/mount.c | 4 | ||||
-rw-r--r-- | fs/sysfs/sysfs.h | 1 |
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) | |||
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; |
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 | */ |
158 | extern struct mutex sysfs_mutex; | 158 | extern struct mutex sysfs_mutex; |
159 | extern spinlock_t sysfs_assoc_lock; | 159 | extern spinlock_t sysfs_assoc_lock; |
160 | extern const struct dentry_operations sysfs_dentry_ops; | ||
160 | 161 | ||
161 | extern const struct file_operations sysfs_dir_operations; | 162 | extern const struct file_operations sysfs_dir_operations; |
162 | extern const struct inode_operations sysfs_dir_inode_operations; | 163 | extern const struct inode_operations sysfs_dir_inode_operations; |