This source file includes following definitions.
- memzero
- sysv_free_block
- sysv_new_block
- sysv_count_free_blocks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <linux/kernel.h>
23 #include <linux/fs.h>
24 #include <linux/sysv_fs.h>
25 #include <linux/string.h>
26 #include <linux/locks.h>
27
28
29
30
31
32 extern inline void memzero (void * s, size_t count)
33 {
34 __asm__("cld\n\t"
35 "rep\n\t"
36 "stosl"
37 :
38 :"a" (0),"D" (s),"c" (count/4)
39 :"cx","di","memory");
40 }
41
42 void sysv_free_block(struct super_block * sb, unsigned int block)
43 {
44 struct buffer_head * bh;
45 char * bh_data;
46
47 if (!sb) {
48 printk("sysv_free_block: trying to free block on nonexistent device\n");
49 return;
50 }
51 if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
52 printk("sysv_free_block: trying to free block not in datazone\n");
53 return;
54 }
55 lock_super(sb);
56 if (*sb->sv_sb_flc_count > sb->sv_flc_size) {
57 printk("sysv_free_block: flc_count > flc_size\n");
58 unlock_super(sb);
59 return;
60 }
61
62
63
64 if (*sb->sv_sb_flc_count == sb->sv_flc_size) {
65 unsigned short * flc_count;
66 unsigned long * flc_blocks;
67
68 if (sb->sv_block_size_ratio_bits > 0)
69 bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
70 else
71 bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
72 if (!bh) {
73 printk("sysv_free_block: getblk() or bread() failed\n");
74 unlock_super(sb);
75 return;
76 }
77 bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
78 switch (sb->sv_type) {
79 case FSTYPE_XENIX:
80 flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
81 flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
82 break;
83 case FSTYPE_SYSV4:
84 flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
85 flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
86 break;
87 case FSTYPE_SYSV2:
88 flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
89 flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
90 break;
91 case FSTYPE_COH:
92 flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
93 flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
94 break;
95 default: panic("sysv_free_block: invalid fs type\n");
96 }
97 *flc_count = *sb->sv_sb_flc_count;
98 memcpy(flc_blocks, sb->sv_sb_flc_blocks, *flc_count * sizeof(sysv_zone_t));
99 mark_buffer_dirty(bh, 1);
100 bh->b_uptodate = 1;
101 brelse(bh);
102 *sb->sv_sb_flc_count = 0;
103 } else
104
105
106
107 if (*sb->sv_sb_flc_count == 0) {
108 if (sb->sv_block_size_ratio_bits > 0)
109 bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
110 else
111 bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
112 if (!bh) {
113 printk("sysv_free_block: getblk() or bread() failed\n");
114 unlock_super(sb);
115 return;
116 }
117 bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
118 memzero(bh_data, sb->sv_block_size);
119
120 mark_buffer_dirty(bh, 1);
121 bh->b_uptodate = 1;
122 brelse(bh);
123
124 } else {
125 if (sb->sv_block_size_ratio_bits == 0) {
126
127 bh = get_hash_table(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
128 if (bh)
129 bh->b_dirt = 0;
130 brelse(bh);
131 }
132 }
133 if (sb->sv_convert)
134 block = to_coh_ulong(block);
135 sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)++] = block;
136 if (sb->sv_convert)
137 *sb->sv_sb_total_free_blocks =
138 to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) + 1);
139 else
140 *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks + 1;
141 mark_buffer_dirty(sb->sv_bh, 1);
142 sb->s_dirt = 1;
143 unlock_super(sb);
144 }
145
146 int sysv_new_block(struct super_block * sb)
147 {
148 unsigned int block;
149 struct buffer_head * bh;
150 char * bh_data;
151
152 if (!sb) {
153 printk("sysv_new_block: trying to get new block from nonexistent device\n");
154 return 0;
155 }
156 lock_super(sb);
157 if (*sb->sv_sb_flc_count == 0) {
158 unlock_super(sb);
159 return 0;
160 }
161 block = sb->sv_sb_flc_blocks[(*sb->sv_sb_flc_count)-1];
162 if (sb->sv_convert)
163 block = from_coh_ulong(block);
164 if (block == 0) {
165 unlock_super(sb);
166 return 0;
167 }
168 (*sb->sv_sb_flc_count)--;
169 if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
170 printk("sysv_new_block: new block %d is not in data zone\n",block);
171 unlock_super(sb);
172 return 0;
173 }
174 if (*sb->sv_sb_flc_count == 0) {
175 unsigned short * flc_count;
176 unsigned long * flc_blocks;
177
178 if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {
179 printk("sysv_new_block: cannot read free-list block\n");
180
181 (*sb->sv_sb_flc_count)++;
182 unlock_super(sb);
183 return 0;
184 }
185 switch (sb->sv_type) {
186 case FSTYPE_XENIX:
187 flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
188 flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
189 break;
190 case FSTYPE_SYSV4:
191 flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
192 flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
193 break;
194 case FSTYPE_SYSV2:
195 flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
196 flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
197 break;
198 case FSTYPE_COH:
199 flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
200 flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
201 break;
202 default: panic("sysv_new_block: invalid fs type\n");
203 }
204 if (*flc_count > sb->sv_flc_size) {
205 printk("sysv_new_block: free-list block with >flc_size entries\n");
206 brelse(bh);
207 unlock_super(sb);
208 return 0;
209 }
210 *sb->sv_sb_flc_count = *flc_count;
211 memcpy(sb->sv_sb_flc_blocks, flc_blocks, *flc_count * sizeof(sysv_zone_t));
212 brelse(bh);
213 }
214
215 if (sb->sv_block_size_ratio_bits > 0)
216 bh = bread(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
217 else
218 bh = getblk(sb->s_dev, (block >> sb->sv_block_size_ratio_bits) + sb->sv_block_base, BLOCK_SIZE);
219 if (!bh) {
220 printk("sysv_new_block: getblk() or bread() failed\n");
221 unlock_super(sb);
222 return 0;
223 }
224 bh_data = bh->b_data + ((block & sb->sv_block_size_ratio_1) << sb->sv_block_size_bits);
225 if (sb->sv_block_size_ratio_bits == 0)
226 if (bh->b_count != 1) {
227 printk("sysv_new_block: block already in use\n");
228 unlock_super(sb);
229 return 0;
230 }
231 memzero(bh_data,sb->sv_block_size);
232 mark_buffer_dirty(bh, 1);
233 bh->b_uptodate = 1;
234 brelse(bh);
235 if (sb->sv_convert)
236 *sb->sv_sb_total_free_blocks =
237 to_coh_ulong(from_coh_ulong(*sb->sv_sb_total_free_blocks) - 1);
238 else
239 *sb->sv_sb_total_free_blocks = *sb->sv_sb_total_free_blocks - 1;
240 mark_buffer_dirty(sb->sv_bh, 1);
241 sb->s_dirt = 1;
242 unlock_super(sb);
243 return block;
244 }
245
246 unsigned long sysv_count_free_blocks(struct super_block * sb)
247 {
248 #if 1
249 int count, old_count;
250 unsigned int block;
251 struct buffer_head * bh;
252 char * bh_data;
253 int i;
254
255
256 count = 0;
257 lock_super(sb);
258 if (*sb->sv_sb_flc_count > 0) {
259 for (i = *sb->sv_sb_flc_count ; ; ) {
260 block = sb->sv_sb_flc_blocks[--i];
261 if (sb->sv_convert)
262 block = from_coh_ulong(block);
263 if (block == 0)
264 goto done;
265 count++;
266 if (i == 0)
267 break;
268 }
269
270 while (1) {
271 unsigned short * flc_count;
272 unsigned long * flc_blocks;
273
274 if (block < sb->sv_firstdatazone || block >= sb->sv_nzones) {
275 printk("sysv_count_free_blocks: new block %d is not in data zone\n",block);
276 break;
277 }
278 if (!(bh = sysv_bread(sb, sb->s_dev, block, &bh_data))) {
279 printk("sysv_count_free_blocks: cannot read free-list block\n");
280 break;
281 }
282 switch (sb->sv_type) {
283 case FSTYPE_XENIX:
284 flc_count = &((struct xenix_freelist_chunk *) bh_data)->fl_nfree;
285 flc_blocks = &((struct xenix_freelist_chunk *) bh_data)->fl_free[0];
286 break;
287 case FSTYPE_SYSV4:
288 flc_count = &((struct sysv4_freelist_chunk *) bh_data)->fl_nfree;
289 flc_blocks = &((struct sysv4_freelist_chunk *) bh_data)->fl_free[0];
290 break;
291 case FSTYPE_SYSV2:
292 flc_count = &((struct sysv2_freelist_chunk *) bh_data)->fl_nfree;
293 flc_blocks = &((struct sysv2_freelist_chunk *) bh_data)->fl_free[0];
294 break;
295 case FSTYPE_COH:
296 flc_count = &((struct coh_freelist_chunk *) bh_data)->fl_nfree;
297 flc_blocks = &((struct coh_freelist_chunk *) bh_data)->fl_free[0];
298 break;
299 default: panic("sysv_count_free_blocks: invalid fs type\n");
300 }
301 if (*flc_count > sb->sv_flc_size) {
302 printk("sysv_count_free_blocks: free-list block with >flc_size entries\n");
303 brelse(bh);
304 break;
305 }
306 if (*flc_count == 0) {
307 brelse(bh);
308 break;
309 }
310 for (i = *flc_count ; ; ) {
311 block = flc_blocks[--i];
312 if (sb->sv_convert)
313 block = from_coh_ulong(block);
314 if (block == 0)
315 break;
316 count++;
317 if (i == 0)
318 break;
319 }
320
321 brelse(bh);
322 if (block == 0)
323 break;
324 }
325 done: ;
326 }
327 old_count = *sb->sv_sb_total_free_blocks;
328 if (sb->sv_convert)
329 old_count = from_coh_ulong(old_count);
330 if (count != old_count) {
331 printk("sysv_count_free_blocks: free block count was %d, correcting to %d\n",old_count,count);
332 if (!(sb->s_flags & MS_RDONLY)) {
333 *sb->sv_sb_total_free_blocks = (sb->sv_convert ? to_coh_ulong(count) : count);
334 mark_buffer_dirty(sb->sv_bh, 1);
335 sb->s_dirt = 1;
336 }
337 }
338 unlock_super(sb);
339 return count;
340 #else
341 int count;
342
343 count = *sb->sv_sb_total_free_blocks;
344 if (sb->sv_convert)
345 count = from_coh_ulong(count);
346 return count;
347 #endif
348 }
349