This source file includes following definitions.
- coh_trunc_direct
- coh_trunc_indirect
- coh_trunc_dindirect
- coh_trunc_tindirect
- coh_trunc_all
- trunc_direct
- trunc_indirect
- trunc_dindirect
- trunc_tindirect
- trunc_all
- sysv_truncate
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/sched.h>
15 #include <linux/fs.h>
16 #include <linux/sysv_fs.h>
17 #include <linux/stat.h>
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 static int coh_trunc_direct (struct inode * inode, unsigned long blocks)
33 {
34 unsigned int i;
35 unsigned long * p;
36 unsigned long block;
37
38 for (i = blocks; i < 10 ; i++) {
39 p = &inode->u.sysv_i.i_data[i];
40 block = *p;
41 if (!block)
42 continue;
43 *p = 0;
44 inode->i_dirt = 1;
45 sysv_free_block(inode->i_sb,block);
46 }
47 return 0;
48 }
49
50
51
52
53 static int coh_trunc_indirect (struct inode * inode, unsigned long blocks, unsigned long * p, int convert, unsigned char * dirt)
54 {
55 struct super_block * sb = inode->i_sb;
56 unsigned long tmp, block, indblock;
57 struct buffer_head * bh;
58 char * bh_data;
59 unsigned long i;
60 sysv_zone_t * ind;
61
62 if (blocks >= sb->sv_ind_per_block)
63 return 0;
64 block = tmp = *p;
65 if (convert)
66 block = from_coh_ulong(block);
67 if (!block)
68 return 0;
69 bh = sysv_bread(sb,inode->i_dev,block,&bh_data);
70 if (tmp != *p) {
71 brelse(bh);
72 return 1;
73 }
74 if (!bh) {
75 *p = 0;
76 *dirt = 1;
77 return 0;
78 }
79 for (i = blocks; i < sb->sv_ind_per_block; i++) {
80 ind = &((sysv_zone_t *) bh_data)[i];
81 indblock = *ind;
82 if (sb->sv_convert)
83 indblock = from_coh_ulong(indblock);
84 if (!indblock)
85 continue;
86 *ind = 0;
87 mark_buffer_dirty(bh, 1);
88 sysv_free_block(sb,indblock);
89 }
90 for (i = 0; i < sb->sv_ind_per_block; i++)
91 if (((sysv_zone_t *) bh_data)[i])
92 goto done;
93 if (tmp != *p) {
94 brelse(bh);
95 return 1;
96 }
97 *p = 0;
98 *dirt = 1;
99 sysv_free_block(sb,block);
100 done:
101 brelse(bh);
102 return 0;
103 }
104
105
106
107
108 static int coh_trunc_dindirect (struct inode * inode, unsigned long blocks, unsigned long * p, int convert, unsigned char * dirt)
109 {
110 struct super_block * sb = inode->i_sb;
111 unsigned long tmp, block, dindblock;
112 struct buffer_head * bh;
113 char * bh_data;
114 unsigned long i, j;
115 sysv_zone_t * dind;
116 int retry = 0;
117
118 if (blocks >= sb->sv_ind_per_block_2)
119 return 0;
120 block = tmp = *p;
121 if (convert)
122 block = from_coh_ulong(block);
123 if (!block)
124 return 0;
125 bh = sysv_bread(sb,inode->i_dev,block,&bh_data);
126 if (tmp != *p) {
127 brelse(bh);
128 return 1;
129 }
130 if (!bh) {
131 *p = 0;
132 *dirt = 1;
133 return 0;
134 }
135 for (i = blocks >> sb->sv_ind_per_block_bits, j = blocks & sb->sv_ind_per_block_1;
136 i < sb->sv_ind_per_block;
137 i++, j = 0) {
138
139 dind = &((sysv_zone_t *) bh_data)[i];
140 dindblock = *dind;
141 if (sb->sv_convert)
142 dindblock = from_coh_ulong(dindblock);
143 if (!dindblock)
144 continue;
145 retry |= coh_trunc_indirect(inode,j,dind,sb->sv_convert,&bh->b_dirt);
146 }
147 for (i = 0; i < sb->sv_ind_per_block; i++)
148 if (((sysv_zone_t *) bh_data)[i])
149 goto done;
150 if (tmp != *p) {
151 brelse(bh);
152 return 1;
153 }
154 *p = 0;
155 *dirt = 1;
156 sysv_free_block(sb,block);
157 done:
158 brelse(bh);
159 return retry;
160 }
161
162
163
164
165 static int coh_trunc_tindirect (struct inode * inode, unsigned long blocks, unsigned long * p)
166 {
167 struct super_block * sb = inode->i_sb;
168 unsigned long block, tindblock;
169 struct buffer_head * bh;
170 char * bh_data;
171 unsigned long i, j;
172 sysv_zone_t * tind;
173 int retry = 0;
174
175 if (blocks >= sb->sv_ind_per_block_3)
176 return 0;
177 block = *p;
178 if (!block)
179 return 0;
180 bh = sysv_bread(sb,inode->i_dev,block,&bh_data);
181 if (block != *p) {
182 brelse(bh);
183 return 1;
184 }
185 if (!bh) {
186 *p = 0;
187 inode->i_dirt = 1;
188 return 0;
189 }
190 for (i = blocks >> sb->sv_ind_per_block_2_bits, j = blocks & sb->sv_ind_per_block_2_1;
191 i < sb->sv_ind_per_block;
192 i++, j = 0) {
193
194 tind = &((sysv_zone_t *) bh_data)[i];
195 tindblock = *tind;
196 if (sb->sv_convert)
197 tindblock = from_coh_ulong(tindblock);
198 if (!tindblock)
199 continue;
200 retry |= coh_trunc_dindirect(inode,j,tind,sb->sv_convert,&bh->b_dirt);
201 }
202 for (i = 0; i < sb->sv_ind_per_block; i++)
203 if (((sysv_zone_t *) bh_data)[i])
204 goto done;
205 if (block != *p) {
206 brelse(bh);
207 return 1;
208 }
209 *p = 0;
210 inode->i_dirt = 1;
211 sysv_free_block(sb,block);
212 done:
213 brelse(bh);
214 return retry;
215 }
216
217 static int coh_trunc_all(struct inode * inode)
218 {
219 struct super_block * sb = inode->i_sb;
220 long blocks;
221 int retry;
222
223 blocks = (inode->i_size + sb->sv_block_size_1) >> sb->sv_block_size_bits;
224 retry = coh_trunc_direct(inode,blocks);
225 blocks -= 10;
226 if (blocks < 0) blocks = 0;
227 retry |= coh_trunc_indirect(inode,blocks,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt);
228 blocks -= sb->sv_ind_per_block;
229 if (blocks < 0) blocks = 0;
230 retry |= coh_trunc_dindirect(inode,blocks,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt);
231 blocks -= sb->sv_ind_per_block_2;
232 if (blocks < 0) blocks = 0;
233 retry |= coh_trunc_tindirect(inode,blocks,&inode->u.sysv_i.i_data[12]);
234 return retry;
235 }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 static int trunc_direct(struct inode * inode)
256 {
257 struct super_block * sb;
258 unsigned int i;
259 unsigned long * p;
260 unsigned long block;
261 struct buffer_head * bh;
262 int retry = 0;
263
264 sb = inode->i_sb;
265 repeat:
266 for (i = ((unsigned long) inode->i_size + BLOCK_SIZE-1) / BLOCK_SIZE; i < 10; i++) {
267 p = inode->u.sysv_i.i_data + i;
268 block = *p;
269 if (!block)
270 continue;
271 bh = get_hash_table(inode->i_dev,block+sb->sv_block_base,BLOCK_SIZE);
272 if (i*BLOCK_SIZE < inode->i_size) {
273 brelse(bh);
274 goto repeat;
275 }
276 if ((bh && bh->b_count != 1) || (block != *p)) {
277 retry = 1;
278 brelse(bh);
279 continue;
280 }
281 *p = 0;
282 inode->i_dirt = 1;
283 brelse(bh);
284 sysv_free_block(sb,block);
285 }
286 return retry;
287 }
288
289 #define IND_PER_BLOCK (BLOCK_SIZE / sizeof(sysv_zone_t))
290
291 static int trunc_indirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
292 {
293 unsigned long indtmp, indblock;
294 struct super_block * sb;
295 struct buffer_head * indbh;
296 unsigned int i;
297 sysv_zone_t * ind;
298 unsigned long tmp, block;
299 struct buffer_head * bh;
300 int retry = 0;
301
302 indblock = indtmp = *p;
303 if (convert)
304 indblock = from_coh_ulong(indblock);
305 if (!indblock)
306 return 0;
307 sb = inode->i_sb;
308 indbh = bread(inode->i_dev,indblock+sb->sv_block_base,BLOCK_SIZE);
309 if (indtmp != *p) {
310 brelse(indbh);
311 return 1;
312 }
313 if (!indbh) {
314 *p = 0;
315 *dirt = 1;
316 return 0;
317 }
318 repeat:
319 if (inode->i_size < offset)
320 i = 0;
321 else
322 i = (inode->i_size - offset + BLOCK_SIZE-1) / BLOCK_SIZE;
323 for (; i < IND_PER_BLOCK; i++) {
324 ind = ((sysv_zone_t *) indbh->b_data) + i;
325 block = tmp = *ind;
326 if (sb->sv_convert)
327 block = from_coh_ulong(block);
328 if (!block)
329 continue;
330 bh = get_hash_table(inode->i_dev,block+sb->sv_block_base,BLOCK_SIZE);
331 if (i*BLOCK_SIZE + offset < inode->i_size) {
332 brelse(bh);
333 goto repeat;
334 }
335 if ((bh && bh->b_count != 1) || (tmp != *ind)) {
336 retry = 1;
337 brelse(bh);
338 continue;
339 }
340 *ind = 0;
341 mark_buffer_dirty(indbh, 1);
342 brelse(bh);
343 sysv_free_block(sb,block);
344 }
345 for (i = 0; i < IND_PER_BLOCK; i++)
346 if (((sysv_zone_t *) indbh->b_data)[i])
347 goto done;
348 if ((indbh->b_count != 1) || (indtmp != *p)) {
349 brelse(indbh);
350 return 1;
351 }
352 *p = 0;
353 *dirt = 1;
354 sysv_free_block(sb,indblock);
355 done:
356 brelse(indbh);
357 return retry;
358 }
359
360 static int trunc_dindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
361 {
362 unsigned long indtmp, indblock;
363 struct super_block * sb;
364 struct buffer_head * indbh;
365 unsigned int i;
366 sysv_zone_t * ind;
367 unsigned long tmp, block;
368 int retry = 0;
369
370 indblock = indtmp = *p;
371 if (convert)
372 indblock = from_coh_ulong(indblock);
373 if (!indblock)
374 return 0;
375 sb = inode->i_sb;
376 indbh = bread(inode->i_dev,indblock+sb->sv_block_base,BLOCK_SIZE);
377 if (indtmp != *p) {
378 brelse(indbh);
379 return 1;
380 }
381 if (!indbh) {
382 *p = 0;
383 *dirt = 1;
384 return 0;
385 }
386 if (inode->i_size < offset)
387 i = 0;
388 else
389 i = (inode->i_size - offset + IND_PER_BLOCK*BLOCK_SIZE-1) / (IND_PER_BLOCK*BLOCK_SIZE);
390 for (; i < IND_PER_BLOCK; i++) {
391 ind = ((sysv_zone_t *) indbh->b_data) + i;
392 block = tmp = *ind;
393 if (sb->sv_convert)
394 block = from_coh_ulong(block);
395 if (!block)
396 continue;
397 retry |= trunc_indirect(inode,offset+i*IND_PER_BLOCK,ind,sb->sv_convert,&indbh->b_dirt);
398 }
399 for (i = 0; i < IND_PER_BLOCK; i++)
400 if (((sysv_zone_t *) indbh->b_data)[i])
401 goto done;
402 if ((indbh->b_count != 1) || (indtmp != *p)) {
403 brelse(indbh);
404 return 1;
405 }
406 *p = 0;
407 *dirt = 1;
408 sysv_free_block(sb,indblock);
409 done:
410 brelse(indbh);
411 return retry;
412 }
413
414 static int trunc_tindirect(struct inode * inode, unsigned long offset, unsigned long * p, int convert, unsigned char * dirt)
415 {
416 unsigned long indtmp, indblock;
417 struct super_block * sb;
418 struct buffer_head * indbh;
419 unsigned int i;
420 sysv_zone_t * ind;
421 unsigned long tmp, block;
422 int retry = 0;
423
424 indblock = indtmp = *p;
425 if (convert)
426 indblock = from_coh_ulong(indblock);
427 if (!indblock)
428 return 0;
429 sb = inode->i_sb;
430 indbh = bread(inode->i_dev,indblock+sb->sv_block_base,BLOCK_SIZE);
431 if (indtmp != *p) {
432 brelse(indbh);
433 return 1;
434 }
435 if (!indbh) {
436 *p = 0;
437 *dirt = 1;
438 return 0;
439 }
440 if (inode->i_size < offset)
441 i = 0;
442 else
443 i = (inode->i_size - offset + IND_PER_BLOCK*IND_PER_BLOCK*BLOCK_SIZE-1) / (IND_PER_BLOCK*IND_PER_BLOCK*BLOCK_SIZE);
444 for (; i < IND_PER_BLOCK; i++) {
445 ind = ((sysv_zone_t *) indbh->b_data) + i;
446 block = tmp = *ind;
447 if (sb->sv_convert)
448 block = from_coh_ulong(block);
449 if (!block)
450 continue;
451 retry |= trunc_dindirect(inode,offset+i*IND_PER_BLOCK*IND_PER_BLOCK,ind,sb->sv_convert,&indbh->b_dirt);
452 }
453 for (i = 0; i < IND_PER_BLOCK; i++)
454 if (((sysv_zone_t *) indbh->b_data)[i])
455 goto done;
456 if ((indbh->b_count != 1) || (indtmp != *p)) {
457 brelse(indbh);
458 return 1;
459 }
460 *p = 0;
461 *dirt = 1;
462 sysv_free_block(sb,indblock);
463 done:
464 brelse(indbh);
465 return retry;
466 }
467
468 static int trunc_all(struct inode * inode)
469 {
470 return trunc_direct(inode)
471 | trunc_indirect(inode,10*BLOCK_SIZE,&inode->u.sysv_i.i_data[10],0,&inode->i_dirt)
472 | trunc_dindirect(inode,(10+IND_PER_BLOCK)*BLOCK_SIZE,&inode->u.sysv_i.i_data[11],0,&inode->i_dirt)
473 | trunc_tindirect(inode,(10+IND_PER_BLOCK+IND_PER_BLOCK*IND_PER_BLOCK)*BLOCK_SIZE,&inode->u.sysv_i.i_data[12],0,&inode->i_dirt);
474 }
475
476
477 void sysv_truncate(struct inode * inode)
478 {
479
480
481
482
483
484
485
486
487 if (S_ISLNK(inode->i_mode))
488 printk("sysv_truncate: truncating symbolic link\n");
489 else if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
490 return;
491 if (inode->i_sb->sv_block_size_ratio_bits > 0) {
492 coh_lock_inode(inode);
493 while (coh_trunc_all(inode)) {
494 current->counter = 0;
495 schedule();
496 }
497 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
498 inode->i_dirt = 1;
499 coh_unlock_inode(inode);
500 } else {
501 while (trunc_all(inode)) {
502 current->counter = 0;
503 schedule();
504 }
505 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
506 inode->i_dirt = 1;
507 }
508 }