This source file includes following definitions.
- trunc_direct
- trunc_indirect
- trunc_dindirect
- trunc_tindirect
- ext2_truncate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <linux/errno.h>
22 #include <linux/fs.h>
23 #include <linux/ext2_fs.h>
24 #include <linux/fcntl.h>
25 #include <linux/sched.h>
26 #include <linux/stat.h>
27 #include <linux/locks.h>
28 #include <linux/string.h>
29
30 static int ext2_secrm_seed = 152;
31
32 #define RANDOM_INT (ext2_secrm_seed = ext2_secrm_seed * 69069l +1)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 static int trunc_direct (struct inode * inode)
48 {
49 u32 * p;
50 int i, tmp;
51 struct buffer_head * bh;
52 unsigned long block_to_free = 0;
53 unsigned long free_count = 0;
54 int retry = 0;
55 int blocks = inode->i_sb->s_blocksize / 512;
56 #define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \
57 inode->i_sb->s_blocksize)
58 int direct_block = DIRECT_BLOCK;
59
60 repeat:
61 for (i = direct_block ; i < EXT2_NDIR_BLOCKS ; i++) {
62 p = inode->u.ext2_i.i_data + i;
63 tmp = *p;
64 if (!tmp)
65 continue;
66 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL)
67 bh = getblk (inode->i_dev, tmp,
68 inode->i_sb->s_blocksize);
69 else
70 bh = get_hash_table (inode->i_dev, tmp,
71 inode->i_sb->s_blocksize);
72 if (i < direct_block) {
73 brelse (bh);
74 goto repeat;
75 }
76 if ((bh && bh->b_count != 1) || tmp != *p) {
77 retry = 1;
78 brelse (bh);
79 continue;
80 }
81 *p = 0;
82 inode->i_blocks -= blocks;
83 inode->i_dirt = 1;
84 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
85 memset(bh->b_data, RANDOM_INT, inode->i_sb->s_blocksize);
86 mark_buffer_dirty(bh, 1);
87 }
88 else if (bh) {
89 mark_buffer_clean(bh);
90 bh->b_reuse = 1;
91 }
92 brelse (bh);
93 if (free_count == 0) {
94 block_to_free = tmp;
95 free_count++;
96 } else if (free_count > 0 && block_to_free == tmp - free_count)
97 free_count++;
98 else {
99 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
100 block_to_free = tmp;
101 free_count = 1;
102 }
103
104 }
105 if (free_count > 0)
106 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
107 return retry;
108 }
109
110 static int trunc_indirect (struct inode * inode, int offset, u32 * p)
111 {
112 int i, tmp;
113 struct buffer_head * bh;
114 struct buffer_head * ind_bh;
115 u32 * ind;
116 unsigned long block_to_free = 0;
117 unsigned long free_count = 0;
118 int retry = 0;
119 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
120 int blocks = inode->i_sb->s_blocksize / 512;
121 #define INDIRECT_BLOCK ((int)DIRECT_BLOCK - offset)
122 int indirect_block = INDIRECT_BLOCK;
123
124 tmp = *p;
125 if (!tmp)
126 return 0;
127 ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
128 if (tmp != *p) {
129 brelse (ind_bh);
130 return 1;
131 }
132 if (!ind_bh) {
133 *p = 0;
134 return 0;
135 }
136 repeat:
137 for (i = indirect_block ; i < addr_per_block ; i++) {
138 if (i < 0)
139 i = 0;
140 if (i < indirect_block)
141 goto repeat;
142 ind = i + (u32 *) ind_bh->b_data;
143 tmp = *ind;
144 if (!tmp)
145 continue;
146 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL)
147 bh = getblk (inode->i_dev, tmp,
148 inode->i_sb->s_blocksize);
149 else
150 bh = get_hash_table (inode->i_dev, tmp,
151 inode->i_sb->s_blocksize);
152 if (i < indirect_block) {
153 brelse (bh);
154 goto repeat;
155 }
156 if ((bh && bh->b_count != 1) || tmp != *ind) {
157 retry = 1;
158 brelse (bh);
159 continue;
160 }
161 *ind = 0;
162 mark_buffer_dirty(ind_bh, 1);
163 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
164 memset(bh->b_data, RANDOM_INT, inode->i_sb->s_blocksize);
165 mark_buffer_dirty(bh, 1);
166 }
167 else if (bh) {
168 mark_buffer_clean(bh);
169 bh->b_reuse = 1;
170 }
171 brelse (bh);
172 if (free_count == 0) {
173 block_to_free = tmp;
174 free_count++;
175 } else if (free_count > 0 && block_to_free == tmp - free_count)
176 free_count++;
177 else {
178 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
179 block_to_free = tmp;
180 free_count = 1;
181 }
182
183 inode->i_blocks -= blocks;
184 inode->i_dirt = 1;
185 }
186 if (free_count > 0)
187 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
188 ind = (u32 *) ind_bh->b_data;
189 for (i = 0; i < addr_per_block; i++)
190 if (*(ind++))
191 break;
192 if (i >= addr_per_block)
193 if (ind_bh->b_count != 1)
194 retry = 1;
195 else {
196 ind_bh->b_reuse = 1;
197 tmp = *p;
198 *p = 0;
199 inode->i_blocks -= blocks;
200 inode->i_dirt = 1;
201 ext2_free_blocks (inode->i_sb, tmp, 1);
202 }
203 if (IS_SYNC(inode) && ind_bh->b_dirt) {
204 ll_rw_block (WRITE, 1, &ind_bh);
205 wait_on_buffer (ind_bh);
206 }
207 brelse (ind_bh);
208 return retry;
209 }
210
211 static int trunc_dindirect (struct inode * inode, int offset,
212 u32 * p)
213 {
214 int i, tmp;
215 struct buffer_head * dind_bh;
216 u32 * dind;
217 int retry = 0;
218 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
219 int blocks = inode->i_sb->s_blocksize / 512;
220 #define DINDIRECT_BLOCK (((int)DIRECT_BLOCK - offset) / addr_per_block)
221 int dindirect_block = DINDIRECT_BLOCK;
222
223 tmp = *p;
224 if (!tmp)
225 return 0;
226 dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
227 if (tmp != *p) {
228 brelse (dind_bh);
229 return 1;
230 }
231 if (!dind_bh) {
232 *p = 0;
233 return 0;
234 }
235 repeat:
236 for (i = dindirect_block ; i < addr_per_block ; i++) {
237 if (i < 0)
238 i = 0;
239 if (i < dindirect_block)
240 goto repeat;
241 dind = i + (u32 *) dind_bh->b_data;
242 tmp = *dind;
243 if (!tmp)
244 continue;
245 retry |= trunc_indirect (inode, offset + (i * addr_per_block),
246 dind);
247 mark_buffer_dirty(dind_bh, 1);
248 }
249 dind = (u32 *) dind_bh->b_data;
250 for (i = 0; i < addr_per_block; i++)
251 if (*(dind++))
252 break;
253 if (i >= addr_per_block)
254 if (dind_bh->b_count != 1)
255 retry = 1;
256 else {
257 dind_bh->b_reuse = 1;
258 tmp = *p;
259 *p = 0;
260 inode->i_blocks -= blocks;
261 inode->i_dirt = 1;
262 ext2_free_blocks (inode->i_sb, tmp, 1);
263 }
264 if (IS_SYNC(inode) && dind_bh->b_dirt) {
265 ll_rw_block (WRITE, 1, &dind_bh);
266 wait_on_buffer (dind_bh);
267 }
268 brelse (dind_bh);
269 return retry;
270 }
271
272 static int trunc_tindirect (struct inode * inode)
273 {
274 int i, tmp;
275 struct buffer_head * tind_bh;
276 u32 * tind, * p;
277 int retry = 0;
278 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
279 int blocks = inode->i_sb->s_blocksize / 512;
280 #define TINDIRECT_BLOCK (((int)DIRECT_BLOCK - (addr_per_block * addr_per_block + \
281 addr_per_block + EXT2_NDIR_BLOCKS)) / \
282 (addr_per_block * addr_per_block))
283 int tindirect_block = TINDIRECT_BLOCK;
284
285 p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
286 if (!(tmp = *p))
287 return 0;
288 tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
289 if (tmp != *p) {
290 brelse (tind_bh);
291 return 1;
292 }
293 if (!tind_bh) {
294 *p = 0;
295 return 0;
296 }
297 repeat:
298 for (i = tindirect_block ; i < addr_per_block ; i++) {
299 if (i < 0)
300 i = 0;
301 if (i < tindirect_block)
302 goto repeat;
303 tind = i + (u32 *) tind_bh->b_data;
304 retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
305 addr_per_block + (i + 1) * addr_per_block * addr_per_block,
306 tind);
307 mark_buffer_dirty(tind_bh, 1);
308 }
309 tind = (u32 *) tind_bh->b_data;
310 for (i = 0; i < addr_per_block; i++)
311 if (*(tind++))
312 break;
313 if (i >= addr_per_block)
314 if (tind_bh->b_count != 1)
315 retry = 1;
316 else {
317 tind_bh->b_reuse = 1;
318 tmp = *p;
319 *p = 0;
320 inode->i_blocks -= blocks;
321 inode->i_dirt = 1;
322 ext2_free_blocks (inode->i_sb, tmp, 1);
323 }
324 if (IS_SYNC(inode) && tind_bh->b_dirt) {
325 ll_rw_block (WRITE, 1, &tind_bh);
326 wait_on_buffer (tind_bh);
327 }
328 brelse (tind_bh);
329 return retry;
330 }
331
332 void ext2_truncate (struct inode * inode)
333 {
334 int retry;
335 struct buffer_head * bh;
336 int err;
337 int offset;
338
339 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
340 S_ISLNK(inode->i_mode)))
341 return;
342 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
343 return;
344 ext2_discard_prealloc(inode);
345 while (1) {
346 down(&inode->i_sem);
347 retry = trunc_direct(inode);
348 retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
349 (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
350 retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
351 EXT2_ADDR_PER_BLOCK(inode->i_sb),
352 (u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
353 retry |= trunc_tindirect (inode);
354 up(&inode->i_sem);
355 if (!retry)
356 break;
357 if (IS_SYNC(inode) && inode->i_dirt)
358 ext2_sync_inode (inode);
359 current->counter = 0;
360 schedule ();
361 }
362
363
364
365
366
367
368 offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
369 if (offset) {
370 bh = ext2_bread (inode,
371 inode->i_size >> EXT2_BLOCK_SIZE_BITS(inode->i_sb),
372 0, &err);
373 if (bh) {
374 memset (bh->b_data + offset, 0,
375 inode->i_sb->s_blocksize - offset);
376 mark_buffer_dirty (bh, 0);
377 brelse (bh);
378 }
379 }
380 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
381 inode->i_dirt = 1;
382 }