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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [sysv/] [balloc.c] - Blame information for rev 1777

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

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/sysv/balloc.c
3
 *
4
 *  minix/bitmap.c
5
 *  Copyright (C) 1991, 1992  Linus Torvalds
6
 *
7
 *  ext/freelists.c
8
 *  Copyright (C) 1992  Remy Card (card@masi.ibp.fr)
9
 *
10
 *  xenix/alloc.c
11
 *  Copyright (C) 1992  Doug Evans
12
 *
13
 *  coh/alloc.c
14
 *  Copyright (C) 1993  Pascal Haible, Bruno Haible
15
 *
16
 *  sysv/balloc.c
17
 *  Copyright (C) 1993  Bruno Haible
18
 *
19
 *  This file contains code for allocating/freeing blocks.
20
 */
21
 
22
#include <linux/kernel.h>
23
#include <linux/fs.h>
24
#include <linux/sysv_fs.h>
25
#include <linux/string.h>
26
#include <linux/locks.h>
27
 
28
/* We don't trust the value of
29
   sb->sv_sbd2->s_tfree = *sb->sv_sb_total_free_blocks
30
   but we nevertheless keep it up to date. */
31
 
32
void sysv_free_block(struct super_block * sb, unsigned int block)
33
{
34
        struct buffer_head * bh;
35
        char * bh_data;
36
 
37
        if (!sb) {
38
                printk("sysv_free_block: trying to free block on nonexistent device\n");
39
                return;
40
        }
41
        if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
42
                printk("sysv_free_block: trying to free block not in datazone\n");
43
                return;
44
        }
45
        lock_super(sb);
46
        if (*sb->sv_sb_flc_count > sb->sv_flc_size) {
47
                printk("sysv_free_block: flc_count > flc_size\n");
48
                unlock_super(sb);
49
                return;
50
        }
51
        /* If the free list head in super-block is full, it is copied
52
         * into this block being freed:
53
         */
54
        if (*sb->sv_sb_flc_count == sb->sv_flc_size) {
55
                unsigned short * flc_count;
56
                unsigned long * flc_blocks;
57
 
58
                bh = sv_getblk(sb, sb->s_dev, block);
59
                if (!bh) {
60
                        printk("sysv_free_block: getblk() failed\n");
61
                        unlock_super(sb);
62
                        return;
63
                }
64
                bh_data = bh->b_data;
65
                switch (sb->sv_type) {
66
                        case FSTYPE_XENIX:
67
                                flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
68
                                flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
69
                                break;
70
                        case FSTYPE_SYSV4:
71
                                flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
72
                                flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
73
                                break;
74
                        case FSTYPE_SYSV2:
75
                                flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
76
                                flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
77
                                break;
78
                        case FSTYPE_COH:
79
                                flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
80
                                flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
81
                                break;
82
                        default: panic("sysv_free_block: invalid fs type\n");
83
                }
84
                *flc_count = *sb->sv_sb_flc_count; /* = sb->sv_flc_size */
85
                memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
86
                mark_buffer_dirty(bh, 1);
87
                mark_buffer_uptodate(bh, 1);
88
                brelse(bh);
89
                *sb->sv_sb_flc_count = 0;
90
        } else
91
        /* If the free list head in super-block is empty, create a new head
92
         * in this block being freed:
93
         */
94
        if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */
95
                bh = sv_getblk(sb, sb->s_dev, block);
96
                if (!bh) {
97
                        printk("sysv_free_block: getblk() failed\n");
98
                        unlock_super(sb);
99
                        return;
100
                }
101
                memset(bh->b_data, 0, sb->sv_block_size);
102
                /* this implies ((struct ..._freelist_chunk *) bh->b_data)->flc_count = 0; */
103
                mark_buffer_dirty(bh, 1);
104
                mark_buffer_uptodate(bh, 1);
105
                brelse(bh);
106
                /* still *sb->sv_sb_flc_count = 0 */
107
        } else {
108
                /* Throw away block's contents */
109
                bh = sv_get_hash_table(sb, sb->s_dev, block);
110
                if (bh)
111
                        mark_buffer_clean(bh);
112
                brelse(bh);
113
        }
114
        if (sb->sv_convert)
115
                block = to_coh_ulong(block);
116
        sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block;
117
        if (sb->sv_convert)
118
                *sb->sv_sb_total_free_blocks =
119
                  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
120
        else
121
                *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
122
        mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
123
        if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
124
        sb->s_dirt = 1; /* and needs time stamp */
125
        unlock_super(sb);
126
}
127
 
128
int sysv_new_block(struct super_block * sb)
129
{
130
        unsigned int block;
131
        struct buffer_head * bh;
132
        char * bh_data;
133
 
134
        if (!sb) {
135
                printk("sysv_new_block: trying to get new block from nonexistent device\n");
136
                return 0;
137
        }
138
        lock_super(sb);
139
        if (*sb->sv_sb_flc_count == 0) { /* Applies only to Coherent FS */
140
                unlock_super(sb);
141
                return 0;                /* no blocks available */
142
        }
143
        block = sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)-1];
144
        if (sb->sv_convert)
145
                block = from_coh_ulong(block);
146
        if (block == 0) { /* Applies only to Xenix FS, SystemV FS */
147
                unlock_super(sb);
148
                return 0;                /* no blocks available */
149
        }
150
        (*sb->sv_sb_flc_count)--;
151
        if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
152
                printk("sysv_new_block: new block %d is not in data zone\n",block);
153
                unlock_super(sb);
154
                return 0;
155
        }
156
        if (*sb->sv_sb_flc_count == 0) { /* the last block continues the free list */
157
                unsigned short * flc_count;
158
                unsigned long * flc_blocks;
159
 
160
                if (!(bh = sv_bread(sb, sb->s_dev, block))) {
161
                        printk("sysv_new_block: cannot read free-list block\n");
162
                        /* retry this same block next time */
163
                        (*sb->sv_sb_flc_count)++;
164
                        unlock_super(sb);
165
                        return 0;
166
                }
167
                bh_data = bh->b_data;
168
                switch (sb->sv_type) {
169
                        case FSTYPE_XENIX:
170
                                flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
171
                                flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
172
                                break;
173
                        case FSTYPE_SYSV4:
174
                                flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
175
                                flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
176
                                break;
177
                        case FSTYPE_SYSV2:
178
                                flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
179
                                flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
180
                                break;
181
                        case FSTYPE_COH:
182
                                flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
183
                                flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
184
                                break;
185
                        default: panic("sysv_new_block: invalid fs type\n");
186
                }
187
                if (*flc_count > sb->sv_flc_size) {
188
                        printk("sysv_new_block: free-list block with >flc_size entries\n");
189
                        brelse(bh);
190
                        unlock_super(sb);
191
                        return 0;
192
                }
193
                *sb->sv_sb_flc_count = *flc_count;
194
                memcpy(sb->sv_sb_flc_blocks, flc_blocks, *flc_count * sizeof(sysv_zone_t));
195
                brelse(bh);
196
        }
197
        /* Now the free list head in the superblock is valid again. */
198
        bh = sv_getblk(sb, sb->s_dev, block);
199
        if (!bh) {
200
                printk("sysv_new_block: getblk() failed\n");
201
                unlock_super(sb);
202
                return 0;
203
        }
204
        if (bh->b_count != 1) {
205
                printk("sysv_new_block: block already in use\n");
206
                unlock_super(sb);
207
                return 0;
208
        }
209
        memset(bh->b_data, 0, sb->sv_block_size);
210
        mark_buffer_dirty(bh, 1);
211
        mark_buffer_uptodate(bh, 1);
212
        brelse(bh);
213
        if (sb->sv_convert)
214
                *sb->sv_sb_total_free_blocks =
215
                  to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
216
        else
217
                *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
218
        mark_buffer_dirty(sb->sv_bh1, 1); /* super-block has been modified */
219
        if (sb->sv_bh1 != sb->sv_bh2) mark_buffer_dirty(sb->sv_bh2, 1);
220
        sb->s_dirt = 1; /* and needs time stamp */
221
        unlock_super(sb);
222
        return block;
223
}
224
 
225
unsigned long sysv_count_free_blocks(struct super_block * sb)
226
{
227
#if 1 /* test */
228
        int count, old_count;
229
        unsigned int block;
230
        struct buffer_head * bh;
231
        char * bh_data;
232
        int i;
233
 
234
        /* this causes a lot of disk traffic ... */
235
        count = 0;
236
        lock_super(sb);
237
        if (*sb->sv_sb_flc_count > 0) {
238
                for (i = *sb->sv_sb_flc_count ; /* i > 0 */ ; ) {
239
                        block = sb->sv_sb_flc_blocks[--i];
240
                        if (sb->sv_convert)
241
                                block = from_coh_ulong(block);
242
                        if (block == 0) /* block 0 terminates list */
243
                                goto done;
244
                        count++;
245
                        if (i == 0)
246
                                break;
247
                }
248
                /* block = sb->sv_sb_flc_blocks[0], the last block continues the free list */
249
                while (1) {
250
                        unsigned short * flc_count;
251
                        unsigned long * flc_blocks;
252
 
253
                        if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
254
                                printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);
255
                                break;
256
                        }
257
                        if (!(bh = sv_bread(sb, sb->s_dev, block))) {
258
                                printk("sysv_count_free_blocks: cannot read free-list block\n");
259
                                break;
260
                        }
261
                        bh_data = bh->b_data;
262
                        switch (sb->sv_type) {
263
                                case FSTYPE_XENIX:
264
                                        flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
265
                                        flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
266
                                        break;
267
                                case FSTYPE_SYSV4:
268
                                        flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
269
                                        flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
270
                                        break;
271
                                case FSTYPE_SYSV2:
272
                                        flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
273
                                        flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
274
                                        break;
275
                                case FSTYPE_COH:
276
                                        flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
277
                                        flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
278
                                        break;
279
                                default: panic("sysv_count_free_blocks: invalid fs type\n");
280
                        }
281
                        if (*flc_count > sb->sv_flc_size) {
282
                                printk("sysv_count_free_blocks: free-list block with >flc_size entries\n");
283
                                brelse(bh);
284
                                break;
285
                        }
286
                        if (*flc_count == 0) { /* Applies only to Coherent FS */
287
                                brelse(bh);
288
                                break;
289
                        }
290
                        for (i = *flc_count ; /* i > 0 */ ; ) {
291
                                block = flc_blocks[--i];
292
                                if (sb->sv_convert)
293
                                        block = from_coh_ulong(block);
294
                                if (block == 0) /* block 0 terminates list */
295
                                        break;
296
                                count++;
297
                                if (i == 0)
298
                                        break;
299
                        }
300
                        /* block = flc_blocks[0], the last block continues the free list */
301
                        brelse(bh);
302
                        if (block == 0) /* Applies only to Xenix FS and SystemV FS */
303
                                break;
304
                }
305
                done: ;
306
        }
307
        old_count = *sb->sv_sb_total_free_blocks;
308
        if (sb->sv_convert)
309
                old_count = from_coh_ulong(old_count);
310
        if (count != old_count) {
311
                printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
312
                if (!(sb->s_flags & MS_RDONLY)) {
313
                        *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
314
                        mark_buffer_dirty(sb->sv_bh2, 1); /* super-block has been modified */
315
                        sb->s_dirt = 1; /* and needs time stamp */
316
                }
317
        }
318
        unlock_super(sb);
319
        return count;
320
#else
321
        int count;
322
 
323
        count = *sb->sv_sb_total_free_blocks;
324
        if (sb->sv_convert)
325
                count = from_coh_ulong(count);
326
        return count;
327
#endif
328
}
329
 

powered by: WebSVN 2.1.0

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