aboutsummaryrefslogtreecommitdiffstats
path: root/fs/direct-io.c
diff options
context:
space:
mode:
authorZach Brown <zach.brown@oracle.com>2007-07-03 15:28:55 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-03 18:23:23 -0700
commitfcb82f8835c1d71b4fe5de1d9894f45370f80dab (patch)
treecdb5f78ff1d41d511b01a04f3f20f7ea248adb20 /fs/direct-io.c
parent5dcccd8d7eae870d85c3f175fd0823d3da07d0e3 (diff)
downloadkernel_samsung_smdk4412-fcb82f8835c1d71b4fe5de1d9894f45370f80dab.zip
kernel_samsung_smdk4412-fcb82f8835c1d71b4fe5de1d9894f45370f80dab.tar.gz
kernel_samsung_smdk4412-fcb82f8835c1d71b4fe5de1d9894f45370f80dab.tar.bz2
dio: remove bogus refcounting BUG_ON
Badari Pulavarty reported a case of this BUG_ON is triggering during testing. It's completely bogus and should be removed. It's trying to notice if we left references to the dio hanging around in the sync case. They should have been dropped as IO completed while this path was in dio_await_completion(). This condition will also be checked, via some twisty logic, by the BUG_ON(ret != -EIOCBQUEUED) a few lines lower. So to start this BUG_ON() is redundant. More fatally, it's dereferencing dio-> after having dropped its reference. It's only safe to dereference the dio after releasing the lock if the final reference was just dropped. Another CPU might free the dio in bio completion and reuse the memory after this path drops the dio lock but before the BUG_ON() is evaluated. This patch passed aio+dio regression unit tests and aio-stress on ext3. Signed-off-by: Zach Brown <zach.brown@oracle.com> Cc: Badari Pulavarty <pbadari@us.ibm.com> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/direct-io.c')
-rw-r--r--fs/direct-io.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 8593f3d..52bb263 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -1106,7 +1106,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode,
spin_lock_irqsave(&dio->bio_lock, flags);
ret2 = --dio->refcount;
spin_unlock_irqrestore(&dio->bio_lock, flags);
- BUG_ON(!dio->is_async && ret2 != 0);
+
if (ret2 == 0) {
ret = dio_complete(dio, offset, ret);
kfree(dio);