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 = get_hash_table (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 = get_hash_table (inode->i_dev, tmp,
104 inode->i_sb->s_blocksize);
105 if (i < indirect_block) {
106 brelse (bh);
107 goto repeat;
108 }
109 if ((bh && bh->b_count != 1) || tmp != *ind) {
110 retry = 1;
111 brelse (bh);
112 continue;
113 }
114 *ind = 0;
115 ind_bh->b_dirt = 1;
116 brelse (bh);
117 ext2_free_block (inode->i_sb, tmp);
118 inode->i_blocks -= blocks;
119 inode->i_dirt = 1;
120 }
121 ind = (unsigned long *) ind_bh->b_data;
122 for (i = 0; i < addr_per_block; i++)
123 if (*(ind++))
124 break;
125 if (i >= addr_per_block)
126 if (ind_bh->b_count != 1)
127 retry = 1;
128 else {
129 tmp = *p;
130 *p = 0;
131 inode->i_blocks -= blocks;
132 inode->i_dirt = 1;
133 ext2_free_block (inode->i_sb, tmp);
134 }
135 brelse (ind_bh);
136 return retry;
137 }
138
139 static int trunc_dindirect (struct inode * inode, int offset,
140 unsigned long * p)
141 {
142 int i, tmp;
143 struct buffer_head * dind_bh;
144 unsigned long * dind;
145 int retry = 0;
146 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
147 int blocks = inode->i_sb->s_blocksize / 512;
148 #define DINDIRECT_BLOCK (((int)DIRECT_BLOCK - offset) / addr_per_block)
149 int dindirect_block = DINDIRECT_BLOCK;
150
151 tmp = *p;
152 if (!tmp)
153 return 0;
154 dind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
155 if (tmp != *p) {
156 brelse (dind_bh);
157 return 1;
158 }
159 if (!dind_bh) {
160 *p = 0;
161 return 0;
162 }
163 repeat:
164 for (i = dindirect_block ; i < addr_per_block ; i ++) {
165 if (i < 0)
166 i = 0;
167 if (i < dindirect_block)
168 goto repeat;
169 dind = i + (unsigned long *) dind_bh->b_data;
170 tmp = *dind;
171 if (!tmp)
172 continue;
173 retry |= trunc_indirect (inode, offset + (i * addr_per_block),
174 dind);
175 dind_bh->b_dirt = 1;
176 }
177 dind = (unsigned long *) dind_bh->b_data;
178 for (i = 0; i < addr_per_block; i++)
179 if (*(dind++))
180 break;
181 if (i >= addr_per_block)
182 if (dind_bh->b_count != 1)
183 retry = 1;
184 else {
185 tmp = *p;
186 *p = 0;
187 inode->i_blocks -= blocks;
188 inode->i_dirt = 1;
189 ext2_free_block (inode->i_sb, tmp);
190 }
191 brelse (dind_bh);
192 return retry;
193 }
194
195 static int trunc_tindirect (struct inode * inode)
196 {
197 int i, tmp;
198 struct buffer_head * tind_bh;
199 unsigned long * tind, * p;
200 int retry = 0;
201 int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
202 int blocks = inode->i_sb->s_blocksize / 512;
203 #define TINDIRECT_BLOCK (((int)DIRECT_BLOCK - (addr_per_block * addr_per_block + \
204 addr_per_block + EXT2_NDIR_BLOCKS)) / \
205 (addr_per_block * addr_per_block))
206 int tindirect_block = TINDIRECT_BLOCK;
207
208 p = inode->u.ext2_i.i_data + EXT2_TIND_BLOCK;
209 if (!(tmp = *p))
210 return 0;
211 tind_bh = bread (inode->i_dev, tmp, inode->i_sb->s_blocksize);
212 if (tmp != *p) {
213 brelse (tind_bh);
214 return 1;
215 }
216 if (!tind_bh) {
217 *p = 0;
218 return 0;
219 }
220 repeat:
221 for (i = tindirect_block ; i < addr_per_block ; i ++) {
222 if (i < 0)
223 i = 0;
224 if (i < tindirect_block)
225 goto repeat;
226 tind = i + (unsigned long *) tind_bh->b_data;
227 retry |= trunc_dindirect(inode, EXT2_NDIR_BLOCKS +
228
229
230 addr_per_block + (i + 1) * addr_per_block * addr_per_block,
231 tind);
232 tind_bh->b_dirt = 1;
233 }
234 tind = (unsigned long *) tind_bh->b_data;
235 for (i = 0; i < addr_per_block; i++)
236 if (*(tind++))
237 break;
238 if (i >= addr_per_block)
239 if (tind_bh->b_count != 1)
240 retry = 1;
241 else {
242 tmp = *p;
243 *p = 0;
244 inode->i_blocks -= blocks;
245 inode->i_dirt = 1;
246 ext2_free_block (inode->i_sb, tmp);
247 }
248 brelse (tind_bh);
249 return retry;
250 }
251
252 void ext2_truncate (struct inode * inode)
253 {
254 int retry;
255
256 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
257 S_ISLNK(inode->i_mode)))
258 return;
259 while (1) {
260 retry = trunc_direct(inode);
261 retry |= trunc_indirect (inode, EXT2_IND_BLOCK,
262 (unsigned long *) &inode->u.ext2_i.i_data[EXT2_IND_BLOCK]);
263 retry |= trunc_dindirect (inode, EXT2_IND_BLOCK +
264 EXT2_ADDR_PER_BLOCK(inode->i_sb),
265 (unsigned long *) &inode->u.ext2_i.i_data[EXT2_DIND_BLOCK]);
266 retry |= trunc_tindirect (inode);
267 if (!retry)
268 break;
269 current->counter = 0;
270 schedule ();
271 }
272 inode->i_mtime = inode->i_ctime = CURRENT_TIME;
273 inode->i_dirt = 1;
274 }
275
276
277
278
279
280
281 void ext2_release (struct inode * inode, struct file * filp)
282 {
283 printk ("ext2_release not implemented\n");
284 }