aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeremy Kerr <jk@ozlabs.org>2007-06-04 09:26:51 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-06 21:44:39 -0400
commit877907d37da9694a34adc9dc3e2ce09400148cb5 (patch)
tree4cb8ffe949e3beeb3ccc0d58824a215e83e6f63c /arch
parentce92987baba60bc082b9eedddfaf4ae3f8435dac (diff)
[POWERPC] spufs: Fix gang destroy leaks
Previously, closing a SPE gang that still has contexts would trigger a WARN_ON, and leak the allocated gang. This change fixes the problem by using the gang's reference counts to destroy the gang instead. The gangs will persist until their last reference (be it context or open file handle) is gone. Also, avoid using statements with side-effects in a WARN_ON(). Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c40
1 files changed, 5 insertions, 35 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 01c4805986f2..fe960ddbde71 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -349,37 +349,6 @@ out:
349 return ret; 349 return ret;
350} 350}
351 351
352static int spufs_rmgang(struct inode *root, struct dentry *dir)
353{
354 /* FIXME: this fails if the dir is not empty,
355 which causes a leak of gangs. */
356 return simple_rmdir(root, dir);
357}
358
359static int spufs_gang_close(struct inode *inode, struct file *file)
360{
361 struct inode *parent;
362 struct dentry *dir;
363 int ret;
364
365 dir = file->f_path.dentry;
366 parent = dir->d_parent->d_inode;
367
368 ret = spufs_rmgang(parent, dir);
369 WARN_ON(ret);
370
371 return dcache_dir_close(inode, file);
372}
373
374const struct file_operations spufs_gang_fops = {
375 .open = dcache_dir_open,
376 .release = spufs_gang_close,
377 .llseek = dcache_dir_lseek,
378 .read = generic_read_dir,
379 .readdir = dcache_readdir,
380 .fsync = simple_sync_file,
381};
382
383static int 352static int
384spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) 353spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
385{ 354{
@@ -407,7 +376,6 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode)
407 inode->i_fop = &simple_dir_operations; 376 inode->i_fop = &simple_dir_operations;
408 377
409 d_instantiate(dentry, inode); 378 d_instantiate(dentry, inode);
410 dget(dentry);
411 dir->i_nlink++; 379 dir->i_nlink++;
412 dentry->d_inode->i_nlink++; 380 dentry->d_inode->i_nlink++;
413 return ret; 381 return ret;
@@ -437,7 +405,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
437 goto out; 405 goto out;
438 } 406 }
439 407
440 filp->f_op = &spufs_gang_fops; 408 filp->f_op = &simple_dir_operations;
441 fd_install(ret, filp); 409 fd_install(ret, filp);
442out: 410out:
443 return ret; 411 return ret;
@@ -458,8 +426,10 @@ static int spufs_create_gang(struct inode *inode,
458 * in error path of *_open(). 426 * in error path of *_open().
459 */ 427 */
460 ret = spufs_gang_open(dget(dentry), mntget(mnt)); 428 ret = spufs_gang_open(dget(dentry), mntget(mnt));
461 if (ret < 0) 429 if (ret < 0) {
462 WARN_ON(spufs_rmgang(inode, dentry)); 430 int err = simple_rmdir(inode, dentry);
431 WARN_ON(err);
432 }
463 433
464out: 434out:
465 mutex_unlock(&inode->i_mutex); 435 mutex_unlock(&inode->i_mutex);