aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hpfs/buffer.c
diff options
context:
space:
mode:
authorMikulas Patocka <mikulas@twibright.com>2015-09-02 16:50:12 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-03 14:55:30 -0400
commita64eefaac1c5cc8dbc6995228fe08a61b8e1d26b (patch)
tree0945e739dbe805c12f5d24170ae8486f6df79a43 /fs/hpfs/buffer.c
parent64291f7db5bd8150a74ad2036f1037e6a0428df2 (diff)
hpfs: support hotfixes
When the OS/2 driver hits a disk write error, it writes the sector to another location and adds the sector mapping to the hotfix map. This patch makes the hpfs driver understand the hotfix map and remap accesses accoring to it. Signed-off-by: Mikulas Patocka <mikulas@twibright.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/hpfs/buffer.c')
-rw-r--r--fs/hpfs/buffer.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
index 8057fe4e6574..f626114449e4 100644
--- a/fs/hpfs/buffer.c
+++ b/fs/hpfs/buffer.c
@@ -10,6 +10,30 @@
10#include <linux/blkdev.h> 10#include <linux/blkdev.h>
11#include "hpfs_fn.h" 11#include "hpfs_fn.h"
12 12
13secno hpfs_search_hotfix_map(struct super_block *s, secno sec)
14{
15 unsigned i;
16 struct hpfs_sb_info *sbi = hpfs_sb(s);
17 for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
18 if (sbi->hotfix_from[i] == sec) {
19 return sbi->hotfix_to[i];
20 }
21 }
22 return sec;
23}
24
25unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n)
26{
27 unsigned i;
28 struct hpfs_sb_info *sbi = hpfs_sb(s);
29 for (i = 0; unlikely(i < sbi->n_hotfixes); i++) {
30 if (sbi->hotfix_from[i] >= sec && sbi->hotfix_from[i] < sec + n) {
31 n = sbi->hotfix_from[i] - sec;
32 }
33 }
34 return n;
35}
36
13void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n) 37void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
14{ 38{
15 struct buffer_head *bh; 39 struct buffer_head *bh;
@@ -18,6 +42,9 @@ void hpfs_prefetch_sectors(struct super_block *s, unsigned secno, int n)
18 if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size)) 42 if (n <= 0 || unlikely(secno >= hpfs_sb(s)->sb_fs_size))
19 return; 43 return;
20 44
45 if (unlikely(hpfs_search_hotfix_map_for_range(s, secno, n) != n))
46 return;
47
21 bh = sb_find_get_block(s, secno); 48 bh = sb_find_get_block(s, secno);
22 if (bh) { 49 if (bh) {
23 if (buffer_uptodate(bh)) { 50 if (buffer_uptodate(bh)) {
@@ -51,7 +78,7 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
51 78
52 cond_resched(); 79 cond_resched();
53 80
54 *bhp = bh = sb_bread(s, secno); 81 *bhp = bh = sb_bread(s, hpfs_search_hotfix_map(s, secno));
55 if (bh != NULL) 82 if (bh != NULL)
56 return bh->b_data; 83 return bh->b_data;
57 else { 84 else {
@@ -71,7 +98,7 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
71 98
72 cond_resched(); 99 cond_resched();
73 100
74 if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { 101 if ((*bhp = bh = sb_getblk(s, hpfs_search_hotfix_map(s, secno))) != NULL) {
75 if (!buffer_uptodate(bh)) wait_on_buffer(bh); 102 if (!buffer_uptodate(bh)) wait_on_buffer(bh);
76 set_buffer_uptodate(bh); 103 set_buffer_uptodate(bh);
77 return bh->b_data; 104 return bh->b_data;
@@ -99,10 +126,10 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
99 126
100 hpfs_prefetch_sectors(s, secno, 4 + ahead); 127 hpfs_prefetch_sectors(s, secno, 4 + ahead);
101 128
102 if (!(qbh->bh[0] = sb_bread(s, secno + 0))) goto bail0; 129 if (!hpfs_map_sector(s, secno + 0, &qbh->bh[0], 0)) goto bail0;
103 if (!(qbh->bh[1] = sb_bread(s, secno + 1))) goto bail1; 130 if (!hpfs_map_sector(s, secno + 1, &qbh->bh[1], 0)) goto bail1;
104 if (!(qbh->bh[2] = sb_bread(s, secno + 2))) goto bail2; 131 if (!hpfs_map_sector(s, secno + 2, &qbh->bh[2], 0)) goto bail2;
105 if (!(qbh->bh[3] = sb_bread(s, secno + 3))) goto bail3; 132 if (!hpfs_map_sector(s, secno + 3, &qbh->bh[3], 0)) goto bail3;
106 133
107 if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) && 134 if (likely(qbh->bh[1]->b_data == qbh->bh[0]->b_data + 1 * 512) &&
108 likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) && 135 likely(qbh->bh[2]->b_data == qbh->bh[0]->b_data + 2 * 512) &&