|
|
1.1 root 1: /*
1.1.1.3 root 2: * linux/fs/minix/bitmap.c
1.1 root 3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: /* bitmap.c contains the code that handles the inode and block bitmaps */
8:
1.1.1.4 ! root 9: #include <linux/string.h>
1.1 root 10: #include <linux/sched.h>
11: #include <linux/minix_fs.h>
12: #include <linux/kernel.h>
13:
14: #define clear_block(addr) \
15: __asm__("cld\n\t" \
16: "rep\n\t" \
17: "stosl" \
18: ::"a" (0),"c" (BLOCK_SIZE/4),"D" ((long) (addr)):"cx","di")
19:
20: #define set_bit(nr,addr) ({\
21: char res; \
22: __asm__ __volatile__("btsl %1,%2\n\tsetb %0": \
23: "=q" (res):"r" (nr),"m" (*(addr))); \
24: res;})
25:
26: #define clear_bit(nr,addr) ({\
27: char res; \
28: __asm__ __volatile__("btrl %1,%2\n\tsetnb %0": \
29: "=q" (res):"r" (nr),"m" (*(addr))); \
30: res;})
31:
32: #define find_first_zero(addr) ({ \
33: int __res; \
34: __asm__("cld\n" \
35: "1:\tlodsl\n\t" \
36: "notl %%eax\n\t" \
37: "bsfl %%eax,%%edx\n\t" \
38: "jne 2f\n\t" \
39: "addl $32,%%ecx\n\t" \
40: "cmpl $8192,%%ecx\n\t" \
41: "jl 1b\n\t" \
42: "xorl %%edx,%%edx\n" \
43: "2:\taddl %%edx,%%ecx" \
44: :"=c" (__res):"0" (0),"S" (addr):"ax","dx","si"); \
45: __res;})
46:
1.1.1.3 root 47: static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
48:
49: static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
50: unsigned numbits)
51: {
52: unsigned i, j, end, sum = 0;
53: struct buffer_head *bh;
54:
55: for (i=0; (i<numblocks) && numbits; i++) {
56: if (!(bh=map[i]))
57: return(0);
58: if (numbits >= (8*BLOCK_SIZE)) {
59: end = BLOCK_SIZE;
60: numbits -= 8*BLOCK_SIZE;
61: } else {
62: int tmp;
63: end = numbits >> 3;
64: numbits &= 0x7;
65: tmp = bh->b_data[end] & ((1<<numbits)-1);
66: sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
67: numbits = 0;
68: }
69: for (j=0; j<end; j++)
70: sum += nibblemap[bh->b_data[j] & 0xf]
71: + nibblemap[(bh->b_data[j]>>4)&0xf];
72: }
73: return(sum);
74: }
75:
1.1 root 76: int minix_free_block(int dev, int block)
77: {
78: struct super_block * sb;
79: struct buffer_head * bh;
80: unsigned int bit,zone;
81:
82: if (!(sb = get_super(dev)))
83: panic("trying to free block on nonexistent device");
84: if (block < sb->s_firstdatazone || block >= sb->s_nzones)
85: panic("trying to free block not in datazone");
86: bh = get_hash_table(dev,block);
87: if (bh) {
88: if (bh->b_count > 1) {
89: brelse(bh);
90: return 0;
91: }
92: bh->b_dirt=0;
93: bh->b_uptodate=0;
94: if (bh->b_count)
95: brelse(bh);
96: }
97: zone = block - sb->s_firstdatazone + 1;
98: bit = zone & 8191;
99: zone >>= 13;
100: bh = sb->s_zmap[zone];
101: if (clear_bit(bit,bh->b_data))
102: printk("free_block (%04x:%d): bit already cleared\n",dev,block);
103: bh->b_dirt = 1;
104: return 1;
105: }
106:
107: int minix_new_block(int dev)
108: {
109: struct buffer_head * bh;
110: struct super_block * sb;
111: int i,j;
112:
113: if (!(sb = get_super(dev)))
114: panic("trying to get new block from nonexistant device");
115: j = 8192;
116: for (i=0 ; i<8 ; i++)
117: if (bh=sb->s_zmap[i])
118: if ((j=find_first_zero(bh->b_data))<8192)
119: break;
120: if (i>=8 || !bh || j>=8192)
121: return 0;
122: if (set_bit(j,bh->b_data))
123: panic("new_block: bit already set");
124: bh->b_dirt = 1;
125: j += i*8192 + sb->s_firstdatazone-1;
126: if (j >= sb->s_nzones)
127: return 0;
128: if (!(bh=getblk(dev,j)))
129: panic("new_block: cannot get block");
130: if (bh->b_count != 1)
131: panic("new block: count is != 1");
132: clear_block(bh->b_data);
133: bh->b_uptodate = 1;
134: bh->b_dirt = 1;
135: brelse(bh);
136: return j;
137: }
138:
1.1.1.3 root 139: unsigned long minix_count_free_blocks(struct super_block *sb)
140: {
141: return (sb->s_nzones - count_used(sb->s_zmap,sb->s_zmap_blocks,sb->s_nzones))
142: << sb->s_log_zone_size;
143: }
144:
1.1 root 145: void minix_free_inode(struct inode * inode)
146: {
147: struct buffer_head * bh;
148:
149: if (!inode)
150: return;
151: if (!inode->i_dev) {
152: memset(inode,0,sizeof(*inode));
153: return;
154: }
155: if (inode->i_count>1) {
156: printk("free_inode: inode has count=%d\n",inode->i_count);
157: return;
158: }
159: if (inode->i_nlink) {
160: printk("free_inode: inode has nlink=%d\n",inode->i_nlink);
161: return;
162: }
163: if (!inode->i_sb) {
164: printk("free_inode: inode on nonexistent device\n");
165: return;
166: }
167: if (inode->i_ino < 1 || inode->i_ino > inode->i_sb->s_ninodes) {
168: printk("free_inode: inode 0 or nonexistent inode\n");
169: return;
170: }
171: if (!(bh=inode->i_sb->s_imap[inode->i_ino>>13])) {
172: printk("free_inode: nonexistent imap in superblock\n");
173: return;
174: }
175: if (clear_bit(inode->i_ino&8191,bh->b_data))
176: printk("free_inode: bit already cleared.\n\r");
177: bh->b_dirt = 1;
178: memset(inode,0,sizeof(*inode));
179: }
180:
181: struct inode * minix_new_inode(int dev)
182: {
183: struct inode * inode;
184: struct buffer_head * bh;
185: int i,j;
186:
187: if (!(inode=get_empty_inode()))
188: return NULL;
189: if (!(inode->i_sb = get_super(dev))) {
190: printk("new_inode: unknown device\n");
191: iput(inode);
192: return NULL;
193: }
194: j = 8192;
195: for (i=0 ; i<8 ; i++)
196: if (bh=inode->i_sb->s_imap[i])
197: if ((j=find_first_zero(bh->b_data))<8192)
198: break;
199: if (!bh || j >= 8192 || j+i*8192 > inode->i_sb->s_ninodes) {
200: iput(inode);
201: return NULL;
202: }
203: if (set_bit(j,bh->b_data)) { /* shouldn't happen */
204: printk("new_inode: bit already set");
205: iput(inode);
206: return NULL;
207: }
208: bh->b_dirt = 1;
209: inode->i_count = 1;
210: inode->i_nlink = 1;
211: inode->i_dev = dev;
212: inode->i_uid = current->euid;
213: inode->i_gid = current->egid;
214: inode->i_dirt = 1;
215: inode->i_ino = j + i*8192;
216: inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1.1.1.2 root 217: inode->i_op = NULL;
1.1 root 218: return inode;
219: }
1.1.1.3 root 220:
221: unsigned long minix_count_free_inodes(struct super_block *sb)
222: {
223: return sb->s_ninodes - count_used(sb->s_imap,sb->s_imap_blocks,sb->s_ninodes);
224: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.