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