aboutsummaryrefslogtreecommitdiffstats
path: root/fs/minix/bitmap.c
diff options
context:
space:
mode:
authorAndries Brouwer <aeb@cwi.nl>2007-02-12 03:52:49 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:31 -0500
commit939b00df0306bc4b5cd25c3c3c78e89b91e72fc8 (patch)
treec251dca9f3ebbebfa1f40f39716423842b247742 /fs/minix/bitmap.c
parentb587b13a4f670ebae79ae6259cf44328455e4e69 (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.c69
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
51void minix_free_block(struct inode * inode, int block) 51void 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)
79int minix_new_block(struct inode * inode) 80int 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
186void minix_free_inode(struct inode * inode) 190void 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;