diff options
author | Andries Brouwer <aeb@cwi.nl> | 2007-02-12 03:52:49 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:31 -0500 |
commit | 939b00df0306bc4b5cd25c3c3c78e89b91e72fc8 (patch) | |
tree | c251dca9f3ebbebfa1f40f39716423842b247742 /fs/minix/bitmap.c | |
parent | b587b13a4f670ebae79ae6259cf44328455e4e69 (diff) |
[PATCH] Minix V3 support
This morning I needed to read a Minix V3 filesystem, but unfortunately my
2.6.19 did not support that, and neither did the downloaded 2.6.20rc4.
Fortunately, google told me that Daniel Aragones had already done the work,
patch found at http://www.terra.es/personal2/danarag/
Unfortunaly, looking at the patch was painful to my eyes, so I polished it
a bit before applying. The resulting kernel boots, and reads the
filesystem it needed to read.
Signed-off-by: Daniel Aragones <danarag@gmail.com>
Signed-off-by: Andries Brouwer <aeb@cwi.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/minix/bitmap.c')
-rw-r--r-- | fs/minix/bitmap.c | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/fs/minix/bitmap.c b/fs/minix/bitmap.c index df6b1075b549..c4a554df7b7e 100644 --- a/fs/minix/bitmap.c +++ b/fs/minix/bitmap.c | |||
@@ -26,14 +26,14 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ | |||
26 | for (i=0; i<numblocks-1; i++) { | 26 | for (i=0; i<numblocks-1; i++) { |
27 | if (!(bh=map[i])) | 27 | if (!(bh=map[i])) |
28 | return(0); | 28 | return(0); |
29 | for (j=0; j<BLOCK_SIZE; j++) | 29 | for (j=0; j<bh->b_size; j++) |
30 | sum += nibblemap[bh->b_data[j] & 0xf] | 30 | sum += nibblemap[bh->b_data[j] & 0xf] |
31 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | 31 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; |
32 | } | 32 | } |
33 | 33 | ||
34 | if (numblocks==0 || !(bh=map[numblocks-1])) | 34 | if (numblocks==0 || !(bh=map[numblocks-1])) |
35 | return(0); | 35 | return(0); |
36 | i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2; | 36 | i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2; |
37 | for (j=0; j<i; j++) { | 37 | for (j=0; j<i; j++) { |
38 | sum += nibblemap[bh->b_data[j] & 0xf] | 38 | sum += nibblemap[bh->b_data[j] & 0xf] |
39 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; | 39 | + nibblemap[(bh->b_data[j]>>4) & 0xf]; |
@@ -48,28 +48,29 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _ | |||
48 | return(sum); | 48 | return(sum); |
49 | } | 49 | } |
50 | 50 | ||
51 | void minix_free_block(struct inode * inode, int block) | 51 | void minix_free_block(struct inode *inode, unsigned long block) |
52 | { | 52 | { |
53 | struct super_block * sb = inode->i_sb; | 53 | struct super_block *sb = inode->i_sb; |
54 | struct minix_sb_info * sbi = minix_sb(sb); | 54 | struct minix_sb_info *sbi = minix_sb(sb); |
55 | struct buffer_head * bh; | 55 | struct buffer_head *bh; |
56 | unsigned int bit,zone; | 56 | int k = sb->s_blocksize_bits + 3; |
57 | unsigned long bit, zone; | ||
57 | 58 | ||
58 | if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { | 59 | if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) { |
59 | printk("Trying to free block not in datazone\n"); | 60 | printk("Trying to free block not in datazone\n"); |
60 | return; | 61 | return; |
61 | } | 62 | } |
62 | zone = block - sbi->s_firstdatazone + 1; | 63 | zone = block - sbi->s_firstdatazone + 1; |
63 | bit = zone & 8191; | 64 | bit = zone & ((1<<k) - 1); |
64 | zone >>= 13; | 65 | zone >>= k; |
65 | if (zone >= sbi->s_zmap_blocks) { | 66 | if (zone >= sbi->s_zmap_blocks) { |
66 | printk("minix_free_block: nonexistent bitmap buffer\n"); | 67 | printk("minix_free_block: nonexistent bitmap buffer\n"); |
67 | return; | 68 | return; |
68 | } | 69 | } |
69 | bh = sbi->s_zmap[zone]; | 70 | bh = sbi->s_zmap[zone]; |
70 | lock_kernel(); | 71 | lock_kernel(); |
71 | if (!minix_test_and_clear_bit(bit,bh->b_data)) | 72 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
72 | printk("free_block (%s:%d): bit already cleared\n", | 73 | printk("minix_free_block (%s:%lu): bit already cleared\n", |
73 | sb->s_id, block); | 74 | sb->s_id, block); |
74 | unlock_kernel(); | 75 | unlock_kernel(); |
75 | mark_buffer_dirty(bh); | 76 | mark_buffer_dirty(bh); |
@@ -79,6 +80,7 @@ void minix_free_block(struct inode * inode, int block) | |||
79 | int minix_new_block(struct inode * inode) | 80 | int minix_new_block(struct inode * inode) |
80 | { | 81 | { |
81 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 82 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
83 | int bits_per_zone = 8 * inode->i_sb->s_blocksize; | ||
82 | int i; | 84 | int i; |
83 | 85 | ||
84 | for (i = 0; i < sbi->s_zmap_blocks; i++) { | 86 | for (i = 0; i < sbi->s_zmap_blocks; i++) { |
@@ -86,11 +88,12 @@ int minix_new_block(struct inode * inode) | |||
86 | int j; | 88 | int j; |
87 | 89 | ||
88 | lock_kernel(); | 90 | lock_kernel(); |
89 | if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) { | 91 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
90 | minix_set_bit(j,bh->b_data); | 92 | if (j < bits_per_zone) { |
93 | minix_set_bit(j, bh->b_data); | ||
91 | unlock_kernel(); | 94 | unlock_kernel(); |
92 | mark_buffer_dirty(bh); | 95 | mark_buffer_dirty(bh); |
93 | j += i*8192 + sbi->s_firstdatazone-1; | 96 | j += i * bits_per_zone + sbi->s_firstdatazone-1; |
94 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) | 97 | if (j < sbi->s_firstdatazone || j >= sbi->s_nzones) |
95 | break; | 98 | break; |
96 | return j; | 99 | return j; |
@@ -137,6 +140,7 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) | |||
137 | int block; | 140 | int block; |
138 | struct minix_sb_info *sbi = minix_sb(sb); | 141 | struct minix_sb_info *sbi = minix_sb(sb); |
139 | struct minix2_inode *p; | 142 | struct minix2_inode *p; |
143 | int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode); | ||
140 | 144 | ||
141 | *bh = NULL; | 145 | *bh = NULL; |
142 | if (!ino || ino > sbi->s_ninodes) { | 146 | if (!ino || ino > sbi->s_ninodes) { |
@@ -146,14 +150,14 @@ minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh) | |||
146 | } | 150 | } |
147 | ino--; | 151 | ino--; |
148 | block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks + | 152 | block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks + |
149 | ino / MINIX2_INODES_PER_BLOCK; | 153 | ino / minix2_inodes_per_block; |
150 | *bh = sb_bread(sb, block); | 154 | *bh = sb_bread(sb, block); |
151 | if (!*bh) { | 155 | if (!*bh) { |
152 | printk("Unable to read inode block\n"); | 156 | printk("Unable to read inode block\n"); |
153 | return NULL; | 157 | return NULL; |
154 | } | 158 | } |
155 | p = (void *)(*bh)->b_data; | 159 | p = (void *)(*bh)->b_data; |
156 | return p + ino % MINIX2_INODES_PER_BLOCK; | 160 | return p + ino % minix2_inodes_per_block; |
157 | } | 161 | } |
158 | 162 | ||
159 | /* Clear the link count and mode of a deleted inode on disk. */ | 163 | /* Clear the link count and mode of a deleted inode on disk. */ |
@@ -185,26 +189,30 @@ static void minix_clear_inode(struct inode *inode) | |||
185 | 189 | ||
186 | void minix_free_inode(struct inode * inode) | 190 | void minix_free_inode(struct inode * inode) |
187 | { | 191 | { |
192 | struct super_block *sb = inode->i_sb; | ||
188 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 193 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
189 | struct buffer_head * bh; | 194 | struct buffer_head *bh; |
190 | unsigned long ino; | 195 | int k = sb->s_blocksize_bits + 3; |
196 | unsigned long ino, bit; | ||
191 | 197 | ||
192 | ino = inode->i_ino; | 198 | ino = inode->i_ino; |
193 | if (ino < 1 || ino > sbi->s_ninodes) { | 199 | if (ino < 1 || ino > sbi->s_ninodes) { |
194 | printk("minix_free_inode: inode 0 or nonexistent inode\n"); | 200 | printk("minix_free_inode: inode 0 or nonexistent inode\n"); |
195 | goto out; | 201 | goto out; |
196 | } | 202 | } |
197 | if ((ino >> 13) >= sbi->s_imap_blocks) { | 203 | bit = ino & ((1<<k) - 1); |
204 | ino >>= k; | ||
205 | if (ino >= sbi->s_imap_blocks) { | ||
198 | printk("minix_free_inode: nonexistent imap in superblock\n"); | 206 | printk("minix_free_inode: nonexistent imap in superblock\n"); |
199 | goto out; | 207 | goto out; |
200 | } | 208 | } |
201 | 209 | ||
202 | minix_clear_inode(inode); /* clear on-disk copy */ | 210 | minix_clear_inode(inode); /* clear on-disk copy */ |
203 | 211 | ||
204 | bh = sbi->s_imap[ino >> 13]; | 212 | bh = sbi->s_imap[ino]; |
205 | lock_kernel(); | 213 | lock_kernel(); |
206 | if (!minix_test_and_clear_bit(ino & 8191, bh->b_data)) | 214 | if (!minix_test_and_clear_bit(bit, bh->b_data)) |
207 | printk("minix_free_inode: bit %lu already cleared\n", ino); | 215 | printk("minix_free_inode: bit %lu already cleared\n", bit); |
208 | unlock_kernel(); | 216 | unlock_kernel(); |
209 | mark_buffer_dirty(bh); | 217 | mark_buffer_dirty(bh); |
210 | out: | 218 | out: |
@@ -217,35 +225,38 @@ struct inode * minix_new_inode(const struct inode * dir, int * error) | |||
217 | struct minix_sb_info *sbi = minix_sb(sb); | 225 | struct minix_sb_info *sbi = minix_sb(sb); |
218 | struct inode *inode = new_inode(sb); | 226 | struct inode *inode = new_inode(sb); |
219 | struct buffer_head * bh; | 227 | struct buffer_head * bh; |
220 | int i,j; | 228 | int bits_per_zone = 8 * sb->s_blocksize; |
229 | unsigned long j; | ||
230 | int i; | ||
221 | 231 | ||
222 | if (!inode) { | 232 | if (!inode) { |
223 | *error = -ENOMEM; | 233 | *error = -ENOMEM; |
224 | return NULL; | 234 | return NULL; |
225 | } | 235 | } |
226 | j = 8192; | 236 | j = bits_per_zone; |
227 | bh = NULL; | 237 | bh = NULL; |
228 | *error = -ENOSPC; | 238 | *error = -ENOSPC; |
229 | lock_kernel(); | 239 | lock_kernel(); |
230 | for (i = 0; i < sbi->s_imap_blocks; i++) { | 240 | for (i = 0; i < sbi->s_imap_blocks; i++) { |
231 | bh = sbi->s_imap[i]; | 241 | bh = sbi->s_imap[i]; |
232 | if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192) | 242 | j = minix_find_first_zero_bit(bh->b_data, bits_per_zone); |
243 | if (j < bits_per_zone) | ||
233 | break; | 244 | break; |
234 | } | 245 | } |
235 | if (!bh || j >= 8192) { | 246 | if (!bh || j >= bits_per_zone) { |
236 | unlock_kernel(); | 247 | unlock_kernel(); |
237 | iput(inode); | 248 | iput(inode); |
238 | return NULL; | 249 | return NULL; |
239 | } | 250 | } |
240 | if (minix_test_and_set_bit(j,bh->b_data)) { /* shouldn't happen */ | 251 | if (minix_test_and_set_bit(j, bh->b_data)) { /* shouldn't happen */ |
241 | printk("new_inode: bit already set\n"); | ||
242 | unlock_kernel(); | 252 | unlock_kernel(); |
253 | printk("minix_new_inode: bit already set\n"); | ||
243 | iput(inode); | 254 | iput(inode); |
244 | return NULL; | 255 | return NULL; |
245 | } | 256 | } |
246 | unlock_kernel(); | 257 | unlock_kernel(); |
247 | mark_buffer_dirty(bh); | 258 | mark_buffer_dirty(bh); |
248 | j += i*8192; | 259 | j += i * bits_per_zone; |
249 | if (!j || j > sbi->s_ninodes) { | 260 | if (!j || j > sbi->s_ninodes) { |
250 | iput(inode); | 261 | iput(inode); |
251 | return NULL; | 262 | return NULL; |