diff options
Diffstat (limited to 'fs/ufs/truncate.c')
-rw-r--r-- | fs/ufs/truncate.c | 139 |
1 files changed, 75 insertions, 64 deletions
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 0437b0a6fe97..77ed77932aeb 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -30,8 +30,8 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Modified to avoid infinite loop on 2006 by | 33 | * Adoptation to use page cache and UFS2 write support by |
34 | * Evgeniy Dushistov <dushistov@mail.ru> | 34 | * Evgeniy Dushistov <dushistov@mail.ru>, 2006-2007 |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
@@ -63,13 +63,13 @@ | |||
63 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) | 63 | #define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift) |
64 | 64 | ||
65 | 65 | ||
66 | static int ufs_trunc_direct (struct inode * inode) | 66 | static int ufs_trunc_direct(struct inode *inode) |
67 | { | 67 | { |
68 | struct ufs_inode_info *ufsi = UFS_I(inode); | 68 | struct ufs_inode_info *ufsi = UFS_I(inode); |
69 | struct super_block * sb; | 69 | struct super_block * sb; |
70 | struct ufs_sb_private_info * uspi; | 70 | struct ufs_sb_private_info * uspi; |
71 | __fs32 * p; | 71 | void *p; |
72 | unsigned frag1, frag2, frag3, frag4, block1, block2; | 72 | u64 frag1, frag2, frag3, frag4, block1, block2; |
73 | unsigned frag_to_free, free_count; | 73 | unsigned frag_to_free, free_count; |
74 | unsigned i, tmp; | 74 | unsigned i, tmp; |
75 | int retry; | 75 | int retry; |
@@ -91,13 +91,16 @@ static int ufs_trunc_direct (struct inode * inode) | |||
91 | if (frag2 > frag3) { | 91 | if (frag2 > frag3) { |
92 | frag2 = frag4; | 92 | frag2 = frag4; |
93 | frag3 = frag4 = 0; | 93 | frag3 = frag4 = 0; |
94 | } | 94 | } else if (frag2 < frag3) { |
95 | else if (frag2 < frag3) { | ||
96 | block1 = ufs_fragstoblks (frag2); | 95 | block1 = ufs_fragstoblks (frag2); |
97 | block2 = ufs_fragstoblks (frag3); | 96 | block2 = ufs_fragstoblks (frag3); |
98 | } | 97 | } |
99 | 98 | ||
100 | UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4); | 99 | UFSD("frag1 %llu, frag2 %llu, block1 %llu, block2 %llu, frag3 %llu," |
100 | " frag4 %llu\n", | ||
101 | (unsigned long long)frag1, (unsigned long long)frag2, | ||
102 | (unsigned long long)block1, (unsigned long long)block2, | ||
103 | (unsigned long long)frag3, (unsigned long long)frag4); | ||
101 | 104 | ||
102 | if (frag1 >= frag2) | 105 | if (frag1 >= frag2) |
103 | goto next1; | 106 | goto next1; |
@@ -105,8 +108,8 @@ static int ufs_trunc_direct (struct inode * inode) | |||
105 | /* | 108 | /* |
106 | * Free first free fragments | 109 | * Free first free fragments |
107 | */ | 110 | */ |
108 | p = ufsi->i_u1.i_data + ufs_fragstoblks (frag1); | 111 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag1)); |
109 | tmp = fs32_to_cpu(sb, *p); | 112 | tmp = ufs_data_ptr_to_cpu(sb, p); |
110 | if (!tmp ) | 113 | if (!tmp ) |
111 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); | 114 | ufs_panic (sb, "ufs_trunc_direct", "internal error"); |
112 | frag2 -= frag1; | 115 | frag2 -= frag1; |
@@ -121,12 +124,11 @@ next1: | |||
121 | * Free whole blocks | 124 | * Free whole blocks |
122 | */ | 125 | */ |
123 | for (i = block1 ; i < block2; i++) { | 126 | for (i = block1 ; i < block2; i++) { |
124 | p = ufsi->i_u1.i_data + i; | 127 | p = ufs_get_direct_data_ptr(uspi, ufsi, i); |
125 | tmp = fs32_to_cpu(sb, *p); | 128 | tmp = ufs_data_ptr_to_cpu(sb, p); |
126 | if (!tmp) | 129 | if (!tmp) |
127 | continue; | 130 | continue; |
128 | 131 | ufs_data_ptr_clear(uspi, p); | |
129 | *p = 0; | ||
130 | 132 | ||
131 | if (free_count == 0) { | 133 | if (free_count == 0) { |
132 | frag_to_free = tmp; | 134 | frag_to_free = tmp; |
@@ -150,13 +152,12 @@ next1: | |||
150 | /* | 152 | /* |
151 | * Free last free fragments | 153 | * Free last free fragments |
152 | */ | 154 | */ |
153 | p = ufsi->i_u1.i_data + ufs_fragstoblks (frag3); | 155 | p = ufs_get_direct_data_ptr(uspi, ufsi, ufs_fragstoblks(frag3)); |
154 | tmp = fs32_to_cpu(sb, *p); | 156 | tmp = ufs_data_ptr_to_cpu(sb, p); |
155 | if (!tmp ) | 157 | if (!tmp ) |
156 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); | 158 | ufs_panic(sb, "ufs_truncate_direct", "internal error"); |
157 | frag4 = ufs_fragnum (frag4); | 159 | frag4 = ufs_fragnum (frag4); |
158 | 160 | ufs_data_ptr_clear(uspi, p); | |
159 | *p = 0; | ||
160 | 161 | ||
161 | ufs_free_fragments (inode, tmp, frag4); | 162 | ufs_free_fragments (inode, tmp, frag4); |
162 | mark_inode_dirty(inode); | 163 | mark_inode_dirty(inode); |
@@ -167,17 +168,20 @@ next1: | |||
167 | } | 168 | } |
168 | 169 | ||
169 | 170 | ||
170 | static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | 171 | static int ufs_trunc_indirect(struct inode *inode, u64 offset, void *p) |
171 | { | 172 | { |
172 | struct super_block * sb; | 173 | struct super_block * sb; |
173 | struct ufs_sb_private_info * uspi; | 174 | struct ufs_sb_private_info * uspi; |
174 | struct ufs_buffer_head * ind_ubh; | 175 | struct ufs_buffer_head * ind_ubh; |
175 | __fs32 * ind; | 176 | void *ind; |
176 | unsigned indirect_block, i, tmp; | 177 | u64 tmp, indirect_block, i, frag_to_free; |
177 | unsigned frag_to_free, free_count; | 178 | unsigned free_count; |
178 | int retry; | 179 | int retry; |
179 | 180 | ||
180 | UFSD("ENTER\n"); | 181 | UFSD("ENTER: ino %lu, offset %llu, p: %p\n", |
182 | inode->i_ino, (unsigned long long)offset, p); | ||
183 | |||
184 | BUG_ON(!p); | ||
181 | 185 | ||
182 | sb = inode->i_sb; | 186 | sb = inode->i_sb; |
183 | uspi = UFS_SB(sb)->s_uspi; | 187 | uspi = UFS_SB(sb)->s_uspi; |
@@ -186,27 +190,27 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
186 | free_count = 0; | 190 | free_count = 0; |
187 | retry = 0; | 191 | retry = 0; |
188 | 192 | ||
189 | tmp = fs32_to_cpu(sb, *p); | 193 | tmp = ufs_data_ptr_to_cpu(sb, p); |
190 | if (!tmp) | 194 | if (!tmp) |
191 | return 0; | 195 | return 0; |
192 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); | 196 | ind_ubh = ubh_bread(sb, tmp, uspi->s_bsize); |
193 | if (tmp != fs32_to_cpu(sb, *p)) { | 197 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
194 | ubh_brelse (ind_ubh); | 198 | ubh_brelse (ind_ubh); |
195 | return 1; | 199 | return 1; |
196 | } | 200 | } |
197 | if (!ind_ubh) { | 201 | if (!ind_ubh) { |
198 | *p = 0; | 202 | ufs_data_ptr_clear(uspi, p); |
199 | return 0; | 203 | return 0; |
200 | } | 204 | } |
201 | 205 | ||
202 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; | 206 | indirect_block = (DIRECT_BLOCK > offset) ? (DIRECT_BLOCK - offset) : 0; |
203 | for (i = indirect_block; i < uspi->s_apb; i++) { | 207 | for (i = indirect_block; i < uspi->s_apb; i++) { |
204 | ind = ubh_get_addr32 (ind_ubh, i); | 208 | ind = ubh_get_data_ptr(uspi, ind_ubh, i); |
205 | tmp = fs32_to_cpu(sb, *ind); | 209 | tmp = ufs_data_ptr_to_cpu(sb, ind); |
206 | if (!tmp) | 210 | if (!tmp) |
207 | continue; | 211 | continue; |
208 | 212 | ||
209 | *ind = 0; | 213 | ufs_data_ptr_clear(uspi, ind); |
210 | ubh_mark_buffer_dirty(ind_ubh); | 214 | ubh_mark_buffer_dirty(ind_ubh); |
211 | if (free_count == 0) { | 215 | if (free_count == 0) { |
212 | frag_to_free = tmp; | 216 | frag_to_free = tmp; |
@@ -226,11 +230,12 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
226 | ufs_free_blocks (inode, frag_to_free, free_count); | 230 | ufs_free_blocks (inode, frag_to_free, free_count); |
227 | } | 231 | } |
228 | for (i = 0; i < uspi->s_apb; i++) | 232 | for (i = 0; i < uspi->s_apb; i++) |
229 | if (*ubh_get_addr32(ind_ubh,i)) | 233 | if (!ufs_is_data_ptr_zero(uspi, |
234 | ubh_get_data_ptr(uspi, ind_ubh, i))) | ||
230 | break; | 235 | break; |
231 | if (i >= uspi->s_apb) { | 236 | if (i >= uspi->s_apb) { |
232 | tmp = fs32_to_cpu(sb, *p); | 237 | tmp = ufs_data_ptr_to_cpu(sb, p); |
233 | *p = 0; | 238 | ufs_data_ptr_clear(uspi, p); |
234 | 239 | ||
235 | ufs_free_blocks (inode, tmp, uspi->s_fpb); | 240 | ufs_free_blocks (inode, tmp, uspi->s_fpb); |
236 | mark_inode_dirty(inode); | 241 | mark_inode_dirty(inode); |
@@ -248,13 +253,13 @@ static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) | |||
248 | return retry; | 253 | return retry; |
249 | } | 254 | } |
250 | 255 | ||
251 | static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | 256 | static int ufs_trunc_dindirect(struct inode *inode, u64 offset, void *p) |
252 | { | 257 | { |
253 | struct super_block * sb; | 258 | struct super_block * sb; |
254 | struct ufs_sb_private_info * uspi; | 259 | struct ufs_sb_private_info * uspi; |
255 | struct ufs_buffer_head * dind_bh; | 260 | struct ufs_buffer_head *dind_bh; |
256 | unsigned i, tmp, dindirect_block; | 261 | u64 i, tmp, dindirect_block; |
257 | __fs32 * dind; | 262 | void *dind; |
258 | int retry = 0; | 263 | int retry = 0; |
259 | 264 | ||
260 | UFSD("ENTER\n"); | 265 | UFSD("ENTER\n"); |
@@ -266,22 +271,22 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
266 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; | 271 | ? ((DIRECT_BLOCK - offset) >> uspi->s_apbshift) : 0; |
267 | retry = 0; | 272 | retry = 0; |
268 | 273 | ||
269 | tmp = fs32_to_cpu(sb, *p); | 274 | tmp = ufs_data_ptr_to_cpu(sb, p); |
270 | if (!tmp) | 275 | if (!tmp) |
271 | return 0; | 276 | return 0; |
272 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); | 277 | dind_bh = ubh_bread(sb, tmp, uspi->s_bsize); |
273 | if (tmp != fs32_to_cpu(sb, *p)) { | 278 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
274 | ubh_brelse (dind_bh); | 279 | ubh_brelse (dind_bh); |
275 | return 1; | 280 | return 1; |
276 | } | 281 | } |
277 | if (!dind_bh) { | 282 | if (!dind_bh) { |
278 | *p = 0; | 283 | ufs_data_ptr_clear(uspi, p); |
279 | return 0; | 284 | return 0; |
280 | } | 285 | } |
281 | 286 | ||
282 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { | 287 | for (i = dindirect_block ; i < uspi->s_apb ; i++) { |
283 | dind = ubh_get_addr32 (dind_bh, i); | 288 | dind = ubh_get_data_ptr(uspi, dind_bh, i); |
284 | tmp = fs32_to_cpu(sb, *dind); | 289 | tmp = ufs_data_ptr_to_cpu(sb, dind); |
285 | if (!tmp) | 290 | if (!tmp) |
286 | continue; | 291 | continue; |
287 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); | 292 | retry |= ufs_trunc_indirect (inode, offset + (i << uspi->s_apbshift), dind); |
@@ -289,11 +294,12 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
289 | } | 294 | } |
290 | 295 | ||
291 | for (i = 0; i < uspi->s_apb; i++) | 296 | for (i = 0; i < uspi->s_apb; i++) |
292 | if (*ubh_get_addr32 (dind_bh, i)) | 297 | if (!ufs_is_data_ptr_zero(uspi, |
298 | ubh_get_data_ptr(uspi, dind_bh, i))) | ||
293 | break; | 299 | break; |
294 | if (i >= uspi->s_apb) { | 300 | if (i >= uspi->s_apb) { |
295 | tmp = fs32_to_cpu(sb, *p); | 301 | tmp = ufs_data_ptr_to_cpu(sb, p); |
296 | *p = 0; | 302 | ufs_data_ptr_clear(uspi, p); |
297 | 303 | ||
298 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 304 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
299 | mark_inode_dirty(inode); | 305 | mark_inode_dirty(inode); |
@@ -311,34 +317,33 @@ static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) | |||
311 | return retry; | 317 | return retry; |
312 | } | 318 | } |
313 | 319 | ||
314 | static int ufs_trunc_tindirect (struct inode * inode) | 320 | static int ufs_trunc_tindirect(struct inode *inode) |
315 | { | 321 | { |
322 | struct super_block *sb = inode->i_sb; | ||
323 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | ||
316 | struct ufs_inode_info *ufsi = UFS_I(inode); | 324 | struct ufs_inode_info *ufsi = UFS_I(inode); |
317 | struct super_block * sb; | ||
318 | struct ufs_sb_private_info * uspi; | ||
319 | struct ufs_buffer_head * tind_bh; | 325 | struct ufs_buffer_head * tind_bh; |
320 | unsigned tindirect_block, tmp, i; | 326 | u64 tindirect_block, tmp, i; |
321 | __fs32 * tind, * p; | 327 | void *tind, *p; |
322 | int retry; | 328 | int retry; |
323 | 329 | ||
324 | UFSD("ENTER\n"); | 330 | UFSD("ENTER\n"); |
325 | 331 | ||
326 | sb = inode->i_sb; | ||
327 | uspi = UFS_SB(sb)->s_uspi; | ||
328 | retry = 0; | 332 | retry = 0; |
329 | 333 | ||
330 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) | 334 | tindirect_block = (DIRECT_BLOCK > (UFS_NDADDR + uspi->s_apb + uspi->s_2apb)) |
331 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; | 335 | ? ((DIRECT_BLOCK - UFS_NDADDR - uspi->s_apb - uspi->s_2apb) >> uspi->s_2apbshift) : 0; |
332 | p = ufsi->i_u1.i_data + UFS_TIND_BLOCK; | 336 | |
333 | if (!(tmp = fs32_to_cpu(sb, *p))) | 337 | p = ufs_get_direct_data_ptr(uspi, ufsi, UFS_TIND_BLOCK); |
338 | if (!(tmp = ufs_data_ptr_to_cpu(sb, p))) | ||
334 | return 0; | 339 | return 0; |
335 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); | 340 | tind_bh = ubh_bread (sb, tmp, uspi->s_bsize); |
336 | if (tmp != fs32_to_cpu(sb, *p)) { | 341 | if (tmp != ufs_data_ptr_to_cpu(sb, p)) { |
337 | ubh_brelse (tind_bh); | 342 | ubh_brelse (tind_bh); |
338 | return 1; | 343 | return 1; |
339 | } | 344 | } |
340 | if (!tind_bh) { | 345 | if (!tind_bh) { |
341 | *p = 0; | 346 | ufs_data_ptr_clear(uspi, p); |
342 | return 0; | 347 | return 0; |
343 | } | 348 | } |
344 | 349 | ||
@@ -349,11 +354,12 @@ static int ufs_trunc_tindirect (struct inode * inode) | |||
349 | ubh_mark_buffer_dirty(tind_bh); | 354 | ubh_mark_buffer_dirty(tind_bh); |
350 | } | 355 | } |
351 | for (i = 0; i < uspi->s_apb; i++) | 356 | for (i = 0; i < uspi->s_apb; i++) |
352 | if (*ubh_get_addr32 (tind_bh, i)) | 357 | if (!ufs_is_data_ptr_zero(uspi, |
358 | ubh_get_data_ptr(uspi, tind_bh, i))) | ||
353 | break; | 359 | break; |
354 | if (i >= uspi->s_apb) { | 360 | if (i >= uspi->s_apb) { |
355 | tmp = fs32_to_cpu(sb, *p); | 361 | tmp = ufs_data_ptr_to_cpu(sb, p); |
356 | *p = 0; | 362 | ufs_data_ptr_clear(uspi, p); |
357 | 363 | ||
358 | ufs_free_blocks(inode, tmp, uspi->s_fpb); | 364 | ufs_free_blocks(inode, tmp, uspi->s_fpb); |
359 | mark_inode_dirty(inode); | 365 | mark_inode_dirty(inode); |
@@ -375,7 +381,8 @@ static int ufs_alloc_lastblock(struct inode *inode) | |||
375 | int err = 0; | 381 | int err = 0; |
376 | struct address_space *mapping = inode->i_mapping; | 382 | struct address_space *mapping = inode->i_mapping; |
377 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | 383 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; |
378 | unsigned lastfrag, i, end; | 384 | unsigned i, end; |
385 | sector_t lastfrag; | ||
379 | struct page *lastpage; | 386 | struct page *lastpage; |
380 | struct buffer_head *bh; | 387 | struct buffer_head *bh; |
381 | 388 | ||
@@ -430,7 +437,9 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
430 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; | 437 | struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; |
431 | int retry, err = 0; | 438 | int retry, err = 0; |
432 | 439 | ||
433 | UFSD("ENTER\n"); | 440 | UFSD("ENTER: ino %lu, i_size: %llu, old_i_size: %llu\n", |
441 | inode->i_ino, (unsigned long long)i_size_read(inode), | ||
442 | (unsigned long long)old_i_size); | ||
434 | 443 | ||
435 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 444 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
436 | S_ISLNK(inode->i_mode))) | 445 | S_ISLNK(inode->i_mode))) |
@@ -450,10 +459,12 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
450 | lock_kernel(); | 459 | lock_kernel(); |
451 | while (1) { | 460 | while (1) { |
452 | retry = ufs_trunc_direct(inode); | 461 | retry = ufs_trunc_direct(inode); |
453 | retry |= ufs_trunc_indirect (inode, UFS_IND_BLOCK, | 462 | retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK, |
454 | (__fs32 *) &ufsi->i_u1.i_data[UFS_IND_BLOCK]); | 463 | ufs_get_direct_data_ptr(uspi, ufsi, |
455 | retry |= ufs_trunc_dindirect (inode, UFS_IND_BLOCK + uspi->s_apb, | 464 | UFS_IND_BLOCK)); |
456 | (__fs32 *) &ufsi->i_u1.i_data[UFS_DIND_BLOCK]); | 465 | retry |= ufs_trunc_dindirect(inode, UFS_IND_BLOCK + uspi->s_apb, |
466 | ufs_get_direct_data_ptr(uspi, ufsi, | ||
467 | UFS_DIND_BLOCK)); | ||
457 | retry |= ufs_trunc_tindirect (inode); | 468 | retry |= ufs_trunc_tindirect (inode); |
458 | if (!retry) | 469 | if (!retry) |
459 | break; | 470 | break; |