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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/fs/minix/bitmap.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 */
6
 
7
/*
8
 * Modified for 680x0 by Hamish Macdonald
9
 * Fixed for 680x0 by Andreas Schwab
10
 */
11
 
12
/* bitmap.c contains the code that handles the inode and block bitmaps */
13
 
14
#include <linux/fs.h>
15
#include <linux/minix_fs.h>
16
#include <linux/locks.h>
17
 
18
#include <asm/bitops.h>
19
 
20
static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
21
 
22
static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
23
{
24
        unsigned i, j, sum = 0;
25
        struct buffer_head *bh;
26
 
27
        for (i=0; i<numblocks-1; i++) {
28
                if (!(bh=map[i]))
29
                        return(0);
30
                for (j=0; j<BLOCK_SIZE; j++)
31
                        sum += nibblemap[bh->b_data[j] & 0xf]
32
                                + nibblemap[(bh->b_data[j]>>4) & 0xf];
33
        }
34
 
35
        if (numblocks==0 || !(bh=map[numblocks-1]))
36
                return(0);
37
        i = ((numbits-(numblocks-1)*BLOCK_SIZE*8)/16)*2;
38
        for (j=0; j<i; j++) {
39
                sum += nibblemap[bh->b_data[j] & 0xf]
40
                        + nibblemap[(bh->b_data[j]>>4) & 0xf];
41
        }
42
 
43
        i = numbits%16;
44
        if (i!=0) {
45
                i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
46
                sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
47
                sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
48
        }
49
        return(sum);
50
}
51
 
52
void minix_free_block(struct inode * inode, int block)
53
{
54
        struct super_block * sb = inode->i_sb;
55
        struct buffer_head * bh;
56
        unsigned int bit,zone;
57
 
58
        if (!sb) {
59
                printk("trying to free block on nonexistent device\n");
60
                return;
61
        }
62
        if (block < sb->u.minix_sb.s_firstdatazone ||
63
            block >= sb->u.minix_sb.s_nzones) {
64
                printk("trying to free block not in datazone\n");
65
                return;
66
        }
67
        zone = block - sb->u.minix_sb.s_firstdatazone + 1;
68
        bit = zone & 8191;
69
        zone >>= 13;
70
        if (zone >= sb->u.minix_sb.s_zmap_blocks) {
71
                printk("minix_free_block: nonexistent bitmap buffer\n");
72
                return;
73
        }
74
        bh = sb->u.minix_sb.s_zmap[zone];
75
        if (!minix_test_and_clear_bit(bit,bh->b_data))
76
                printk("free_block (%s:%d): bit already cleared\n",
77
                       kdevname(sb->s_dev), block);
78
        mark_buffer_dirty(bh);
79
        return;
80
}
81
 
82
int minix_new_block(struct inode * inode)
83
{
84
        struct super_block * sb = inode->i_sb;
85
        struct buffer_head * bh;
86
        int i,j;
87
 
88
        if (!sb) {
89
                printk("trying to get new block from nonexistent device\n");
90
                return 0;
91
        }
92
repeat:
93
        j = 8192;
94
        bh = NULL;
95
        for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
96
                bh = sb->u.minix_sb.s_zmap[i];
97
                if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
98
                        break;
99
        }
100
        if (!bh || j >= 8192)
101
                return 0;
102
        if (minix_test_and_set_bit(j,bh->b_data)) {
103
                printk("new_block: bit already set");
104
                goto repeat;
105
        }
106
        mark_buffer_dirty(bh);
107
        j += i*8192 + sb->u.minix_sb.s_firstdatazone-1;
108
        if (j < sb->u.minix_sb.s_firstdatazone ||
109
            j >= sb->u.minix_sb.s_nzones)
110
                return 0;
111
        return j;
112
}
113
 
114
unsigned long minix_count_free_blocks(struct super_block *sb)
115
{
116
        return (count_free(sb->u.minix_sb.s_zmap, sb->u.minix_sb.s_zmap_blocks,
117
                sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone + 1)
118
                << sb->u.minix_sb.s_log_zone_size);
119
}
120
 
121
struct minix_inode *
122
minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
123
{
124
        int block;
125
        struct minix_sb_info *sbi = &sb->u.minix_sb;
126
        struct minix_inode *p;
127
 
128
        if (!ino || ino > sbi->s_ninodes) {
129
                printk("Bad inode number on dev %s: %ld is out of range\n",
130
                       bdevname(sb->s_dev), ino);
131
                return NULL;
132
        }
133
        ino--;
134
        block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
135
                 ino / MINIX_INODES_PER_BLOCK;
136
        *bh = sb_bread(sb, block);
137
        if (!*bh) {
138
                printk("unable to read i-node block\n");
139
                return NULL;
140
        }
141
        p = (void *)(*bh)->b_data;
142
        return p + ino % MINIX_INODES_PER_BLOCK;
143
}
144
 
145
struct minix2_inode *
146
minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
147
{
148
        int block;
149
        struct minix_sb_info *sbi = &sb->u.minix_sb;
150
        struct minix2_inode *p;
151
 
152
        *bh = NULL;
153
        if (!ino || ino > sbi->s_ninodes) {
154
                printk("Bad inode number on dev %s: %ld is out of range\n",
155
                       bdevname(sb->s_dev), ino);
156
                return NULL;
157
        }
158
        ino--;
159
        block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
160
                 ino / MINIX2_INODES_PER_BLOCK;
161
        *bh = sb_bread(sb, block);
162
        if (!*bh) {
163
                printk("unable to read i-node block\n");
164
                return NULL;
165
        }
166
        p = (void *)(*bh)->b_data;
167
        return p + ino % MINIX2_INODES_PER_BLOCK;
168
}
169
 
170
/* Clear the link count and mode of a deleted inode on disk. */
171
 
172
static void minix_clear_inode(struct inode *inode)
173
{
174
        struct buffer_head *bh;
175
        if (INODE_VERSION(inode) == MINIX_V1) {
176
                struct minix_inode *raw_inode;
177
                raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
178
                if (raw_inode) {
179
                        raw_inode->i_nlinks = 0;
180
                        raw_inode->i_mode = 0;
181
                }
182
        } else {
183
                struct minix2_inode *raw_inode;
184
                raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
185
                if (raw_inode) {
186
                        raw_inode->i_nlinks = 0;
187
                        raw_inode->i_mode = 0;
188
                }
189
        }
190
        if (bh) {
191
                mark_buffer_dirty(bh);
192
                brelse (bh);
193
        }
194
}
195
 
196
void minix_free_inode(struct inode * inode)
197
{
198
        struct buffer_head * bh;
199
        unsigned long ino;
200
 
201
        if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->u.minix_sb.s_ninodes) {
202
                printk("free_inode: inode 0 or nonexistent inode\n");
203
                return;
204
        }
205
        ino = inode->i_ino;
206
        if ((ino >> 13) >= inode->i_sb->u.minix_sb.s_imap_blocks) {
207
                printk("free_inode: nonexistent imap in superblock\n");
208
                return;
209
        }
210
 
211
        bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
212
        minix_clear_inode(inode);
213
        clear_inode(inode);
214
        if (!minix_test_and_clear_bit(ino & 8191, bh->b_data))
215
                printk("free_inode: bit %lu already cleared.\n",ino);
216
        mark_buffer_dirty(bh);
217
}
218
 
219
struct inode * minix_new_inode(const struct inode * dir, int * error)
220
{
221
        struct super_block * sb;
222
        struct inode * inode;
223
        struct buffer_head * bh;
224
        int i,j;
225
 
226
        sb = dir->i_sb;
227
        inode = new_inode(sb);
228
        if (!inode) {
229
                *error = -ENOMEM;
230
                return NULL;
231
        }
232
        j = 8192;
233
        bh = NULL;
234
        *error = -ENOSPC;
235
        lock_super(sb);
236
        for (i = 0; i < sb->u.minix_sb.s_imap_blocks; i++) {
237
                bh = inode->i_sb->u.minix_sb.s_imap[i];
238
                if ((j = minix_find_first_zero_bit(bh->b_data, 8192)) < 8192)
239
                        break;
240
        }
241
        if (!bh || j >= 8192) {
242
                iput(inode);
243
                unlock_super(sb);
244
                return NULL;
245
        }
246
        if (minix_test_and_set_bit(j,bh->b_data)) {     /* shouldn't happen */
247
                printk("new_inode: bit already set");
248
                iput(inode);
249
                unlock_super(sb);
250
                return NULL;
251
        }
252
        mark_buffer_dirty(bh);
253
        j += i*8192;
254
        if (!j || j > inode->i_sb->u.minix_sb.s_ninodes) {
255
                iput(inode);
256
                unlock_super(sb);
257
                return NULL;
258
        }
259
        inode->i_uid = current->fsuid;
260
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
261
        inode->i_ino = j;
262
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
263
        inode->i_blocks = inode->i_blksize = 0;
264
        insert_inode_hash(inode);
265
        mark_inode_dirty(inode);
266
 
267
        unlock_super(sb);
268
        *error = 0;
269
        return inode;
270
}
271
 
272
unsigned long minix_count_free_inodes(struct super_block *sb)
273
{
274
        return count_free(sb->u.minix_sb.s_imap, sb->u.minix_sb.s_imap_blocks,
275
                sb->u.minix_sb.s_ninodes + 1);
276
}

powered by: WebSVN 2.1.0

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