From: Arnd Bergmann Date: Wed, 4 Jan 2006 19:31:27 +0000 (+0100) Subject: [PATCH] spufs: fix spufs_fill_dir error path X-Git-Tag: v2.6.16-rc1~666^2~18 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f51dd91c80746a5cf76f8c4a77bfc88aa82bb9e;p=linux-2.6 [PATCH] spufs: fix spufs_fill_dir error path If creating one entry failed in spufs_fill_dir, we never cleaned up the freshly created entries. Fix this by calling the cleanup function on error. Noticed by Al Viro. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d9a39fb63a..687f80d09f 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -134,47 +134,18 @@ spufs_delete_inode(struct inode *inode) clear_inode(inode); } -static int -spufs_fill_dir(struct dentry *dir, struct tree_descr *files, - int mode, struct spu_context *ctx) -{ - struct dentry *dentry; - int ret; - - while (files->name && files->name[0]) { - ret = -ENOMEM; - dentry = d_alloc_name(dir, files->name); - if (!dentry) - goto out; - ret = spufs_new_file(dir->d_sb, dentry, files->ops, - files->mode & mode, ctx); - if (ret) - goto out; - files++; - } - return 0; -out: - // FIXME: remove all files that are left - - return ret; -} - -static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) +static void spufs_prune_dir(struct dentry *dir) { struct dentry *dentry, *tmp; - struct spu_context *ctx; - - /* remove all entries */ - down(&root->i_sem); - down(&dir_dentry->d_inode->i_sem); - list_for_each_entry_safe(dentry, tmp, &dir_dentry->d_subdirs, d_child) { + down(&dir->d_inode->i_sem); + list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_child) { spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (!(d_unhashed(dentry)) && dentry->d_inode) { dget_locked(dentry); __d_drop(dentry); spin_unlock(&dentry->d_lock); - simple_unlink(dir_dentry->d_inode, dentry); + simple_unlink(dir->d_inode, dentry); spin_unlock(&dcache_lock); dput(dentry); } else { @@ -182,8 +153,17 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) spin_unlock(&dcache_lock); } } - shrink_dcache_parent(dir_dentry); - up(&dir_dentry->d_inode->i_sem); + shrink_dcache_parent(dir); + up(&dir->d_inode->i_sem); +} + +static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) +{ + struct spu_context *ctx; + + /* remove all entries */ + down(&root->i_sem); + spufs_prune_dir(dir_dentry); up(&root->i_sem); /* We have to give up the mm_struct */ @@ -194,6 +174,29 @@ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) return simple_rmdir(root, dir_dentry); } +static int spufs_fill_dir(struct dentry *dir, struct tree_descr *files, + int mode, struct spu_context *ctx) +{ + struct dentry *dentry; + int ret; + + while (files->name && files->name[0]) { + ret = -ENOMEM; + dentry = d_alloc_name(dir, files->name); + if (!dentry) + goto out; + ret = spufs_new_file(dir->d_sb, dentry, files->ops, + files->mode & mode, ctx); + if (ret) + goto out; + files++; + } + return 0; +out: + spufs_prune_dir(dir); + return ret; +} + static int spufs_dir_close(struct inode *inode, struct file *file) { struct inode *dir;