aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ufs/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ufs/truncate.c')
-rw-r--r--fs/ufs/truncate.c139
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
66static int ufs_trunc_direct (struct inode * inode) 66static 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
170static int ufs_trunc_indirect (struct inode * inode, unsigned offset, __fs32 *p) 171static 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
251static int ufs_trunc_dindirect (struct inode *inode, unsigned offset, __fs32 *p) 256static 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
314static int ufs_trunc_tindirect (struct inode * inode) 320static 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;