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 brelse (bh);
89 if (free_count == 0) {
90 block_to_free = tmp;
91 free_count++;
92 } else if (free_count > 0 && block_to_free == tmp - free_count)
93 free_count++;
94 else {
95 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
96 block_to_free = tmp;
97 free_count = 1;
98 }
99
100 }
101 if (free_count > 0)
102 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
103 return retry;
104 }
105
106 static int trunc_indirect (struct inode * inode, int offset, u32 * p)
107 {
108 int i, tmp;
109 struct buffer_head * bh;
110 struct buffer_head * ind_bh;
111 u32 * ind;
112 unsigned long block_to_free = 0;
113 unsigned long free_count = 0;
114 int retry = 0;
115 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
116 int blocks = inode->i_sb->s_blocksize / 512;
117 #define INDIRECT_BLOCK ((int)DIRECT_BLOCK - offset)
118 int indirect_block = INDIRECT_BLOCK;
119
120 tmp = *p;
121 if (!tmp)
122 return 0;
123 ind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
124 if (tmp != *p) {
125 brelse (ind_bh);
126 return 1;
127 }
128 if (!ind_bh) {
129 *p = 0;
130 return 0;
131 }
132 repeat:
133 for (i = indirect_block ; i < addr_per_block ; i++) {
134 if (i < 0)
135 i = 0;
136 if (i < indirect_block)
137 goto repeat;
138 ind = i + (u32 *) ind_bh->b_data;
139 tmp = *ind;
140 if (!tmp)
141 continue;
142 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL)
143 bh = getblk (inode->i_dev, tmp,
144 inode->i_sb->s_blocksize);
145 else
146 bh = get_hash_table (inode->i_dev, tmp,
147 inode->i_sb->s_blocksize);
148 if (i < indirect_block) {
149 brelse (bh);
150 goto repeat;
151 }
152 if ((bh && bh->b_count != 1) || tmp != *ind) {
153 retry = 1;
154 brelse (bh);
155 continue;
156 }
157 *ind = 0;
158 mark_buffer_dirty(ind_bh, 1);
159 if (inode->u.ext2_i.i_flags & EXT2_SECRM_FL) {
160 memset(bh->b_data, RANDOM_INT, inode->i_sb->s_blocksize);
161 mark_buffer_dirty(bh, 1);
162 }
163 brelse (bh);
164 if (free_count == 0) {
165 block_to_free = tmp;
166 free_count++;
167 } else if (free_count > 0 && block_to_free == tmp - free_count)
168 free_count++;
169 else {
170 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
171 block_to_free = tmp;
172 free_count = 1;
173 }
174
175 inode->i_blocks -= blocks;
176 inode->i_dirt = 1;
177 }
178 if (free_count > 0)
179 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
180 ind = (u32 *) ind_bh->b_data;
181 for (i = 0; i < addr_per_block; i++)
182 if (*(ind++))
183 break;
184 if (i >= addr_per_block)
185 if (ind_bh->b_count != 1)
186 retry = 1;
187 else {
188 tmp = *p;
189 *p = 0;
190 inode->i_blocks -= blocks;
191 inode->i_dirt = 1;
192 ext2_free_blocks (inode->i_sb, tmp, 1);
193 }
194 if (IS_SYNC(inode) && ind_bh->b_dirt) {
195 ll_rw_block (WRITE, 1, &ind_bh);
196 wait_on_buffer (ind_bh);
197 }
198 brelse (ind_bh);
199 return retry;
200 }
201
202 static int trunc_dindirect (struct inode * inode, int offset,
203 u32 * p)
204 {
205 int i, tmp;
206 struct buffer_head * dind_bh;
207 u32 * dind;
208 int retry = 0;
209 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
210 int blocks = inode->i_sb->s_blocksize / 512;
211 #define DINDIRECT_BLOCK (((int)DIRECT_BLOCK - offset) / addr_per_block)
212 int dindirect_block = DINDIRECT_BLOCK;
213
214 tmp = *p;
215 if (!tmp)
216 return 0;
217 dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
218 if (tmp != *p) {
219 brelse (dind_bh);
220 return 1;
221 }
222 if (!dind_bh) {
223 *p = 0;
224 return 0;
225 }
226 repeat:
227 for (i = dindirect_block ; i < addr_per_block ; i++) {
228 if (i < 0)
229 i = 0;
230 if (i < dindirect_block)
231 goto repeat;
232 dind = i + (u32 *) dind_bh->b_data;
233 tmp = *dind;
234 if (!tmp)
235 continue;
236 retry |= trunc_indirect (inode, offset + (i * addr_per_block),
237 dind);
238 mark_buffer_dirty(dind_bh, 1);
239 }
240 dind = (u32 *) dind_bh->b_data;
241 for (i = 0; i < addr_per_block; i++)
242 if (*(dind++))
243 break;
244 if (i >= addr_per_block)
245 if (dind_bh->b_count != 1)
246 retry = 1;
247 else {
248 tmp = *p;
249 *p = 0;
250 inode->i_blocks -= blocks;
251 inode->i_dirt = 1;
252 ext2_free_blocks (inode->i_sb, tmp, 1);
253 }
254 if (IS_SYNC(inode) && dind_bh->b_dirt) {
255 ll_rw_block (WRITE, 1, &dind_bh);
256 wait_on_buffer (dind_bh);
257 }
258 brelse (dind_bh);
259 return retry;
260 }
261
262 static int trunc_tindirect (struct inode * inode)
263 {
264 int i, tmp;
265 struct buffer_head * tind_bh;
266 u32 * tind, * p;
267 int retry = 0;
268 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
269 int blocks = inode->i_sb->s_blocksize / 512;
270 #define TINDIRECT_BLOCK (((int)DIRECT_BLOCK - (addr_per_block * addr_per_block + \
271 addr_per_block + EXT2_NDIR_BLOCKS)) / \
272 (addr_per_block * addr_per_block))
273 int tindirect_block = TINDIRECT_BLOCK;
274
275 p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
276 if (!(tmp = *p))
277 return 0;
278 tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
279 if (tmp != *p) {
280 brelse (tind_bh);
281 return 1;
282 }
283 if (!tind_bh) {
284 *p = 0;
285 return 0;
286 }
287 repeat:
288 for (i = tindirect_block ; i < addr_per_block ; i++) {
289 if (i < 0)
290 i = 0;
291 if (i < tindirect_block)
292 goto repeat;
293 tind = i + (u32 *) tind_bh->b_data;
294 retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
295 addr_per_block + (i + 1) * addr_per_block * addr_per_block,
296 tind);
297 mark_buffer_dirty(tind_bh, 1);
298 }
299 tind = (u32 *) tind_bh->b_data;
300 for (i = 0; i < addr_per_block; i++)
301 if (*(tind++))
302 break;
303 if (i >= addr_per_block)
304 if (tind_bh->b_count != 1)
305 retry = 1;
306 else {
307 tmp = *p;
308 *p = 0;
309 inode->i_blocks -= blocks;
310 inode->i_dirt = 1;
311 ext2_free_blocks (inode->i_sb, tmp, 1);
312 }
313 if (IS_SYNC(inode) && tind_bh->b_dirt) {
314 ll_rw_block (WRITE, 1, &tind_bh);
315 wait_on_buffer (tind_bh);
316 }
317 brelse (tind_bh);
318 return retry;
319 }
320
321 void ext2_truncate (struct inode * inode)
322 {
323 int retry;
324 struct buffer_head * bh;
325 int err;
326 int offset;
327
328 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
329 S_ISLNK(inode->i_mode)))
330 return;
331 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
332 return;
333 ext2_discard_prealloc(inode);
334 while (1) {
335 down(&inode->i_sem);
336 retry = trunc_direct(inode);
337 retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
338 (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
339 retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
340 EXT2_ADDR_PER_BLOCK(inode->i_sb),
341 (u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
342 retry |= trunc_tindirect (inode);
343 up(&inode->i_sem);
344 if (!retry)
345 break;
346 if (IS_SYNC(inode) && inode->i_dirt)
347 ext2_sync_inode (inode);
348 current->counter = 0;
349 schedule ();
350 }
351
352
353
354
355
356
357 offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
358 if (offset) {
359 bh = ext2_bread (inode,
360 inode->i_size >> EXT2_BLOCK_SIZE_BITS(inode->i_sb),
361 0, &err);
362 if (bh) {
363 memset (bh->b_data + offset, 0,
364 inode->i_sb->s_blocksize - offset);
365 mark_buffer_dirty (bh, 0);
366 brelse (bh);
367 }
368 }
369 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
370 inode->i_dirt = 1;
371 }