diff options
Diffstat (limited to 'fs/ufs')
-rw-r--r-- | fs/ufs/truncate.c | 77 |
1 files changed, 25 insertions, 52 deletions
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index c9b55872079b..ea11d04c41a0 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c | |||
@@ -375,17 +375,15 @@ static int ufs_alloc_lastblock(struct inode *inode) | |||
375 | int err = 0; | 375 | int err = 0; |
376 | struct address_space *mapping = inode->i_mapping; | 376 | struct address_space *mapping = inode->i_mapping; |
377 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; | 377 | struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; |
378 | struct ufs_inode_info *ufsi = UFS_I(inode); | ||
379 | unsigned lastfrag, i, end; | 378 | unsigned lastfrag, i, end; |
380 | struct page *lastpage; | 379 | struct page *lastpage; |
381 | struct buffer_head *bh; | 380 | struct buffer_head *bh; |
382 | 381 | ||
383 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; | 382 | lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; |
384 | 383 | ||
385 | if (!lastfrag) { | 384 | if (!lastfrag) |
386 | ufsi->i_lastfrag = 0; | ||
387 | goto out; | 385 | goto out; |
388 | } | 386 | |
389 | lastfrag--; | 387 | lastfrag--; |
390 | 388 | ||
391 | lastpage = ufs_get_locked_page(mapping, lastfrag >> | 389 | lastpage = ufs_get_locked_page(mapping, lastfrag >> |
@@ -400,25 +398,25 @@ static int ufs_alloc_lastblock(struct inode *inode) | |||
400 | for (i = 0; i < end; ++i) | 398 | for (i = 0; i < end; ++i) |
401 | bh = bh->b_this_page; | 399 | bh = bh->b_this_page; |
402 | 400 | ||
403 | if (!buffer_mapped(bh)) { | 401 | |
404 | err = ufs_getfrag_block(inode, lastfrag, bh, 1); | 402 | err = ufs_getfrag_block(inode, lastfrag, bh, 1); |
405 | 403 | ||
406 | if (unlikely(err)) | 404 | if (unlikely(err)) |
407 | goto out_unlock; | 405 | goto out_unlock; |
408 | 406 | ||
409 | if (buffer_new(bh)) { | 407 | if (buffer_new(bh)) { |
410 | clear_buffer_new(bh); | 408 | clear_buffer_new(bh); |
411 | unmap_underlying_metadata(bh->b_bdev, | 409 | unmap_underlying_metadata(bh->b_bdev, |
412 | bh->b_blocknr); | 410 | bh->b_blocknr); |
413 | /* | 411 | /* |
414 | * we do not zeroize fragment, because of | 412 | * we do not zeroize fragment, because of |
415 | * if it maped to hole, it already contains zeroes | 413 | * if it maped to hole, it already contains zeroes |
416 | */ | 414 | */ |
417 | set_buffer_uptodate(bh); | 415 | set_buffer_uptodate(bh); |
418 | mark_buffer_dirty(bh); | 416 | mark_buffer_dirty(bh); |
419 | set_page_dirty(lastpage); | 417 | set_page_dirty(lastpage); |
420 | } | ||
421 | } | 418 | } |
419 | |||
422 | out_unlock: | 420 | out_unlock: |
423 | ufs_put_locked_page(lastpage); | 421 | ufs_put_locked_page(lastpage); |
424 | out: | 422 | out: |
@@ -440,23 +438,11 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
440 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | 438 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) |
441 | return -EPERM; | 439 | return -EPERM; |
442 | 440 | ||
443 | if (inode->i_size > old_i_size) { | 441 | err = ufs_alloc_lastblock(inode); |
444 | /* | ||
445 | * if we expand file we should care about | ||
446 | * allocation of block for last byte first of all | ||
447 | */ | ||
448 | err = ufs_alloc_lastblock(inode); | ||
449 | 442 | ||
450 | if (err) { | 443 | if (err) { |
451 | i_size_write(inode, old_i_size); | 444 | i_size_write(inode, old_i_size); |
452 | goto out; | 445 | goto out; |
453 | } | ||
454 | /* | ||
455 | * go away, because of we expand file, and we do not | ||
456 | * need free blocks, and zeroizes page | ||
457 | */ | ||
458 | lock_kernel(); | ||
459 | goto almost_end; | ||
460 | } | 446 | } |
461 | 447 | ||
462 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); | 448 | block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); |
@@ -477,21 +463,8 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) | |||
477 | yield(); | 463 | yield(); |
478 | } | 464 | } |
479 | 465 | ||
480 | if (inode->i_size < old_i_size) { | ||
481 | /* | ||
482 | * now we should have enough space | ||
483 | * to allocate block for last byte | ||
484 | */ | ||
485 | err = ufs_alloc_lastblock(inode); | ||
486 | if (err) | ||
487 | /* | ||
488 | * looks like all the same - we have no space, | ||
489 | * but we truncate file already | ||
490 | */ | ||
491 | inode->i_size = (ufsi->i_lastfrag - 1) * uspi->s_fsize; | ||
492 | } | ||
493 | almost_end: | ||
494 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 466 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
467 | ufsi->i_lastfrag = DIRECT_FRAGMENT; | ||
495 | unlock_kernel(); | 468 | unlock_kernel(); |
496 | mark_inode_dirty(inode); | 469 | mark_inode_dirty(inode); |
497 | out: | 470 | out: |