diff options
| -rw-r--r-- | fs/btrfs/inode.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3d2c64d4734a..9bc6c40b182d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -88,7 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { | |||
| 88 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, | 88 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | static int btrfs_setsize(struct inode *inode, loff_t newsize); | 91 | static int btrfs_setsize(struct inode *inode, struct iattr *attr); |
| 92 | static int btrfs_truncate(struct inode *inode); | 92 | static int btrfs_truncate(struct inode *inode); |
| 93 | static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent); | 93 | static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent); |
| 94 | static noinline int cow_file_range(struct inode *inode, | 94 | static noinline int cow_file_range(struct inode *inode, |
| @@ -3761,16 +3761,27 @@ next: | |||
| 3761 | return err; | 3761 | return err; |
| 3762 | } | 3762 | } |
| 3763 | 3763 | ||
| 3764 | static int btrfs_setsize(struct inode *inode, loff_t newsize) | 3764 | static int btrfs_setsize(struct inode *inode, struct iattr *attr) |
| 3765 | { | 3765 | { |
| 3766 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3766 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3767 | struct btrfs_trans_handle *trans; | 3767 | struct btrfs_trans_handle *trans; |
| 3768 | loff_t oldsize = i_size_read(inode); | 3768 | loff_t oldsize = i_size_read(inode); |
| 3769 | loff_t newsize = attr->ia_size; | ||
| 3770 | int mask = attr->ia_valid; | ||
| 3769 | int ret; | 3771 | int ret; |
| 3770 | 3772 | ||
| 3771 | if (newsize == oldsize) | 3773 | if (newsize == oldsize) |
| 3772 | return 0; | 3774 | return 0; |
| 3773 | 3775 | ||
| 3776 | /* | ||
| 3777 | * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a | ||
| 3778 | * special case where we need to update the times despite not having | ||
| 3779 | * these flags set. For all other operations the VFS set these flags | ||
| 3780 | * explicitly if it wants a timestamp update. | ||
| 3781 | */ | ||
| 3782 | if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) | ||
| 3783 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); | ||
| 3784 | |||
| 3774 | if (newsize > oldsize) { | 3785 | if (newsize > oldsize) { |
| 3775 | truncate_pagecache(inode, oldsize, newsize); | 3786 | truncate_pagecache(inode, oldsize, newsize); |
| 3776 | ret = btrfs_cont_expand(inode, oldsize, newsize); | 3787 | ret = btrfs_cont_expand(inode, oldsize, newsize); |
| @@ -3843,7 +3854,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 3843 | return err; | 3854 | return err; |
| 3844 | 3855 | ||
| 3845 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { | 3856 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { |
| 3846 | err = btrfs_setsize(inode, attr->ia_size); | 3857 | err = btrfs_setsize(inode, attr); |
| 3847 | if (err) | 3858 | if (err) |
| 3848 | return err; | 3859 | return err; |
| 3849 | } | 3860 | } |
