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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [minix/] [bitmap.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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 "minix.h"
15
#include <linux/smp_lock.h>
16
#include <linux/buffer_head.h>
17
#include <linux/bitops.h>
18
#include <linux/sched.h>
19
 
20
static const 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<bh->b_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) * bh->b_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, unsigned long block)
53
{
54
        struct super_block *sb = inode->i_sb;
55
        struct minix_sb_info *sbi = minix_sb(sb);
56
        struct buffer_head *bh;
57
        int k = sb->s_blocksize_bits + 3;
58
        unsigned long bit, zone;
59
 
60
        if (block < sbi->s_firstdatazone || block >= sbi->s_nzones) {
61
                printk("Trying to free block not in datazone\n");
62
                return;
63
        }
64
        zone = block - sbi->s_firstdatazone + 1;
65
        bit = zone & ((1<<k) - 1);
66
        zone >>= k;
67
        if (zone >= sbi->s_zmap_blocks) {
68
                printk("minix_free_block: nonexistent bitmap buffer\n");
69
                return;
70
        }
71
        bh = sbi->s_zmap[zone];
72
        lock_kernel();
73
        if (!minix_test_and_clear_bit(bit, bh->b_data))
74
                printk("minix_free_block (%s:%lu): bit already cleared\n",
75
                       sb->s_id, block);
76
        unlock_kernel();
77
        mark_buffer_dirty(bh);
78
        return;
79
}
80
 
81
int minix_new_block(struct inode * inode)
82
{
83
        struct minix_sb_info *sbi = minix_sb(inode->i_sb);
84
        int bits_per_zone = 8 * inode->i_sb->s_blocksize;
85
        int i;
86
 
87
        for (i = 0; i < sbi->s_zmap_blocks; i++) {
88
                struct buffer_head *bh = sbi->s_zmap[i];
89
                int j;
90
 
91
                lock_kernel();
92
                j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
93
                if (j < bits_per_zone) {
94
                        minix_set_bit(j, bh->b_data);
95
                        unlock_kernel();
96
                        mark_buffer_dirty(bh);
97
                        j += i * bits_per_zone + sbi->s_firstdatazone-1;
98
                        if (j < sbi->s_firstdatazone || j >= sbi->s_nzones)
99
                                break;
100
                        return j;
101
                }
102
                unlock_kernel();
103
        }
104
        return 0;
105
}
106
 
107
unsigned long minix_count_free_blocks(struct minix_sb_info *sbi)
108
{
109
        return (count_free(sbi->s_zmap, sbi->s_zmap_blocks,
110
                sbi->s_nzones - sbi->s_firstdatazone + 1)
111
                << sbi->s_log_zone_size);
112
}
113
 
114
struct minix_inode *
115
minix_V1_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
116
{
117
        int block;
118
        struct minix_sb_info *sbi = minix_sb(sb);
119
        struct minix_inode *p;
120
 
121
        if (!ino || ino > sbi->s_ninodes) {
122
                printk("Bad inode number on dev %s: %ld is out of range\n",
123
                       sb->s_id, (long)ino);
124
                return NULL;
125
        }
126
        ino--;
127
        block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
128
                 ino / MINIX_INODES_PER_BLOCK;
129
        *bh = sb_bread(sb, block);
130
        if (!*bh) {
131
                printk("Unable to read inode block\n");
132
                return NULL;
133
        }
134
        p = (void *)(*bh)->b_data;
135
        return p + ino % MINIX_INODES_PER_BLOCK;
136
}
137
 
138
struct minix2_inode *
139
minix_V2_raw_inode(struct super_block *sb, ino_t ino, struct buffer_head **bh)
140
{
141
        int block;
142
        struct minix_sb_info *sbi = minix_sb(sb);
143
        struct minix2_inode *p;
144
        int minix2_inodes_per_block = sb->s_blocksize / sizeof(struct minix2_inode);
145
 
146
        *bh = NULL;
147
        if (!ino || ino > sbi->s_ninodes) {
148
                printk("Bad inode number on dev %s: %ld is out of range\n",
149
                       sb->s_id, (long)ino);
150
                return NULL;
151
        }
152
        ino--;
153
        block = 2 + sbi->s_imap_blocks + sbi->s_zmap_blocks +
154
                 ino / minix2_inodes_per_block;
155
        *bh = sb_bread(sb, block);
156
        if (!*bh) {
157
                printk("Unable to read inode block\n");
158
                return NULL;
159
        }
160
        p = (void *)(*bh)->b_data;
161
        return p + ino % minix2_inodes_per_block;
162
}
163
 
164
/* Clear the link count and mode of a deleted inode on disk. */
165
 
166
static void minix_clear_inode(struct inode *inode)
167
{
168
        struct buffer_head *bh = NULL;
169
 
170
        if (INODE_VERSION(inode) == MINIX_V1) {
171
                struct minix_inode *raw_inode;
172
                raw_inode = minix_V1_raw_inode(inode->i_sb, inode->i_ino, &bh);
173
                if (raw_inode) {
174
                        raw_inode->i_nlinks = 0;
175
                        raw_inode->i_mode = 0;
176
                }
177
        } else {
178
                struct minix2_inode *raw_inode;
179
                raw_inode = minix_V2_raw_inode(inode->i_sb, inode->i_ino, &bh);
180
                if (raw_inode) {
181
                        raw_inode->i_nlinks = 0;
182
                        raw_inode->i_mode = 0;
183
                }
184
        }
185
        if (bh) {
186
                mark_buffer_dirty(bh);
187
                brelse (bh);
188
        }
189
}
190
 
191
void minix_free_inode(struct inode * inode)
192
{
193
        struct super_block *sb = inode->i_sb;
194
        struct minix_sb_info *sbi = minix_sb(inode->i_sb);
195
        struct buffer_head *bh;
196
        int k = sb->s_blocksize_bits + 3;
197
        unsigned long ino, bit;
198
 
199
        ino = inode->i_ino;
200
        if (ino < 1 || ino > sbi->s_ninodes) {
201
                printk("minix_free_inode: inode 0 or nonexistent inode\n");
202
                goto out;
203
        }
204
        bit = ino & ((1<<k) - 1);
205
        ino >>= k;
206
        if (ino >= sbi->s_imap_blocks) {
207
                printk("minix_free_inode: nonexistent imap in superblock\n");
208
                goto out;
209
        }
210
 
211
        minix_clear_inode(inode);       /* clear on-disk copy */
212
 
213
        bh = sbi->s_imap[ino];
214
        lock_kernel();
215
        if (!minix_test_and_clear_bit(bit, bh->b_data))
216
                printk("minix_free_inode: bit %lu already cleared\n", bit);
217
        unlock_kernel();
218
        mark_buffer_dirty(bh);
219
 out:
220
        clear_inode(inode);             /* clear in-memory copy */
221
}
222
 
223
struct inode * minix_new_inode(const struct inode * dir, int * error)
224
{
225
        struct super_block *sb = dir->i_sb;
226
        struct minix_sb_info *sbi = minix_sb(sb);
227
        struct inode *inode = new_inode(sb);
228
        struct buffer_head * bh;
229
        int bits_per_zone = 8 * sb->s_blocksize;
230
        unsigned long j;
231
        int i;
232
 
233
        if (!inode) {
234
                *error = -ENOMEM;
235
                return NULL;
236
        }
237
        j = bits_per_zone;
238
        bh = NULL;
239
        *error = -ENOSPC;
240
        lock_kernel();
241
        for (i = 0; i < sbi->s_imap_blocks; i++) {
242
                bh = sbi->s_imap[i];
243
                j = minix_find_first_zero_bit(bh->b_data, bits_per_zone);
244
                if (j < bits_per_zone)
245
                        break;
246
        }
247
        if (!bh || j >= bits_per_zone) {
248
                unlock_kernel();
249
                iput(inode);
250
                return NULL;
251
        }
252
        if (minix_test_and_set_bit(j, bh->b_data)) {    /* shouldn't happen */
253
                unlock_kernel();
254
                printk("minix_new_inode: bit already set\n");
255
                iput(inode);
256
                return NULL;
257
        }
258
        unlock_kernel();
259
        mark_buffer_dirty(bh);
260
        j += i * bits_per_zone;
261
        if (!j || j > sbi->s_ninodes) {
262
                iput(inode);
263
                return NULL;
264
        }
265
        inode->i_uid = current->fsuid;
266
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
267
        inode->i_ino = j;
268
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
269
        inode->i_blocks = 0;
270
        memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
271
        insert_inode_hash(inode);
272
        mark_inode_dirty(inode);
273
 
274
        *error = 0;
275
        return inode;
276
}
277
 
278
unsigned long minix_count_free_inodes(struct minix_sb_info *sbi)
279
{
280
        return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1);
281
}

powered by: WebSVN 2.1.0

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