Commit 31fc3053 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] blkdev_put() data corruption

	We used to have sync_blockdev() on each normal (== non-raw)
blkdev_put() + kill_bdev() on the final blkdev_put().  That worked
fine until we'd moved sync_blockdev() to the final blkdev_put().

	Now we have a nasty scenario:

open block device
open raw device
write on block device	# data ends up in cache
close block device	# no sync here, we still have the sucker opened
close raw device	# no sync here either
			# ... and cache is killed by kill_bdev()

	IOW, if we postpone sync to final close, we must do it regardless of
kind of close.  Otherwise we are in for data corruption and yes, it is easy
to trigger.  Fix is obvious...
parent d6c561ce
...@@ -697,12 +697,7 @@ int blkdev_put(struct block_device *bdev, int kind) ...@@ -697,12 +697,7 @@ int blkdev_put(struct block_device *bdev, int kind)
down(&bdev->bd_sem); down(&bdev->bd_sem);
lock_kernel(); lock_kernel();
if (!--bdev->bd_openers) { if (!--bdev->bd_openers) {
switch (kind) {
case BDEV_FILE:
case BDEV_FS:
sync_blockdev(bdev); sync_blockdev(bdev);
break;
}
kill_bdev(bdev); kill_bdev(bdev);
} }
if (bdev->bd_contains == bdev) { if (bdev->bd_contains == bdev) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment