diff options
Diffstat (limited to 'fs/ufs/truncate.c')
| -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: |
