aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hpfs
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
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')
-rw-r--r--fs/hpfs/buffer.c39
-rw-r--r--fs/hpfs/file.c9
-rw-r--r--fs/hpfs/hpfs_fn.h7
-rw-r--r--fs/hpfs/map.c26
-rw-r--r--fs/hpfs/super.c15
5 files changed, 76 insertions, 20 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) &&
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 7ca28d604bf7..d3bcdd975700 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -83,6 +83,11 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
83 if (s) { 83 if (s) {
84 if (bh_result->b_size >> 9 < n_secs) 84 if (bh_result->b_size >> 9 < n_secs)
85 n_secs = bh_result->b_size >> 9; 85 n_secs = bh_result->b_size >> 9;
86 n_secs = hpfs_search_hotfix_map_for_range(inode->i_sb, s, n_secs);
87 if (unlikely(!n_secs)) {
88 s = hpfs_search_hotfix_map(inode->i_sb, s);
89 n_secs = 1;
90 }
86 map_bh(bh_result, inode->i_sb, s); 91 map_bh(bh_result, inode->i_sb, s);
87 bh_result->b_size = n_secs << 9; 92 bh_result->b_size = n_secs << 9;
88 goto ret_0; 93 goto ret_0;
@@ -101,7 +106,7 @@ static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_he
101 inode->i_blocks++; 106 inode->i_blocks++;
102 hpfs_i(inode)->mmu_private += 512; 107 hpfs_i(inode)->mmu_private += 512;
103 set_buffer_new(bh_result); 108 set_buffer_new(bh_result);
104 map_bh(bh_result, inode->i_sb, s); 109 map_bh(bh_result, inode->i_sb, hpfs_search_hotfix_map(inode->i_sb, s));
105 ret_0: 110 ret_0:
106 r = 0; 111 r = 0;
107 ret_r: 112 ret_r:
@@ -181,7 +186,7 @@ static int hpfs_write_end(struct file *file, struct address_space *mapping,
181 186
182static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) 187static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block)
183{ 188{
184 return generic_block_bmap(mapping,block,hpfs_get_block); 189 return generic_block_bmap(mapping, block, hpfs_get_block);
185} 190}
186 191
187const struct address_space_operations hpfs_aops = { 192const struct address_space_operations hpfs_aops = {
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index c4867b5116dd..975654a63c13 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -88,6 +88,10 @@ struct hpfs_sb_info {
88 unsigned sb_max_fwd_alloc; /* max forwad allocation */ 88 unsigned sb_max_fwd_alloc; /* max forwad allocation */
89 int sb_timeshift; 89 int sb_timeshift;
90 struct rcu_head rcu; 90 struct rcu_head rcu;
91
92 unsigned n_hotfixes;
93 secno hotfix_from[256];
94 secno hotfix_to[256];
91}; 95};
92 96
93/* Four 512-byte buffers and the 2k block obtained by concatenating them */ 97/* Four 512-byte buffers and the 2k block obtained by concatenating them */
@@ -217,6 +221,8 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
217 221
218/* buffer.c */ 222/* buffer.c */
219 223
224secno hpfs_search_hotfix_map(struct super_block *s, secno sec);
225unsigned hpfs_search_hotfix_map_for_range(struct super_block *s, secno sec, unsigned n);
220void hpfs_prefetch_sectors(struct super_block *, unsigned, int); 226void hpfs_prefetch_sectors(struct super_block *, unsigned, int);
221void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); 227void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
222void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); 228void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
@@ -285,6 +291,7 @@ __le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head
285void hpfs_prefetch_bitmap(struct super_block *, unsigned); 291void hpfs_prefetch_bitmap(struct super_block *, unsigned);
286unsigned char *hpfs_load_code_page(struct super_block *, secno); 292unsigned char *hpfs_load_code_page(struct super_block *, secno);
287__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp); 293__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
294void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock);
288struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **); 295struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
289struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **); 296struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);
290struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *); 297struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c
index 442770edcdc7..a69bbc1e87f8 100644
--- a/fs/hpfs/map.c
+++ b/fs/hpfs/map.c
@@ -130,6 +130,32 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
130 return b; 130 return b;
131} 131}
132 132
133void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock)
134{
135 struct quad_buffer_head qbh;
136 u32 *directory;
137 u32 n_hotfixes, n_used_hotfixes;
138 unsigned i;
139
140 n_hotfixes = le32_to_cpu(spareblock->n_spares);
141 n_used_hotfixes = le32_to_cpu(spareblock->n_spares_used);
142
143 if (n_hotfixes > 256 || n_used_hotfixes > n_hotfixes) {
144 hpfs_error(s, "invalid number of hotfixes: %u, used: %u", n_hotfixes, n_used_hotfixes);
145 return;
146 }
147 if (!(directory = hpfs_map_4sectors(s, le32_to_cpu(spareblock->hotfix_map), &qbh, 0))) {
148 hpfs_error(s, "can't load hotfix map");
149 return;
150 }
151 for (i = 0; i < n_used_hotfixes; i++) {
152 hpfs_sb(s)->hotfix_from[i] = le32_to_cpu(directory[i]);
153 hpfs_sb(s)->hotfix_to[i] = le32_to_cpu(directory[n_hotfixes + i]);
154 }
155 hpfs_sb(s)->n_hotfixes = n_used_hotfixes;
156 hpfs_brelse4(&qbh);
157}
158
133/* 159/*
134 * Load fnode to memory 160 * Load fnode to memory
135 */ 161 */
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index 68a9bed05628..a561591896bd 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -628,6 +628,9 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
628 goto bail4; 628 goto bail4;
629 } 629 }
630 630
631 if (spareblock->n_spares_used)
632 hpfs_load_hotfix_map(s, spareblock);
633
631 /* Load bitmap directory */ 634 /* Load bitmap directory */
632 if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) 635 if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
633 goto bail4; 636 goto bail4;
@@ -647,18 +650,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
647 mark_buffer_dirty(bh2); 650 mark_buffer_dirty(bh2);
648 } 651 }
649 652
650 if (spareblock->hotfixes_used || spareblock->n_spares_used) {
651 if (errs >= 2) {
652 pr_err("Hotfixes not supported here, try chkdsk\n");
653 mark_dirty(s, 0);
654 goto bail4;
655 }
656 hpfs_error(s, "hotfixes not supported here, try chkdsk");
657 if (errs == 0)
658 pr_err("Proceeding, but your filesystem will be probably corrupted by this driver...\n");
659 else
660 pr_err("This driver may read bad files or crash when operating on disk with hotfixes.\n");
661 }
662 if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) { 653 if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
663 if (errs >= 2) { 654 if (errs >= 2) {
664 pr_err("Spare dnodes used, try chkdsk\n"); 655 pr_err("Spare dnodes used, try chkdsk\n");