diff options
Diffstat (limited to 'fs/configfs/symlink.c')
-rw-r--r-- | fs/configfs/symlink.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c index 2a731ef5f305..0004d18c40ac 100644 --- a/fs/configfs/symlink.c +++ b/fs/configfs/symlink.c | |||
@@ -77,12 +77,15 @@ static int create_link(struct config_item *parent_item, | |||
77 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); | 77 | sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL); |
78 | if (sl) { | 78 | if (sl) { |
79 | sl->sl_target = config_item_get(item); | 79 | sl->sl_target = config_item_get(item); |
80 | /* FIXME: needs a lock, I'd bet */ | 80 | spin_lock(&configfs_dirent_lock); |
81 | list_add(&sl->sl_list, &target_sd->s_links); | 81 | list_add(&sl->sl_list, &target_sd->s_links); |
82 | spin_unlock(&configfs_dirent_lock); | ||
82 | ret = configfs_create_link(sl, parent_item->ci_dentry, | 83 | ret = configfs_create_link(sl, parent_item->ci_dentry, |
83 | dentry); | 84 | dentry); |
84 | if (ret) { | 85 | if (ret) { |
86 | spin_lock(&configfs_dirent_lock); | ||
85 | list_del_init(&sl->sl_list); | 87 | list_del_init(&sl->sl_list); |
88 | spin_unlock(&configfs_dirent_lock); | ||
86 | config_item_put(item); | 89 | config_item_put(item); |
87 | kfree(sl); | 90 | kfree(sl); |
88 | } | 91 | } |
@@ -137,8 +140,12 @@ int configfs_symlink(struct inode *dir, struct dentry *dentry, const char *symna | |||
137 | goto out_put; | 140 | goto out_put; |
138 | 141 | ||
139 | ret = type->ct_item_ops->allow_link(parent_item, target_item); | 142 | ret = type->ct_item_ops->allow_link(parent_item, target_item); |
140 | if (!ret) | 143 | if (!ret) { |
141 | ret = create_link(parent_item, target_item, dentry); | 144 | ret = create_link(parent_item, target_item, dentry); |
145 | if (ret && type->ct_item_ops->drop_link) | ||
146 | type->ct_item_ops->drop_link(parent_item, | ||
147 | target_item); | ||
148 | } | ||
142 | 149 | ||
143 | config_item_put(target_item); | 150 | config_item_put(target_item); |
144 | path_put(&nd.path); | 151 | path_put(&nd.path); |
@@ -169,7 +176,9 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry) | |||
169 | parent_item = configfs_get_config_item(dentry->d_parent); | 176 | parent_item = configfs_get_config_item(dentry->d_parent); |
170 | type = parent_item->ci_type; | 177 | type = parent_item->ci_type; |
171 | 178 | ||
179 | spin_lock(&configfs_dirent_lock); | ||
172 | list_del_init(&sd->s_sibling); | 180 | list_del_init(&sd->s_sibling); |
181 | spin_unlock(&configfs_dirent_lock); | ||
173 | configfs_drop_dentry(sd, dentry->d_parent); | 182 | configfs_drop_dentry(sd, dentry->d_parent); |
174 | dput(dentry); | 183 | dput(dentry); |
175 | configfs_put(sd); | 184 | configfs_put(sd); |
@@ -184,8 +193,9 @@ int configfs_unlink(struct inode *dir, struct dentry *dentry) | |||
184 | type->ct_item_ops->drop_link(parent_item, | 193 | type->ct_item_ops->drop_link(parent_item, |
185 | sl->sl_target); | 194 | sl->sl_target); |
186 | 195 | ||
187 | /* FIXME: Needs lock */ | 196 | spin_lock(&configfs_dirent_lock); |
188 | list_del_init(&sl->sl_list); | 197 | list_del_init(&sl->sl_list); |
198 | spin_unlock(&configfs_dirent_lock); | ||
189 | 199 | ||
190 | /* Put reference from create_link() */ | 200 | /* Put reference from create_link() */ |
191 | config_item_put(sl->sl_target); | 201 | config_item_put(sl->sl_target); |