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