Linux 2.2.0
[davej-history.git] / fs / affs / bitmap.c
blob718a73970fb6d47e883959207d22fe3f663cd2c1
1 /*
2 * linux/fs/affs/bitmap.c
4 * (c) 1996 Hans-Joachim Widmaier
6 * bitmap.c contains the code that handles all bitmap related stuff -
7 * block allocation, deallocation, calculation of free space.
8 */
10 #define DEBUG 0
11 #include <linux/sched.h>
12 #include <linux/affs_fs.h>
13 #include <linux/stat.h>
14 #include <linux/kernel.h>
15 #include <linux/string.h>
16 #include <linux/locks.h>
17 #include <linux/amigaffs.h>
19 #include <asm/bitops.h>
21 /* This is, of course, shamelessly stolen from fs/minix */
23 static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
25 int
26 affs_count_free_bits(int blocksize, const char *data)
28 int free;
29 int i;
31 free = 0;
32 for (i = 0; i < blocksize; i++) {
33 free += nibblemap[data[i] & 0xF] + nibblemap[(data[i]>>4) & 0xF];
36 return free;
39 int
40 affs_count_free_blocks(struct super_block *s)
42 int free;
43 int i;
45 pr_debug("AFFS: count_free_blocks()\n");
47 free = 0;
48 if (s->u.affs_sb.s_flags & SF_BM_VALID) {
49 for (i = 0; i < s->u.affs_sb.s_num_az; i++) {
50 free += s->u.affs_sb.s_alloc[i].az_free;
53 return free;
56 void
57 affs_free_block(struct super_block *sb, s32 block)
59 int bmap;
60 int bit;
61 int blk;
62 int zone_no;
63 struct affs_bm_info *bm;
65 pr_debug("AFFS: free_block(%d)\n",block);
67 blk = block - sb->u.affs_sb.s_reserved;
68 bmap = blk / (sb->s_blocksize * 8 - 32);
69 bit = blk % (sb->s_blocksize * 8 - 32);
70 zone_no = (bmap << (sb->s_blocksize_bits - 7)) + bit / 1024;
71 bm = &sb->u.affs_sb.s_bitmap[bmap];
72 if (bmap >= sb->u.affs_sb.s_bm_count) {
73 affs_error(sb,"affs_free_block","Block %d outside partition",block);
74 return;
76 blk = 0;
77 set_bit(bit & 31,&blk);
79 lock_super(sb);
80 bm->bm_count++;
81 if (!bm->bm_bh) {
82 bm->bm_bh = affs_bread(sb->s_dev,bm->bm_key,sb->s_blocksize);
83 if (!bm->bm_bh) {
84 bm->bm_count--;
85 unlock_super(sb);
86 affs_error(sb,"affs_free_block","Cannot read bitmap block %d",bm->bm_key);
87 return;
90 if (test_and_set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4))
91 affs_warning(sb,"affs_free_block","Trying to free block %d which is already free",
92 block);
93 else {
94 sb->u.affs_sb.s_alloc[zone_no].az_free++;
95 ((u32 *)bm->bm_bh->b_data)[0] = cpu_to_be32(be32_to_cpu(((u32 *)bm->bm_bh->b_data)[0]) - blk);
96 mark_buffer_dirty(bm->bm_bh,1);
97 sb->s_dirt = 1;
99 if (--bm->bm_count == 0) {
100 affs_brelse(bm->bm_bh);
101 bm->bm_bh = NULL;
103 unlock_super(sb);
107 * Allocate a block in the given allocation zone.
108 * Since we have to byte-swap the bitmap on little-endian
109 * machines, this is rather expensive. Therefor we will
110 * preallocate up to 16 blocks from the same word, if
111 * possible. We are not doing preallocations in the
112 * header zone, though.
115 static s32
116 affs_balloc(struct inode *inode, int zone_no)
118 u32 w;
119 u32 *bm;
120 int fb;
121 int i;
122 int fwb;
123 s32 block;
124 struct affs_zone *zone;
125 struct affs_alloc_zone *az;
126 struct super_block *sb;
128 sb = inode->i_sb;
129 zone = &sb->u.affs_sb.s_zones[zone_no];
131 if (!zone->z_bm || !zone->z_bm->bm_bh)
132 return 0;
134 pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no);
136 az = &sb->u.affs_sb.s_alloc[zone->z_az_no];
137 bm = (u32 *)zone->z_bm->bm_bh->b_data;
138 repeat:
139 for (i = zone->z_start; i < zone->z_end; i++) {
140 if (bm[i])
141 goto found;
143 return 0;
145 found:
146 fwb = zone->z_bm->bm_firstblk + (i - 1) * 32;
147 lock_super(sb);
148 zone->z_start = i;
149 w = ~be32_to_cpu(bm[i]);
150 fb = find_first_zero_bit(&w,32);
151 if (fb > 31 || !test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) {
152 unlock_super(sb);
153 affs_warning(sb,"balloc","Empty block disappeared somehow");
154 goto repeat;
156 block = fwb + fb;
157 az->az_free--;
159 /* prealloc as much as possible within this word, but not in header zone */
161 if (zone_no) {
162 while (inode->u.affs_i.i_pa_cnt < AFFS_MAX_PREALLOC && ++fb < 32) {
163 fb = find_next_zero_bit(&w,32,fb);
164 if (fb > 31)
165 break;
166 if (!test_and_clear_bit(fb ^ BO_EXBITS,&bm[i])) {
167 affs_warning(sb,"balloc","Empty block disappeared somehow");
168 break;
170 inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb;
171 inode->u.affs_i.i_pa_last &= AFFS_MAX_PREALLOC - 1;
172 inode->u.affs_i.i_pa_cnt++;
173 az->az_free--;
176 w = ~w - be32_to_cpu(bm[i]);
177 bm[0] = cpu_to_be32(be32_to_cpu(bm[0]) + w);
178 unlock_super(sb);
179 mark_buffer_dirty(zone->z_bm->bm_bh,1);
180 sb->s_dirt = 1;
181 zone->z_lru_time = jiffies;
183 return block;
186 /* Find a new allocation zone, starting at zone_no. */
188 static int
189 affs_find_new_zone(struct super_block *sb, int zone_no)
191 struct affs_bm_info *bm;
192 struct affs_zone *zone;
193 struct affs_alloc_zone *az;
194 int bestfree;
195 int bestno;
196 int bestused;
197 int lusers;
198 int i;
199 int min;
201 pr_debug("AFFS: find_new_zone(zone_no=%d)\n",zone_no);
203 bestfree = 0;
204 bestused = -1;
205 bestno = -1;
206 lusers = MAX_ZONES;
207 min = zone_no ? AFFS_DATA_MIN_FREE : AFFS_HDR_MIN_FREE;
208 lock_super(sb);
209 zone = &sb->u.affs_sb.s_zones[zone_no];
210 i = zone->z_az_no;
211 az = &sb->u.affs_sb.s_alloc[i];
212 if (zone->z_bm && zone->z_bm->bm_count) {
213 if (--zone->z_bm->bm_count == 0) {
214 affs_brelse(zone->z_bm->bm_bh);
215 zone->z_bm->bm_bh = NULL;
217 if (az->az_count)
218 az->az_count--;
219 else
220 affs_error(sb,"find_new_zone","az_count=0, but bm used");
223 while (1) {
224 az = &sb->u.affs_sb.s_alloc[i];
225 if (!az->az_count) {
226 if (az->az_free > min) {
227 break;
229 if (az->az_free > bestfree) {
230 bestfree = az->az_free;
231 bestno = i;
233 } else if (az->az_free && az->az_count < lusers) {
234 lusers = az->az_count;
235 bestused = i;
237 if (++i >= sb->u.affs_sb.s_num_az)
238 i = 0;
239 if (i == zone->z_az_no) { /* Seen all */
240 if (bestno >= 0) {
241 i = bestno;
242 } else {
243 i = bestused;
245 break;
248 if (i < 0) {
249 /* Didn't find a single free block anywhere. */
250 unlock_super(sb);
251 return 0;
253 az = &sb->u.affs_sb.s_alloc[i];
254 az->az_count++;
255 bm = &sb->u.affs_sb.s_bitmap[i >> (sb->s_blocksize_bits - 7)];
256 bm->bm_count++;
257 if (!bm->bm_bh)
258 bm->bm_bh = affs_bread(sb->s_dev,bm->bm_key,sb->s_blocksize);
259 if (!bm->bm_bh) {
260 bm->bm_count--;
261 az->az_count--;
262 unlock_super(sb);
263 affs_error(sb,"find_new_zone","Cannot read bitmap");
264 return 0;
266 zone->z_bm = bm;
267 zone->z_start = (i & ((sb->s_blocksize / 128) - 1)) * 32 + 1;
268 zone->z_end = zone->z_start + az->az_size;
269 zone->z_az_no = i;
270 zone->z_lru_time = jiffies;
271 pr_debug("AFFS: found zone (%d) in bm %d at lw offset %d with %d free blocks\n",
272 i,(i >> (sb->s_blocksize_bits - 7)),zone->z_start,az->az_free);
273 unlock_super(sb);
274 return az->az_free;
277 /* Allocate a new header block. */
280 affs_new_header(struct inode *inode)
282 s32 block;
283 struct buffer_head *bh;
285 pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino);
287 if (!(block = affs_balloc(inode,0))) {
288 while (affs_find_new_zone(inode->i_sb,0)) {
289 if ((block = affs_balloc(inode,0)))
290 goto init_block;
291 schedule();
293 return 0;
295 init_block:
296 if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
297 affs_error(inode->i_sb,"new_header","Cannot get block %d",block);
298 return 0;
300 memset(bh->b_data,0,AFFS_I2BSIZE(inode));
301 mark_buffer_uptodate(bh,1);
302 mark_buffer_dirty(bh,1);
303 affs_brelse(bh);
305 return block;
308 /* Allocate a new data block. */
311 affs_new_data(struct inode *inode)
313 int empty, old;
314 unsigned long oldest;
315 struct affs_zone *zone;
316 struct super_block *sb;
317 struct buffer_head *bh;
318 int i = 0;
319 s32 block;
321 pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino);
323 sb = inode->i_sb;
324 lock_super(sb);
325 if (inode->u.affs_i.i_pa_cnt) {
326 inode->u.affs_i.i_pa_cnt--;
327 unlock_super(sb);
328 block = inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++];
329 inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1;
330 goto init_block;
332 unlock_super(sb);
333 oldest = jiffies;
334 old = 0;
335 empty = 0;
336 zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
337 if (zone->z_ino == inode->i_ino) {
338 i = inode->u.affs_i.i_zone;
339 goto found;
341 for (i = 1; i < MAX_ZONES; i++) {
342 zone = &sb->u.affs_sb.s_zones[i];
343 if (!empty && zone->z_bm && !zone->z_ino)
344 empty = i;
345 if (zone->z_bm && zone->z_lru_time < oldest) {
346 old = i;
347 oldest = zone->z_lru_time;
350 if (empty)
351 i = empty;
352 else if (old)
353 i = old;
354 else {
355 inode->u.affs_i.i_zone = 0;
356 return affs_new_header(inode);
359 inode->u.affs_i.i_zone = i;
360 zone->z_ino = inode->i_ino;
362 found:
363 zone = &sb->u.affs_sb.s_zones[i];
364 if (!(block = affs_balloc(inode,i))) { /* No data zones left */
365 while (affs_find_new_zone(sb,i)) {
366 if ((block = affs_balloc(inode,i)))
367 goto init_block;
368 schedule();
370 inode->u.affs_i.i_zone = 0;
371 zone->z_ino = -1;
372 return 0;
375 init_block:
376 if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) {
377 affs_error(inode->i_sb,"new_data","Cannot get block %d",block);
378 return 0;
380 memset(bh->b_data,0,sb->s_blocksize);
381 mark_buffer_uptodate(bh,1);
382 mark_buffer_dirty(bh,1);
383 affs_brelse(bh);
385 return block;
388 void
389 affs_make_zones(struct super_block *sb)
391 int i, mid;
393 pr_debug("AFFS: make_zones(): num_zones=%d\n",sb->u.affs_sb.s_num_az);
395 mid = (sb->u.affs_sb.s_num_az + 1) / 2;
396 for (i = 0; i < MAX_ZONES; i++) {
397 sb->u.affs_sb.s_zones[i].z_az_no = mid;
398 affs_find_new_zone(sb,i);