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