OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [bitmap.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/affs/bitmap.c
3
 *
4
 *  (c) 1996 Hans-Joachim Widmaier
5
 *
6
 *
7
 *  bitmap.c contains the code that handles all bitmap related stuff -
8
 *  block allocation, deallocation, calculation of free space.
9
 */
10
 
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>
18
 
19
#include <asm/bitops.h>
20
 
21
/* This is, of course, shamelessly stolen from fs/minix */
22
 
23
static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
24
 
25
int
26
affs_count_free_bits(int blocksize, const char *data)
27
{
28
  int    free;
29
  int    i;
30
 
31
  free = 0;
32
  for (i = 0; i < blocksize; i++) {
33
    free  += nibblemap[data[i] & 0xF] + nibblemap[(data[i]>>4) & 0xF];
34
  }
35
 
36
  return free;
37
}
38
 
39
int
40
affs_count_free_blocks(struct super_block *s)
41
{
42
        int      free;
43
        int      i;
44
 
45
        pr_debug("AFFS: count_free_blocks()\n");
46
 
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;
51
                }
52
        }
53
        return free;
54
}
55
 
56
void
57
affs_free_block(struct super_block *sb, int block)
58
{
59
        int                      bmap;
60
        int                      bit;
61
        int                      blk;
62
        int                      zone_no;
63
        struct affs_bm_info     *bm;
64
 
65
        pr_debug("AFFS: free_block(%d)\n",block);
66
 
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
                printk("AFFS: free_block(): block %d outside partition.\n",block);
74
                return;
75
        }
76
        blk = 0;
77
        set_bit(bit & 31,&blk);
78
 
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
                        printk("AFFS: free_block(): Cannot read bitmap block %d\n",bm->bm_key);
87
                        return;
88
                }
89
        }
90
        if (set_bit(bit ^ BO_EXBITS,bm->bm_bh->b_data + 4))
91
                printk("AFFS: free_block(): block %d is already free.\n",block);
92
        else {
93
                sb->u.affs_sb.s_alloc[zone_no].az_free++;
94
                ((__u32 *)bm->bm_bh->b_data)[0] = ntohl(htonl(((__u32 *)bm->bm_bh->b_data)[0]) - blk);
95
                mark_buffer_dirty(bm->bm_bh,1);
96
                sb->s_dirt = 1;
97
        }
98
        if (--bm->bm_count == 0) {
99
                affs_brelse(bm->bm_bh);
100
                bm->bm_bh = NULL;
101
        }
102
        unlock_super(sb);
103
}
104
 
105
static int
106
affs_balloc(struct inode *inode, int zone_no)
107
{
108
        __u32                    w;
109
        __u32                   *bm;
110
        int                      fb;
111
        int                      i;
112
        int                      fwb;
113
        int                      block;
114
        struct affs_zone        *zone;
115
        struct affs_alloc_zone  *az;
116
        struct super_block      *sb;
117
 
118
        sb   = inode->i_sb;
119
        zone = &sb->u.affs_sb.s_zones[zone_no];
120
 
121
        if (!zone->z_bm || !zone->z_bm->bm_bh)
122
                return 0;
123
 
124
        pr_debug("AFFS: balloc(inode=%lu,zone=%d)\n",inode->i_ino,zone_no);
125
 
126
        az = &sb->u.affs_sb.s_alloc[zone->z_az_no];
127
        bm = (__u32 *)zone->z_bm->bm_bh->b_data;
128
repeat:
129
        for (i = zone->z_start; i < zone->z_end; i++) {
130
                if (bm[i])
131
                        goto found;
132
        }
133
        return 0;
134
 
135
found:
136
        fwb = zone->z_bm->bm_firstblk + (i - 1) * 32;
137
        lock_super(sb);
138
        zone->z_start = i;
139
        w   = ~htonl(bm[i]);
140
        fb  = find_first_zero_bit(&w,32);
141
        if (fb > 31 || !clear_bit(fb ^ BO_EXBITS,&bm[i])) {
142
                unlock_super(sb);
143
                printk("AFFS: balloc(): empty block disappeared somehow\n");
144
                goto repeat;
145
        }
146
        block = fwb + fb;
147
        az->az_free--;
148
 
149
        /* prealloc as much as possible within this word, but not in header zone */
150
 
151
        if (zone_no) {
152
                while (inode->u.affs_i.i_pa_cnt < MAX_PREALLOC && ++fb < 32) {
153
                        fb = find_next_zero_bit(&w,32,fb);
154
                        if (fb > 31)
155
                                break;
156
                        if (!clear_bit(fb ^ BO_EXBITS,&bm[i])) {
157
                                printk("AFFS: balloc(): empty block disappeared\n");
158
                                break;
159
                        }
160
                        inode->u.affs_i.i_data[inode->u.affs_i.i_pa_last++] = fwb + fb;
161
                        inode->u.affs_i.i_pa_last &= MAX_PREALLOC - 1;
162
                        inode->u.affs_i.i_pa_cnt++;
163
                        az->az_free--;
164
                }
165
        }
166
        w     = ~w - htonl(bm[i]);
167
        bm[0] = ntohl(htonl(bm[0]) + w);
168
        unlock_super(sb);
169
        mark_buffer_dirty(zone->z_bm->bm_bh,1);
170
        zone->z_lru_time = jiffies;
171
 
172
        return block;
173
}
174
 
175
static int
176
affs_find_new_zone(struct super_block *sb, int zone_no)
177
{
178
        struct affs_bm_info     *bm;
179
        struct affs_zone        *zone;
180
        struct affs_alloc_zone  *az;
181
        int                      bestfree;
182
        int                      bestno;
183
        int                      bestused;
184
        int                      lusers;
185
        int                      i;
186
        int                      min;
187
 
188
        pr_debug("AFFS: find_new_zone(zone_no=%d)\n",zone_no);
189
 
190
        bestfree = 0;
191
        bestused = -1;
192
        bestno   = -1;
193
        lusers   = MAX_ZONES;
194
        min      = zone_no ? AFFS_DATA_MIN_FREE : AFFS_HDR_MIN_FREE;
195
        lock_super(sb);
196
        zone = &sb->u.affs_sb.s_zones[zone_no];
197
        i    = zone->z_az_no;
198
        az   = &sb->u.affs_sb.s_alloc[i];
199
        if (zone->z_bm && zone->z_bm->bm_count) {
200
                if (--zone->z_bm->bm_count == 0) {
201
                        affs_brelse(zone->z_bm->bm_bh);
202
                        zone->z_bm->bm_bh = NULL;
203
                }
204
                if (az->az_count)
205
                        az->az_count--;
206
                else
207
                        printk("AFFS: find_new_zone(): az_count=0, but bm used\n");
208
 
209
        }
210
        while (1) {
211
                if (i >= sb->u.affs_sb.s_num_az)
212
                        i = 0;
213
                az = &sb->u.affs_sb.s_alloc[i];
214
                if (!az->az_count) {
215
                        if (az->az_free > min) {
216
                                break;
217
                        }
218
                        if (az->az_free > bestfree) {
219
                                bestfree = az->az_free;
220
                                bestno   = i;
221
                        }
222
                } else if (az->az_free && az->az_count < lusers) {
223
                        lusers   = az->az_count;
224
                        bestused = i;
225
                }
226
                if (++i == zone->z_az_no) {             /* Seen all */
227
                        if (bestno >= 0) {
228
                                i = bestno;
229
                        } else {
230
                                i = bestused;
231
                        }
232
                        break;
233
                }
234
        }
235
        if (i < 0) {
236
                /* Didn't find a single free block anywhere. */
237
                unlock_super(sb);
238
                return 0;
239
        }
240
        az = &sb->u.affs_sb.s_alloc[i];
241
        az->az_count++;
242
        bm = &sb->u.affs_sb.s_bitmap[i >> (sb->s_blocksize_bits - 7)];
243
        bm->bm_count++;
244
        if (!bm->bm_bh)
245
                bm->bm_bh = affs_bread(sb->s_dev,bm->bm_key,sb->s_blocksize);
246
        if (!bm->bm_bh) {
247
                bm->bm_count--;
248
                az->az_count--;
249
                unlock_super(sb);
250
                printk("AFFS: find_new_zone(): Cannot read bitmap\n");
251
                return 0;
252
        }
253
        zone->z_bm    = bm;
254
        zone->z_start = (i & ((sb->s_blocksize / 128) - 1)) * 32 + 1;
255
        zone->z_end   = zone->z_start + az->az_size;
256
        zone->z_az_no = i;
257
        zone->z_lru_time = jiffies;
258
        pr_debug("  ++ found zone (%d) in bm %d at lw offset %d with %d free blocks\n",
259
                 i,(i >> (sb->s_blocksize_bits - 7)),zone->z_start,az->az_free);
260
        unlock_super(sb);
261
        return az->az_free;
262
}
263
 
264
int
265
affs_new_header(struct inode *inode)
266
{
267
        int                      block;
268
        struct buffer_head      *bh;
269
 
270
        pr_debug("AFFS: new_header(ino=%lu)\n",inode->i_ino);
271
 
272
        if (!(block = affs_balloc(inode,0))) {
273
                while(affs_find_new_zone(inode->i_sb,0)) {
274
                        if ((block = affs_balloc(inode,0)))
275
                                goto init_block;
276
                        schedule();
277
                }
278
                return 0;
279
        }
280
init_block:
281
        if (!(bh = getblk(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
282
                printk("AFFS: balloc(): cannot read block %d\n",block);
283
                return 0;
284
        }
285
        memset(bh->b_data,0,AFFS_I2BSIZE(inode));
286
        mark_buffer_uptodate(bh,1);
287
        mark_buffer_dirty(bh,1);
288
        affs_brelse(bh);
289
 
290
        return block;
291
}
292
 
293
int
294
affs_new_data(struct inode *inode)
295
{
296
        int                      empty, old;
297
        unsigned long            oldest;
298
        struct affs_zone        *zone;
299
        struct super_block      *sb;
300
        struct buffer_head      *bh;
301
        int                      i = 0;
302
        int                      block;
303
 
304
        pr_debug("AFFS: new_data(ino=%lu)\n",inode->i_ino);
305
 
306
        sb = inode->i_sb;
307
        lock_super(sb);
308
        if (inode->u.affs_i.i_pa_cnt) {
309
                inode->u.affs_i.i_pa_cnt--;
310
                unlock_super(sb);
311
                block = inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++];
312
                inode->u.affs_i.i_pa_next &= MAX_PREALLOC - 1;
313
                goto init_block;
314
        }
315
        unlock_super(sb);
316
        oldest = jiffies;
317
        old    = 0;
318
        empty  = 0;
319
        zone   = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
320
        if (zone->z_ino == inode->i_ino) {
321
                i = inode->u.affs_i.i_zone;
322
                goto found;
323
        }
324
        for (i = 1; i < MAX_ZONES; i++) {
325
                zone = &sb->u.affs_sb.s_zones[i];
326
                if (!empty && zone->z_bm && !zone->z_ino)
327
                        empty = i;
328
                if (zone->z_bm && zone->z_lru_time < oldest) {
329
                        old    = i;
330
                        oldest = zone->z_lru_time;
331
                }
332
        }
333
        if (empty)
334
                i = empty;
335
        else if (old)
336
                i = old;
337
        else {
338
                inode->u.affs_i.i_zone = 0;
339
                return affs_new_header(inode);
340
        }
341
 
342
        inode->u.affs_i.i_zone = i;
343
        zone->z_ino            = inode->i_ino;
344
 
345
found:
346
        zone = &sb->u.affs_sb.s_zones[i];
347
        if (!(block = affs_balloc(inode,i))) {          /* No data zones left */
348
                while(affs_find_new_zone(sb,i)) {
349
                        if ((block = affs_balloc(inode,i)))
350
                                goto init_block;
351
                        schedule();
352
                }
353
                inode->u.affs_i.i_zone = 0;
354
                zone->z_ino            = -1;
355
                return 0;
356
        }
357
 
358
init_block:
359
        if (!(bh = getblk(inode->i_dev,block,sb->s_blocksize))) {
360
                printk("AFFS: balloc(): cannot read block %u\n",block);
361
                return 0;
362
        }
363
        memset(bh->b_data,0,sb->s_blocksize);
364
        mark_buffer_uptodate(bh,1);
365
        mark_buffer_dirty(bh,1);
366
        affs_brelse(bh);
367
 
368
        return block;
369
}
370
 
371
void
372
affs_make_zones(struct super_block *sb)
373
{
374
        int      i, mid;
375
 
376
        pr_debug("AFFS: make_zones(): num_zones=%d\n",sb->u.affs_sb.s_num_az);
377
 
378
        mid = (sb->u.affs_sb.s_num_az + 1) / 2;
379
        sb->u.affs_sb.s_zones[0].z_az_no = mid;
380
        affs_find_new_zone(sb,0);
381
        for (i = 1; i < MAX_ZONES; i++) {
382
                sb->u.affs_sb.s_zones[i].z_az_no = mid;
383
                affs_find_new_zone(sb,i);
384
        }
385
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.