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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [sysv/] [balloc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/fs.h>
23
#include <linux/sysv_fs.h>
24
#include <linux/locks.h>
25
 
26
/* We don't trust the value of
27
   sb->sv_sbd2->s_tfree = *sb->sv_free_blocks
28
   but we nevertheless keep it up to date. */
29
 
30
static inline u32 *get_chunk(struct super_block *sb, struct buffer_head *bh)
31
{
32
        char *bh_data = bh->b_data;
33
 
34
        if (sb->sv_type == FSTYPE_SYSV4)
35
                return (u32*)(bh_data+4);
36
        else
37
                return (u32*)(bh_data+2);
38
}
39
 
40
/* NOTE NOTE NOTE: nr is a block number _as_ _stored_ _on_ _disk_ */
41
 
42
void sysv_free_block(struct super_block * sb, u32 nr)
43
{
44
        struct buffer_head * bh;
45
        u32 *blocks = sb->sv_bcache;
46
        unsigned count;
47
        unsigned block = fs32_to_cpu(sb, nr);
48
 
49
        /*
50
         * This code does not work at all for AFS (it has a bitmap
51
         * free list).  As AFS is supposed to be read-only no one
52
         * should call this for an AFS filesystem anyway...
53
         */
54
        if (sb->sv_type == FSTYPE_AFS)
55
                return;
56
 
57
        if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
58
                printk("sysv_free_block: trying to free block not in datazone\n");
59
                return;
60
        }
61
 
62
        lock_super(sb);
63
        count = fs16_to_cpu(sb, *sb->sv_bcache_count);
64
 
65
        if (count > sb->sv_flc_size) {
66
                printk("sysv_free_block: flc_count > flc_size\n");
67
                unlock_super(sb);
68
                return;
69
        }
70
        /* If the free list head in super-block is full, it is copied
71
         * into this block being freed, ditto if it's completely empty
72
         * (applies only on Coherent).
73
         */
74
        if (count == sb->sv_flc_size || count == 0) {
75
                block += sb->sv_block_base;
76
                bh = sb_getblk(sb, block);
77
                if (!bh) {
78
                        printk("sysv_free_block: getblk() failed\n");
79
                        unlock_super(sb);
80
                        return;
81
                }
82
                memset(bh->b_data, 0, sb->s_blocksize);
83
                *(u16*)bh->b_data = cpu_to_fs16(sb, count);
84
                memcpy(get_chunk(sb,bh), blocks, count * sizeof(sysv_zone_t));
85
                mark_buffer_dirty(bh);
86
                mark_buffer_uptodate(bh, 1);
87
                brelse(bh);
88
                count = 0;
89
        }
90
        sb->sv_bcache[count++] = nr;
91
 
92
        *sb->sv_bcache_count = cpu_to_fs16(sb, count);
93
        fs32_add(sb, sb->sv_free_blocks, 1);
94
        dirty_sb(sb);
95
        unlock_super(sb);
96
}
97
 
98
u32 sysv_new_block(struct super_block * sb)
99
{
100
        unsigned int block;
101
        u32 nr;
102
        struct buffer_head * bh;
103
        unsigned count;
104
 
105
        lock_super(sb);
106
        count = fs16_to_cpu(sb, *sb->sv_bcache_count);
107
 
108
        if (count == 0) /* Applies only to Coherent FS */
109
                goto Enospc;
110
        nr = sb->sv_bcache[--count];
111
        if (nr == 0)  /* Applies only to Xenix FS, SystemV FS */
112
                goto Enospc;
113
 
114
        block = fs32_to_cpu(sb, nr);
115
 
116
        *sb->sv_bcache_count = cpu_to_fs16(sb, count);
117
 
118
        if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
119
                printk("sysv_new_block: new block %d is not in data zone\n",
120
                        block);
121
                goto Enospc;
122
        }
123
 
124
        if (count == 0) { /* the last block continues the free list */
125
                unsigned count;
126
 
127
                block += sb->sv_block_base;
128
                if (!(bh = sb_bread(sb, block))) {
129
                        printk("sysv_new_block: cannot read free-list block\n");
130
                        /* retry this same block next time */
131
                        *sb->sv_bcache_count = cpu_to_fs16(sb, 1);
132
                        goto Enospc;
133
                }
134
                count = fs16_to_cpu(sb, *(u16*)bh->b_data);
135
                if (count > sb->sv_flc_size) {
136
                        printk("sysv_new_block: free-list block with >flc_size entries\n");
137
                        brelse(bh);
138
                        goto Enospc;
139
                }
140
                *sb->sv_bcache_count = cpu_to_fs16(sb, count);
141
                memcpy(sb->sv_bcache, get_chunk(sb, bh),
142
                                count * sizeof(sysv_zone_t));
143
                brelse(bh);
144
        }
145
        /* Now the free list head in the superblock is valid again. */
146
        fs32_add(sb, sb->sv_free_blocks, -1);
147
        dirty_sb(sb);
148
        unlock_super(sb);
149
        return nr;
150
 
151
Enospc:
152
        unlock_super(sb);
153
        return 0;
154
}
155
 
156
unsigned long sysv_count_free_blocks(struct super_block * sb)
157
{
158
        int sb_count;
159
        int count;
160
        struct buffer_head * bh = NULL;
161
        u32 *blocks;
162
        unsigned block;
163
        int n;
164
 
165
        /*
166
         * This code does not work at all for AFS (it has a bitmap
167
         * free list).  As AFS is supposed to be read-only we just
168
         * lie and say it has no free block at all.
169
         */
170
        if (sb->sv_type == FSTYPE_AFS)
171
                return 0;
172
 
173
        lock_super(sb);
174
        sb_count = fs32_to_cpu(sb, *sb->sv_free_blocks);
175
 
176
        if (0)
177
                goto trust_sb;
178
 
179
        /* this causes a lot of disk traffic ... */
180
        count = 0;
181
        n = fs16_to_cpu(sb, *sb->sv_bcache_count);
182
        blocks = sb->sv_bcache;
183
        while (1) {
184
                if (n > sb->sv_flc_size)
185
                        goto E2big;
186
                block = 0;
187
                while (n && (block = blocks[--n]) != 0)
188
                        count++;
189
                if (block == 0)
190
                        break;
191
 
192
                block = fs32_to_cpu(sb, block);
193
                if (bh)
194
                        brelse(bh);
195
 
196
                if (block < sb->sv_firstdatazone || block >= sb->sv_nzones)
197
                        goto Einval;
198
                block += sb->sv_block_base;
199
                bh = sb_bread(sb, block);
200
                if (!bh)
201
                        goto Eio;
202
                n = fs16_to_cpu(sb, *(u16*)bh->b_data);
203
                blocks = get_chunk(sb, bh);
204
        }
205
        if (bh)
206
                brelse(bh);
207
        if (count != sb_count)
208
                goto Ecount;
209
done:
210
        unlock_super(sb);
211
        return count;
212
 
213
Einval:
214
        printk("sysv_count_free_blocks: new block %d is not in data zone\n",
215
                block);
216
        goto trust_sb;
217
Eio:
218
        printk("sysv_count_free_blocks: cannot read free-list block\n");
219
        goto trust_sb;
220
E2big:
221
        printk("sysv_count_free_blocks: >flc_size entries in free-list block\n");
222
        if (bh)
223
                brelse(bh);
224
trust_sb:
225
        count = sb_count;
226
        goto done;
227
Ecount:
228
        printk("sysv_count_free_blocks: free block count was %d, "
229
                "correcting to %d\n", sb_count, count);
230
        if (!(sb->s_flags & MS_RDONLY)) {
231
                *sb->sv_free_blocks = cpu_to_fs32(sb, count);
232
                dirty_sb(sb);
233
        }
234
        goto done;
235
}

powered by: WebSVN 2.1.0

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