|
@@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry,
|
|
|
struct configfs_dirent *sd = dentry->d_fsdata;
|
|
|
|
|
|
if (sd) {
|
|
|
- BUG_ON(sd->s_dentry != dentry);
|
|
|
/* Coordinate with configfs_readdir */
|
|
|
spin_lock(&configfs_dirent_lock);
|
|
|
- sd->s_dentry = NULL;
|
|
|
+ /* Coordinate with configfs_attach_attr where will increase
|
|
|
+ * sd->s_count and update sd->s_dentry to new allocated one.
|
|
|
+ * Only set sd->dentry to null when this dentry is the only
|
|
|
+ * sd owner.
|
|
|
+ * If not do so, configfs_d_iput may run just after
|
|
|
+ * configfs_attach_attr and set sd->s_dentry to null
|
|
|
+ * even it's still in use.
|
|
|
+ */
|
|
|
+ if (atomic_read(&sd->s_count) <= 2)
|
|
|
+ sd->s_dentry = NULL;
|
|
|
+
|
|
|
spin_unlock(&configfs_dirent_lock);
|
|
|
configfs_put(sd);
|
|
|
}
|
|
@@ -416,8 +425,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
|
|
|
struct configfs_attribute * attr = sd->s_element;
|
|
|
int error;
|
|
|
|
|
|
+ spin_lock(&configfs_dirent_lock);
|
|
|
dentry->d_fsdata = configfs_get(sd);
|
|
|
sd->s_dentry = dentry;
|
|
|
+ spin_unlock(&configfs_dirent_lock);
|
|
|
+
|
|
|
error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG,
|
|
|
configfs_init_file);
|
|
|
if (error) {
|