diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2006-09-26 02:31:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:48 -0400 |
commit | 6ddab3b9ebebc88bfdd8107c64f12d7e4480c559 (patch) | |
tree | 192edd3a85d3665bb7e44c429609a7357ba12bac | |
parent | ca5f9703dffa012cc46166e6206c5a992910e041 (diff) |
[PATCH] mm: swap write failure fixup
Currently we can silently drop data if the write to swap failed. It
usually doesn't result in data-corruption because on page-in the process
will receive SIGBUS (assuming write-failure implies read-failure).
This assumption might or might not be valid.
This patch will avoid the page being discarded after a failed write. But
will print a warning the sysadmin _should_ take to heart, if a lot of swap
space becomes un-writeable, OOM is not far off.
Tested by making the write fail 'randomly' once every 50 writes or so.
[akpm@osdl.org: printk warning fix]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | mm/page_io.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/mm/page_io.c b/mm/page_io.c index 88029948d00a..d2f0a5783370 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
@@ -52,8 +52,23 @@ static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err) | |||
52 | if (bio->bi_size) | 52 | if (bio->bi_size) |
53 | return 1; | 53 | return 1; |
54 | 54 | ||
55 | if (!uptodate) | 55 | if (!uptodate) { |
56 | SetPageError(page); | 56 | SetPageError(page); |
57 | /* | ||
58 | * We failed to write the page out to swap-space. | ||
59 | * Re-dirty the page in order to avoid it being reclaimed. | ||
60 | * Also print a dire warning that things will go BAD (tm) | ||
61 | * very quickly. | ||
62 | * | ||
63 | * Also clear PG_reclaim to avoid rotate_reclaimable_page() | ||
64 | */ | ||
65 | set_page_dirty(page); | ||
66 | printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n", | ||
67 | imajor(bio->bi_bdev->bd_inode), | ||
68 | iminor(bio->bi_bdev->bd_inode), | ||
69 | (unsigned long long)bio->bi_sector); | ||
70 | ClearPageReclaim(page); | ||
71 | } | ||
57 | end_page_writeback(page); | 72 | end_page_writeback(page); |
58 | bio_put(bio); | 73 | bio_put(bio); |
59 | return 0; | 74 | return 0; |
@@ -70,6 +85,10 @@ static int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err) | |||
70 | if (!uptodate) { | 85 | if (!uptodate) { |
71 | SetPageError(page); | 86 | SetPageError(page); |
72 | ClearPageUptodate(page); | 87 | ClearPageUptodate(page); |
88 | printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n", | ||
89 | imajor(bio->bi_bdev->bd_inode), | ||
90 | iminor(bio->bi_bdev->bd_inode), | ||
91 | (unsigned long long)bio->bi_sector); | ||
73 | } else { | 92 | } else { |
74 | SetPageUptodate(page); | 93 | SetPageUptodate(page); |
75 | } | 94 | } |