This source file includes following definitions.
- count_used
- ext_free_block
- ext_new_block
- ext_count_free_blocks
- ext_free_inode
- ext_new_inode
- ext_count_free_inodes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <linux/sched.h>
17 #include <linux/ext_fs.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
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 }
206 inode->i_flags = inode->i_sb->s_flags;
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)) {
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