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 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; |
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; |