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, 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, 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, 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, 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 tmp = *p;
185 *p = 0;
186 inode->i_blocks -= blocks;
187 inode->i_dirt = 1;
188 ext2_free_blocks (inode, tmp, 1);
189 }
190 if (IS_SYNC(inode) && buffer_dirty(ind_bh)) {
191 ll_rw_block (WRITE, 1, &ind_bh);
192 wait_on_buffer (ind_bh);
193 }
194 brelse (ind_bh);
195 return retry;
196 }
197
198 static int trunc_dindirect (struct inode * inode, int offset,
199 u32 * p)
200 {
201 int i, tmp;
202 struct buffer_head * dind_bh;
203 u32 * dind;
204 int retry = 0;
205 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
206 int blocks = inode->i_sb->s_blocksize / 512;
207 #define DINDIRECT_BLOCK (((int)DIRECT_BLOCK - offset) / addr_per_block)
208 int dindirect_block = DINDIRECT_BLOCK;
209
210 tmp = *p;
211 if (!tmp)
212 return 0;
213 dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
214 if (tmp != *p) {
215 brelse (dind_bh);
216 return 1;
217 }
218 if (!dind_bh) {
219 *p = 0;
220 return 0;
221 }
222 repeat:
223 for (i = dindirect_block ; i < addr_per_block ; i++) {
224 if (i < 0)
225 i = 0;
226 if (i < dindirect_block)
227 goto repeat;
228 dind = i + (u32 *) dind_bh->b_data;
229 tmp = *dind;
230 if (!tmp)
231 continue;
232 retry |= trunc_indirect (inode, offset + (i * addr_per_block),
233 dind);
234 mark_buffer_dirty(dind_bh, 1);
235 }
236 dind = (u32 *) dind_bh->b_data;
237 for (i = 0; i < addr_per_block; i++)
238 if (*(dind++))
239 break;
240 if (i >= addr_per_block)
241 if (dind_bh->b_count != 1)
242 retry = 1;
243 else {
244 tmp = *p;
245 *p = 0;
246 inode->i_blocks -= blocks;
247 inode->i_dirt = 1;
248 ext2_free_blocks (inode, tmp, 1);
249 }
250 if (IS_SYNC(inode) && buffer_dirty(dind_bh)) {
251 ll_rw_block (WRITE, 1, &dind_bh);
252 wait_on_buffer (dind_bh);
253 }
254 brelse (dind_bh);
255 return retry;
256 }
257
258 static int trunc_tindirect (struct inode * inode)
259 {
260 int i, tmp;
261 struct buffer_head * tind_bh;
262 u32 * tind, * p;
263 int retry = 0;
264 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
265 int blocks = inode->i_sb->s_blocksize / 512;
266 #define TINDIRECT_BLOCK (((int)DIRECT_BLOCK - (addr_per_block * addr_per_block + \
267 addr_per_block + EXT2_NDIR_BLOCKS)) / \
268 (addr_per_block * addr_per_block))
269 int tindirect_block = TINDIRECT_BLOCK;
270
271 p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
272 if (!(tmp = *p))
273 return 0;
274 tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
275 if (tmp != *p) {
276 brelse (tind_bh);
277 return 1;
278 }
279 if (!tind_bh) {
280 *p = 0;
281 return 0;
282 }
283 repeat:
284 for (i = tindirect_block ; i < addr_per_block ; i++) {
285 if (i < 0)
286 i = 0;
287 if (i < tindirect_block)
288 goto repeat;
289 tind = i + (u32 *) tind_bh->b_data;
290 retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
291 addr_per_block + (i + 1) * addr_per_block * addr_per_block,
292 tind);
293 mark_buffer_dirty(tind_bh, 1);
294 }
295 tind = (u32 *) tind_bh->b_data;
296 for (i = 0; i < addr_per_block; i++)
297 if (*(tind++))
298 break;
299 if (i >= addr_per_block)
300 if (tind_bh->b_count != 1)
301 retry = 1;
302 else {
303 tmp = *p;
304 *p = 0;
305 inode->i_blocks -= blocks;
306 inode->i_dirt = 1;
307 ext2_free_blocks (inode, tmp, 1);
308 }
309 if (IS_SYNC(inode) && buffer_dirty(tind_bh)) {
310 ll_rw_block (WRITE, 1, &tind_bh);
311 wait_on_buffer (tind_bh);
312 }
313 brelse (tind_bh);
314 return retry;
315 }
316
317 void ext2_truncate (struct inode * inode)
318 {
319 int retry;
320 struct buffer_head * bh;
321 int err;
322 int offset;
323
324 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
325 S_ISLNK(inode->i_mode)))
326 return;
327 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
328 return;
329 ext2_discard_prealloc(inode);
330 while (1) {
331 retry = trunc_direct(inode);
332 retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
333 (u32 *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
334 retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
335 EXT2_ADDR_PER_BLOCK(inode->i_sb),
336 (u32 *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
337 retry |= trunc_tindirect (inode);
338 if (!retry)
339 break;
340 if (IS_SYNC(inode) && inode->i_dirt)
341 ext2_sync_inode (inode);
342 current->counter = 0;
343 schedule ();
344 }
345
346
347
348
349
350
351 offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
352 if (offset) {
353 bh = ext2_bread (inode,
354 inode->i_size >> EXT2_BLOCK_SIZE_BITS(inode->i_sb),
355 0, &err);
356 if (bh) {
357 memset (bh->b_data + offset, 0,
358 inode->i_sb->s_blocksize - offset);
359 mark_buffer_dirty (bh, 0);
360 brelse (bh);
361 }
362 }
363 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
364 inode->i_dirt = 1;
365 }