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