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 #if 0
31
32
33
34
35
36
37
38
39
40
41 static int ext2_secrm_seed = 152;
42
43 #define RANDOM_INT (ext2_secrm_seed = ext2_secrm_seed * 69069l +1)
44 #endif
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 static int trunc_direct (struct inode * inode)
60 {
61 u32 * p;
62 int i, tmp;
63 struct buffer_head * bh;
64 unsigned long block_to_free = 0;
65 unsigned long free_count = 0;
66 int retry = 0;
67 int blocks = inode->i_sb->s_blocksize / 512;
68 #define DIRECT_BLOCK ((inode->i_size + inode->i_sb->s_blocksize - 1) / \
69 inode->i_sb->s_blocksize)
70 int direct_block = DIRECT_BLOCK;
71
72 repeat:
73 for (i = direct_block ; i < EXT2_NDIR_BLOCKS ; i++) {
74 p = inode->u.ext2_i.i_data + i;
75 tmp = *p;
76 if (!tmp)
77 continue;
78 bh = get_hash_table (inode->i_dev, tmp,
79 inode->i_sb->s_blocksize);
80 if (i < direct_block) {
81 brelse (bh);
82 goto repeat;
83 }
84 if ((bh && bh->b_count != 1) || tmp != *p) {
85 retry = 1;
86 brelse (bh);
87 continue;
88 }
89 *p = 0;
90 inode->i_blocks -= blocks;
91 inode->i_dirt = 1;
92 bforget(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 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 bforget(bh);
160 if (free_count == 0) {
161 block_to_free = tmp;
162 free_count++;
163 } else if (free_count > 0 && block_to_free == tmp - free_count)
164 free_count++;
165 else {
166 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
167 block_to_free = tmp;
168 free_count = 1;
169 }
170
171 inode->i_blocks -= blocks;
172 inode->i_dirt = 1;
173 }
174 if (free_count > 0)
175 ext2_free_blocks (inode->i_sb, block_to_free, free_count);
176 ind = (u32 *) ind_bh->b_data;
177 for (i = 0; i < addr_per_block; i++)
178 if (*(ind++))
179 break;
180 if (i >= addr_per_block)
181 if (ind_bh->b_count != 1)
182 retry = 1;
183 else {
184 ind_bh->b_reuse = 1;
185 tmp = *p;
186 *p = 0;
187 inode->i_blocks -= blocks;
188 inode->i_dirt = 1;
189 ext2_free_blocks (inode->i_sb, tmp, 1);
190 }
191 if (IS_SYNC(inode) && ind_bh->b_dirt) {
192 ll_rw_block (WRITE, 1, &ind_bh);
193 wait_on_buffer (ind_bh);
194 }
195 brelse (ind_bh);
196 return retry;
197 }
198
199 static int trunc_dindirect (struct inode * inode, int offset,
200 u32 * p)
201 {
202 int i, tmp;
203 struct buffer_head * dind_bh;
204 u32 * dind;
205 int retry = 0;
206 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
207 int blocks = inode->i_sb->s_blocksize / 512;
208 #define DINDIRECT_BLOCK (((int)DIRECT_BLOCK - offset) / addr_per_block)
209 int dindirect_block = DINDIRECT_BLOCK;
210
211 tmp = *p;
212 if (!tmp)
213 return 0;
214 dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
215 if (tmp != *p) {
216 brelse (dind_bh);
217 return 1;
218 }
219 if (!dind_bh) {
220 *p = 0;
221 return 0;
222 }
223 repeat:
224 for (i = dindirect_block ; i < addr_per_block ; i++) {
225 if (i < 0)
226 i = 0;
227 if (i < dindirect_block)
228 goto repeat;
229 dind = i + (u32 *) dind_bh->b_data;
230 tmp = *dind;
231 if (!tmp)
232 continue;
233 retry |= trunc_indirect (inode, offset + (i * addr_per_block),
234 dind);
235 mark_buffer_dirty(dind_bh, 1);
236 }
237 dind = (u32 *) dind_bh->b_data;
238 for (i = 0; i < addr_per_block; i++)
239 if (*(dind++))
240 break;
241 if (i >= addr_per_block)
242 if (dind_bh->b_count != 1)
243 retry = 1;
244 else {
245 dind_bh->b_reuse = 1;
246 tmp = *p;
247 *p = 0;
248 inode->i_blocks -= blocks;
249 inode->i_dirt = 1;
250 ext2_free_blocks (inode->i_sb, tmp, 1);
251 }
252 if (IS_SYNC(inode) && dind_bh->b_dirt) {
253 ll_rw_block (WRITE, 1, &dind_bh);
254 wait_on_buffer (dind_bh);
255 }
256 brelse (dind_bh);
257 return retry;
258 }
259
260 static int trunc_tindirect (struct inode * inode)
261 {
262 int i, tmp;
263 struct buffer_head * tind_bh;
264 u32 * tind, * p;
265 int retry = 0;
266 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
267 int blocks = inode->i_sb->s_blocksize / 512;
268 #define TINDIRECT_BLOCK (((int)DIRECT_BLOCK - (addr_per_block * addr_per_block + \
269 addr_per_block + EXT2_NDIR_BLOCKS)) / \
270 (addr_per_block * addr_per_block))
271 int tindirect_block = TINDIRECT_BLOCK;
272
273 p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
274 if (!(tmp = *p))
275 return 0;
276 tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
277 if (tmp != *p) {
278 brelse (tind_bh);
279 return 1;
280 }
281 if (!tind_bh) {
282 *p = 0;
283 return 0;
284 }
285 repeat:
286 for (i = tindirect_block ; i < addr_per_block ; i++) {
287 if (i < 0)
288 i = 0;
289 if (i < tindirect_block)
290 goto repeat;
291 tind = i + (u32 *) tind_bh->b_data;
292 retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
293 addr_per_block + (i + 1) * addr_per_block * addr_per_block,
294 tind);
295 mark_buffer_dirty(tind_bh, 1);
296 }
297 tind = (u32 *) tind_bh->b_data;
298 for (i = 0; i < addr_per_block; i++)
299 if (*(tind++))
300 break;
301 if (i >= addr_per_block)
302 if (tind_bh->b_count != 1)
303 retry = 1;
304 else {
305 tind_bh->b_reuse = 1;
306 tmp = *p;
307 *p = 0;
308 inode->i_blocks -= blocks;
309 inode->i_dirt = 1;
310 ext2_free_blocks (inode->i_sb, tmp, 1);
311 }
312 if (IS_SYNC(inode) && tind_bh->b_dirt) {
313 ll_rw_block (WRITE, 1, &tind_bh);
314 wait_on_buffer (tind_bh);
315 }
316 brelse (tind_bh);
317 return retry;
318 }
319
320 void ext2_truncate (struct inode * inode)
321 {
322 int retry;
323 struct buffer_head * bh;
324 int err;
325 int offset;
326
327 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
328 S_ISLNK(inode->i_mode)))
329 return;
330 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
331 return;
332 ext2_discard_prealloc(inode);
333 while (1) {
334 down(&inode->i_sem);
335 retry = trunc_direct(inode);
336 retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
337 (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
338 retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
339 EXT2_ADDR_PER_BLOCK(inode->i_sb),
340 (u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
341 retry |= trunc_tindirect (inode);
342 up(&inode->i_sem);
343 if (!retry)
344 break;
345 if (IS_SYNC(inode) && inode->i_dirt)
346 ext2_sync_inode (inode);
347 current->counter = 0;
348 schedule ();
349 }
350
351
352
353
354
355
356 offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
357 if (offset) {
358 bh = ext2_bread (inode,
359 inode->i_size >> EXT2_BLOCK_SIZE_BITS(inode->i_sb),
360 0, &err);
361 if (bh) {
362 memset (bh->b_data + offset, 0,
363 inode->i_sb->s_blocksize - offset);
364 mark_buffer_dirty (bh, 0);
365 brelse (bh);
366 }
367 }
368 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
369 inode->i_dirt = 1;
370 }