aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:21 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:17 -0500
commitfbc8d4c04626e015b18cc61199f505920abb48f0 (patch)
tree31cd59dd54966d225ae159f41308798b2d58b8a2
parent5adcee1d8d32d7f305f6f5aaefdbf8f35adca177 (diff)
config fs: avoid switching ->d_op on live dentry
Switching d_op on a live dentry is racy in general, so avoid it. In this case it is a negative dentry, which is safer, but there are still concurrent ops which may be called on d_op in that case (eg. d_revalidate). So in general a filesystem may not do this. Fix configfs so as not to do this. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r--fs/configfs/dir.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 0b502f80c691..578706969415 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -232,10 +232,8 @@ int configfs_make_dirent(struct configfs_dirent * parent_sd,
232 232
233 sd->s_mode = mode; 233 sd->s_mode = mode;
234 sd->s_dentry = dentry; 234 sd->s_dentry = dentry;
235 if (dentry) { 235 if (dentry)
236 dentry->d_fsdata = configfs_get(sd); 236 dentry->d_fsdata = configfs_get(sd);
237 dentry->d_op = &configfs_dentry_ops;
238 }
239 237
240 return 0; 238 return 0;
241} 239}
@@ -278,7 +276,6 @@ static int create_dir(struct config_item * k, struct dentry * p,
278 error = configfs_create(d, mode, init_dir); 276 error = configfs_create(d, mode, init_dir);
279 if (!error) { 277 if (!error) {
280 inc_nlink(p->d_inode); 278 inc_nlink(p->d_inode);
281 (d)->d_op = &configfs_dentry_ops;
282 } else { 279 } else {
283 struct configfs_dirent *sd = d->d_fsdata; 280 struct configfs_dirent *sd = d->d_fsdata;
284 if (sd) { 281 if (sd) {
@@ -371,9 +368,7 @@ int configfs_create_link(struct configfs_symlink *sl,
371 CONFIGFS_ITEM_LINK); 368 CONFIGFS_ITEM_LINK);
372 if (!err) { 369 if (!err) {
373 err = configfs_create(dentry, mode, init_symlink); 370 err = configfs_create(dentry, mode, init_symlink);
374 if (!err) 371 if (err) {
375 dentry->d_op = &configfs_dentry_ops;
376 else {
377 struct configfs_dirent *sd = dentry->d_fsdata; 372 struct configfs_dirent *sd = dentry->d_fsdata;
378 if (sd) { 373 if (sd) {
379 spin_lock(&configfs_dirent_lock); 374 spin_lock(&configfs_dirent_lock);
@@ -493,7 +488,11 @@ static struct dentry * configfs_lookup(struct inode *dir,
493 * If it doesn't exist and it isn't a NOT_PINNED item, 488 * If it doesn't exist and it isn't a NOT_PINNED item,
494 * it must be negative. 489 * it must be negative.
495 */ 490 */
496 return simple_lookup(dir, dentry, nd); 491 if (dentry->d_name.len > NAME_MAX)
492 return ERR_PTR(-ENAMETOOLONG);
493 dentry->d_op = &configfs_dentry_ops;
494 d_add(dentry, NULL);
495 return NULL;
497 } 496 }
498 497
499out: 498out:
@@ -685,6 +684,7 @@ static int create_default_group(struct config_group *parent_group,
685 ret = -ENOMEM; 684 ret = -ENOMEM;
686 child = d_alloc(parent, &name); 685 child = d_alloc(parent, &name);
687 if (child) { 686 if (child) {
687 child->d_op = &configfs_dentry_ops;
688 d_add(child, NULL); 688 d_add(child, NULL);
689 689
690 ret = configfs_attach_group(&parent_group->cg_item, 690 ret = configfs_attach_group(&parent_group->cg_item,
@@ -1682,6 +1682,7 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
1682 err = -ENOMEM; 1682 err = -ENOMEM;
1683 dentry = d_alloc(configfs_sb->s_root, &name); 1683 dentry = d_alloc(configfs_sb->s_root, &name);
1684 if (dentry) { 1684 if (dentry) {
1685 dentry->d_op = &configfs_dentry_ops;
1685 d_add(dentry, NULL); 1686 d_add(dentry, NULL);
1686 1687
1687 err = configfs_attach_group(sd->s_element, &group->cg_item, 1688 err = configfs_attach_group(sd->s_element, &group->cg_item,