diff options
author | Jeremy Kerr <jk@ozlabs.org> | 2007-06-04 09:26:51 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-06 21:44:39 -0400 |
commit | 877907d37da9694a34adc9dc3e2ce09400148cb5 (patch) | |
tree | 4cb8ffe949e3beeb3ccc0d58824a215e83e6f63c /arch/powerpc | |
parent | ce92987baba60bc082b9eedddfaf4ae3f8435dac (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/powerpc')
-rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 40 |
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 | ||
352 | static 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 | |||
359 | static 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 | |||
374 | const 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 | |||
383 | static int | 352 | static int |
384 | spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) | 353 | spufs_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); |
442 | out: | 410 | out: |
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 | ||
464 | out: | 434 | out: |
465 | mutex_unlock(&inode->i_mutex); | 435 | mutex_unlock(&inode->i_mutex); |