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