aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/configfs/dir.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 4522e0755773..e081acbac2e7 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry,
56 struct configfs_dirent *sd = dentry->d_fsdata; 56 struct configfs_dirent *sd = dentry->d_fsdata;
57 57
58 if (sd) { 58 if (sd) {
59 BUG_ON(sd->s_dentry != dentry);
60 /* Coordinate with configfs_readdir */ 59 /* Coordinate with configfs_readdir */
61 spin_lock(&configfs_dirent_lock); 60 spin_lock(&configfs_dirent_lock);
62 sd->s_dentry = NULL; 61 /* Coordinate with configfs_attach_attr where will increase
62 * sd->s_count and update sd->s_dentry to new allocated one.
63 * Only set sd->dentry to null when this dentry is the only
64 * sd owner.
65 * If not do so, configfs_d_iput may run just after
66 * configfs_attach_attr and set sd->s_dentry to null
67 * even it's still in use.
68 */
69 if (atomic_read(&sd->s_count) <= 2)
70 sd->s_dentry = NULL;
71
63 spin_unlock(&configfs_dirent_lock); 72 spin_unlock(&configfs_dirent_lock);
64 configfs_put(sd); 73 configfs_put(sd);
65 } 74 }
@@ -416,8 +425,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
416 struct configfs_attribute * attr = sd->s_element; 425 struct configfs_attribute * attr = sd->s_element;
417 int error; 426 int error;
418 427
428 spin_lock(&configfs_dirent_lock);
419 dentry->d_fsdata = configfs_get(sd); 429 dentry->d_fsdata = configfs_get(sd);
420 sd->s_dentry = dentry; 430 sd->s_dentry = dentry;
431 spin_unlock(&configfs_dirent_lock);
432
421 error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, 433 error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
422 configfs_init_file); 434 configfs_init_file);
423 if (error) { 435 if (error) {