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