diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:21 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:17 -0500 |
commit | fbc8d4c04626e015b18cc61199f505920abb48f0 (patch) | |
tree | 31cd59dd54966d225ae159f41308798b2d58b8a2 /fs/configfs | |
parent | 5adcee1d8d32d7f305f6f5aaefdbf8f35adca177 (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>
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/dir.c | 17 |
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 | ||
499 | out: | 498 | out: |
@@ -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, |