diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-13 07:52:33 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-11-13 08:08:19 -0500 |
commit | 441a9d0e1e827e6433e3487145fbb0c5513301e2 (patch) | |
tree | 853602df86aeb2b95d955e40edddce774aed52b0 /drivers/infiniband/hw | |
parent | ede4cebce16f5643c61aedd6d88d9070a1d23a68 (diff) |
qib_fs: fix (some) dcache abuses
* lookup_one_len() really wants i_mutex held on directory.
* leaks galore - just mount ipathfs, then
cd /sys/bus/pci/drivers/qib_ib; echo *:*:*.* >unbind
on a box with that card present and try to umount ipathfs...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_fs.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index f247fc6e6182..c61e2a92b3c1 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c | |||
@@ -456,13 +456,13 @@ static int remove_file(struct dentry *parent, char *name) | |||
456 | 456 | ||
457 | spin_lock(&tmp->d_lock); | 457 | spin_lock(&tmp->d_lock); |
458 | if (!(d_unhashed(tmp) && tmp->d_inode)) { | 458 | if (!(d_unhashed(tmp) && tmp->d_inode)) { |
459 | dget_dlock(tmp); | ||
460 | __d_drop(tmp); | 459 | __d_drop(tmp); |
461 | spin_unlock(&tmp->d_lock); | 460 | spin_unlock(&tmp->d_lock); |
462 | simple_unlink(parent->d_inode, tmp); | 461 | simple_unlink(parent->d_inode, tmp); |
463 | } else { | 462 | } else { |
464 | spin_unlock(&tmp->d_lock); | 463 | spin_unlock(&tmp->d_lock); |
465 | } | 464 | } |
465 | dput(tmp); | ||
466 | 466 | ||
467 | ret = 0; | 467 | ret = 0; |
468 | bail: | 468 | bail: |
@@ -491,6 +491,7 @@ static int remove_device_files(struct super_block *sb, | |||
491 | goto bail; | 491 | goto bail; |
492 | } | 492 | } |
493 | 493 | ||
494 | mutex_lock(&dir->d_inode->i_mutex); | ||
494 | remove_file(dir, "counters"); | 495 | remove_file(dir, "counters"); |
495 | remove_file(dir, "counter_names"); | 496 | remove_file(dir, "counter_names"); |
496 | remove_file(dir, "portcounter_names"); | 497 | remove_file(dir, "portcounter_names"); |
@@ -505,8 +506,10 @@ static int remove_device_files(struct super_block *sb, | |||
505 | } | 506 | } |
506 | } | 507 | } |
507 | remove_file(dir, "flash"); | 508 | remove_file(dir, "flash"); |
508 | d_delete(dir); | 509 | mutex_unlock(&dir->d_inode->i_mutex); |
509 | ret = simple_rmdir(root->d_inode, dir); | 510 | ret = simple_rmdir(root->d_inode, dir); |
511 | d_delete(dir); | ||
512 | dput(dir); | ||
510 | 513 | ||
511 | bail: | 514 | bail: |
512 | mutex_unlock(&root->d_inode->i_mutex); | 515 | mutex_unlock(&root->d_inode->i_mutex); |