aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2008-07-02 15:30:15 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-07-26 20:53:05 -0400
commitd70b67c8bc72ee23b55381bd6a884f4796692f77 (patch)
treec15055c81f21b7863318e1e6f8a9620afaeb3327 /fs
parenta048d3aff8b828b6c0fa7ddd90a531248ab4e0f9 (diff)
[patch] vfs: fix lookup on deleted directory
Lookup can install a child dentry for a deleted directory. This keeps the directory dentry alive, and the inode pinned in the cache and on disk, even after all external references have gone away. This isn't a big problem normally, since memory pressure or umount will clear out the directory dentry and its children, releasing the inode. But for UBIFS this causes problems because its orphan area can overflow. Fix this by returning ENOENT for all lookups on a S_DEAD directory before creating a child dentry. Thanks to Zoltan Sogor for noticing this while testing UBIFS, and Artem for the excellent analysis of the problem and testing. Reported-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 01e67dddcc3d..3b26a240ade9 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -519,7 +519,14 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
519 */ 519 */
520 result = d_lookup(parent, name); 520 result = d_lookup(parent, name);
521 if (!result) { 521 if (!result) {
522 struct dentry * dentry = d_alloc(parent, name); 522 struct dentry *dentry;
523
524 /* Don't create child dentry for a dead directory. */
525 result = ERR_PTR(-ENOENT);
526 if (IS_DEADDIR(dir))
527 goto out_unlock;
528
529 dentry = d_alloc(parent, name);
523 result = ERR_PTR(-ENOMEM); 530 result = ERR_PTR(-ENOMEM);
524 if (dentry) { 531 if (dentry) {
525 result = dir->i_op->lookup(dir, dentry, nd); 532 result = dir->i_op->lookup(dir, dentry, nd);
@@ -528,6 +535,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
528 else 535 else
529 result = dentry; 536 result = dentry;
530 } 537 }
538out_unlock:
531 mutex_unlock(&dir->i_mutex); 539 mutex_unlock(&dir->i_mutex);
532 return result; 540 return result;
533 } 541 }
@@ -1317,7 +1325,14 @@ static struct dentry *__lookup_hash(struct qstr *name,
1317 1325
1318 dentry = cached_lookup(base, name, nd); 1326 dentry = cached_lookup(base, name, nd);
1319 if (!dentry) { 1327 if (!dentry) {
1320 struct dentry *new = d_alloc(base, name); 1328 struct dentry *new;
1329
1330 /* Don't create child dentry for a dead directory. */
1331 dentry = ERR_PTR(-ENOENT);
1332 if (IS_DEADDIR(inode))
1333 goto out;
1334
1335 new = d_alloc(base, name);
1321 dentry = ERR_PTR(-ENOMEM); 1336 dentry = ERR_PTR(-ENOMEM);
1322 if (!new) 1337 if (!new)
1323 goto out; 1338 goto out;