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