diff options
author | Josef Bacik <josef@redhat.com> | 2011-01-31 15:30:16 -0500 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2011-03-17 14:21:22 -0400 |
commit | a41ad394a03b802497958d7c98a9dcf607266645 (patch) | |
tree | f18d97b7feb5c3dcf0d3c1a670d4eaf6b94e8b79 /fs/btrfs/inode.c | |
parent | dc89e9824464e91fa0b06267864ceabe3186fd8b (diff) |
Btrfs: convert to the new truncate sequence
->truncate() is going away, instead all of the work needs to be done in
->setattr(). So this converts us over to do this. It's fairly straightforward,
just get rid of our .truncate inode operation and call btrfs_truncate() directly
from btrfs_setsize. This works out better for us since truncate can technically
return ENOSPC, and before we had no way of letting anybody know. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 80 |
1 files changed, 36 insertions, 44 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2d2e079713d7..3662ffec17d9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -84,7 +84,8 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { | |||
84 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, | 84 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static void btrfs_truncate(struct inode *inode); | 87 | static int btrfs_setsize(struct inode *inode, loff_t newsize); |
88 | static int btrfs_truncate(struct inode *inode); | ||
88 | static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end); | 89 | static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end); |
89 | static noinline int cow_file_range(struct inode *inode, | 90 | static noinline int cow_file_range(struct inode *inode, |
90 | struct page *locked_page, | 91 | struct page *locked_page, |
@@ -2371,6 +2372,11 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2371 | 2372 | ||
2372 | /* if we have links, this was a truncate, lets do that */ | 2373 | /* if we have links, this was a truncate, lets do that */ |
2373 | if (inode->i_nlink) { | 2374 | if (inode->i_nlink) { |
2375 | if (!S_ISREG(inode->i_mode)) { | ||
2376 | WARN_ON(1); | ||
2377 | iput(inode); | ||
2378 | continue; | ||
2379 | } | ||
2374 | nr_truncate++; | 2380 | nr_truncate++; |
2375 | btrfs_truncate(inode); | 2381 | btrfs_truncate(inode); |
2376 | } else { | 2382 | } else { |
@@ -3538,7 +3544,7 @@ out: | |||
3538 | return ret; | 3544 | return ret; |
3539 | } | 3545 | } |
3540 | 3546 | ||
3541 | int btrfs_cont_expand(struct inode *inode, loff_t size) | 3547 | int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) |
3542 | { | 3548 | { |
3543 | struct btrfs_trans_handle *trans; | 3549 | struct btrfs_trans_handle *trans; |
3544 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3550 | struct btrfs_root *root = BTRFS_I(inode)->root; |
@@ -3546,7 +3552,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) | |||
3546 | struct extent_map *em = NULL; | 3552 | struct extent_map *em = NULL; |
3547 | struct extent_state *cached_state = NULL; | 3553 | struct extent_state *cached_state = NULL; |
3548 | u64 mask = root->sectorsize - 1; | 3554 | u64 mask = root->sectorsize - 1; |
3549 | u64 hole_start = (inode->i_size + mask) & ~mask; | 3555 | u64 hole_start = (oldsize + mask) & ~mask; |
3550 | u64 block_end = (size + mask) & ~mask; | 3556 | u64 block_end = (size + mask) & ~mask; |
3551 | u64 last_byte; | 3557 | u64 last_byte; |
3552 | u64 cur_offset; | 3558 | u64 cur_offset; |
@@ -3617,27 +3623,17 @@ int btrfs_cont_expand(struct inode *inode, loff_t size) | |||
3617 | return err; | 3623 | return err; |
3618 | } | 3624 | } |
3619 | 3625 | ||
3620 | static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) | 3626 | static int btrfs_setsize(struct inode *inode, loff_t newsize) |
3621 | { | 3627 | { |
3622 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3628 | struct btrfs_root *root = BTRFS_I(inode)->root; |
3623 | struct btrfs_trans_handle *trans; | 3629 | struct btrfs_trans_handle *trans; |
3630 | loff_t oldsize = i_size_read(inode); | ||
3624 | unsigned long nr; | 3631 | unsigned long nr; |
3625 | int ret; | 3632 | int ret; |
3626 | 3633 | ||
3627 | if (attr->ia_size == inode->i_size) | 3634 | if (newsize == oldsize) |
3628 | return 0; | 3635 | return 0; |
3629 | 3636 | ||
3630 | if (attr->ia_size > inode->i_size) { | ||
3631 | unsigned long limit; | ||
3632 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
3633 | if (attr->ia_size > inode->i_sb->s_maxbytes) | ||
3634 | return -EFBIG; | ||
3635 | if (limit != RLIM_INFINITY && attr->ia_size > limit) { | ||
3636 | send_sig(SIGXFSZ, current, 0); | ||
3637 | return -EFBIG; | ||
3638 | } | ||
3639 | } | ||
3640 | |||
3641 | trans = btrfs_start_transaction(root, 5); | 3637 | trans = btrfs_start_transaction(root, 5); |
3642 | if (IS_ERR(trans)) | 3638 | if (IS_ERR(trans)) |
3643 | return PTR_ERR(trans); | 3639 | return PTR_ERR(trans); |
@@ -3651,16 +3647,16 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) | |||
3651 | btrfs_end_transaction(trans, root); | 3647 | btrfs_end_transaction(trans, root); |
3652 | btrfs_btree_balance_dirty(root, nr); | 3648 | btrfs_btree_balance_dirty(root, nr); |
3653 | 3649 | ||
3654 | if (attr->ia_size > inode->i_size) { | 3650 | if (newsize > oldsize) { |
3655 | ret = btrfs_cont_expand(inode, attr->ia_size); | 3651 | i_size_write(inode, newsize); |
3652 | btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); | ||
3653 | truncate_pagecache(inode, oldsize, newsize); | ||
3654 | ret = btrfs_cont_expand(inode, oldsize, newsize); | ||
3656 | if (ret) { | 3655 | if (ret) { |
3657 | btrfs_truncate(inode); | 3656 | btrfs_setsize(inode, oldsize); |
3658 | return ret; | 3657 | return ret; |
3659 | } | 3658 | } |
3660 | 3659 | ||
3661 | i_size_write(inode, attr->ia_size); | ||
3662 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); | ||
3663 | |||
3664 | trans = btrfs_start_transaction(root, 0); | 3660 | trans = btrfs_start_transaction(root, 0); |
3665 | BUG_ON(IS_ERR(trans)); | 3661 | BUG_ON(IS_ERR(trans)); |
3666 | btrfs_set_trans_block_group(trans, inode); | 3662 | btrfs_set_trans_block_group(trans, inode); |
@@ -3676,22 +3672,22 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) | |||
3676 | nr = trans->blocks_used; | 3672 | nr = trans->blocks_used; |
3677 | btrfs_end_transaction(trans, root); | 3673 | btrfs_end_transaction(trans, root); |
3678 | btrfs_btree_balance_dirty(root, nr); | 3674 | btrfs_btree_balance_dirty(root, nr); |
3679 | return 0; | 3675 | } else { |
3680 | } | ||
3681 | 3676 | ||
3682 | /* | 3677 | /* |
3683 | * We're truncating a file that used to have good data down to | 3678 | * We're truncating a file that used to have good data down to |
3684 | * zero. Make sure it gets into the ordered flush list so that | 3679 | * zero. Make sure it gets into the ordered flush list so that |
3685 | * any new writes get down to disk quickly. | 3680 | * any new writes get down to disk quickly. |
3686 | */ | 3681 | */ |
3687 | if (attr->ia_size == 0) | 3682 | if (newsize == 0) |
3688 | BTRFS_I(inode)->ordered_data_close = 1; | 3683 | BTRFS_I(inode)->ordered_data_close = 1; |
3689 | 3684 | ||
3690 | /* we don't support swapfiles, so vmtruncate shouldn't fail */ | 3685 | /* we don't support swapfiles, so vmtruncate shouldn't fail */ |
3691 | ret = vmtruncate(inode, attr->ia_size); | 3686 | truncate_setsize(inode, newsize); |
3692 | BUG_ON(ret); | 3687 | ret = btrfs_truncate(inode); |
3688 | } | ||
3693 | 3689 | ||
3694 | return 0; | 3690 | return ret; |
3695 | } | 3691 | } |
3696 | 3692 | ||
3697 | static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | 3693 | static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) |
@@ -3708,7 +3704,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3708 | return err; | 3704 | return err; |
3709 | 3705 | ||
3710 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { | 3706 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { |
3711 | err = btrfs_setattr_size(inode, attr); | 3707 | err = btrfs_setsize(inode, attr->ia_size); |
3712 | if (err) | 3708 | if (err) |
3713 | return err; | 3709 | return err; |
3714 | } | 3710 | } |
@@ -6478,7 +6474,7 @@ out: | |||
6478 | return ret; | 6474 | return ret; |
6479 | } | 6475 | } |
6480 | 6476 | ||
6481 | static void btrfs_truncate(struct inode *inode) | 6477 | static int btrfs_truncate(struct inode *inode) |
6482 | { | 6478 | { |
6483 | struct btrfs_root *root = BTRFS_I(inode)->root; | 6479 | struct btrfs_root *root = BTRFS_I(inode)->root; |
6484 | int ret; | 6480 | int ret; |
@@ -6486,14 +6482,9 @@ static void btrfs_truncate(struct inode *inode) | |||
6486 | unsigned long nr; | 6482 | unsigned long nr; |
6487 | u64 mask = root->sectorsize - 1; | 6483 | u64 mask = root->sectorsize - 1; |
6488 | 6484 | ||
6489 | if (!S_ISREG(inode->i_mode)) { | ||
6490 | WARN_ON(1); | ||
6491 | return; | ||
6492 | } | ||
6493 | |||
6494 | ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); | 6485 | ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); |
6495 | if (ret) | 6486 | if (ret) |
6496 | return; | 6487 | return ret; |
6497 | 6488 | ||
6498 | btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); | 6489 | btrfs_wait_ordered_range(inode, inode->i_size & (~mask), (u64)-1); |
6499 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); | 6490 | btrfs_ordered_update_i_size(inode, inode->i_size, NULL); |
@@ -6568,6 +6559,8 @@ static void btrfs_truncate(struct inode *inode) | |||
6568 | ret = btrfs_end_transaction_throttle(trans, root); | 6559 | ret = btrfs_end_transaction_throttle(trans, root); |
6569 | BUG_ON(ret); | 6560 | BUG_ON(ret); |
6570 | btrfs_btree_balance_dirty(root, nr); | 6561 | btrfs_btree_balance_dirty(root, nr); |
6562 | |||
6563 | return ret; | ||
6571 | } | 6564 | } |
6572 | 6565 | ||
6573 | /* | 6566 | /* |
@@ -7367,7 +7360,6 @@ static const struct address_space_operations btrfs_symlink_aops = { | |||
7367 | }; | 7360 | }; |
7368 | 7361 | ||
7369 | static const struct inode_operations btrfs_file_inode_operations = { | 7362 | static const struct inode_operations btrfs_file_inode_operations = { |
7370 | .truncate = btrfs_truncate, | ||
7371 | .getattr = btrfs_getattr, | 7363 | .getattr = btrfs_getattr, |
7372 | .setattr = btrfs_setattr, | 7364 | .setattr = btrfs_setattr, |
7373 | .setxattr = btrfs_setxattr, | 7365 | .setxattr = btrfs_setxattr, |