diff options
author | Eric Sandeen <sandeen@redhat.com> | 2013-01-11 21:57:22 -0500 |
---|---|---|
committer | Josef Bacik <josef@toxicpanda.com> | 2013-01-14 13:53:37 -0500 |
commit | 3972f2603d8570effaf633cea52b12c7c2773c11 (patch) | |
tree | edfaa5dc10be60ef2a882a2e0713026312367b88 /fs | |
parent | f276795627045a3c599a60b476767861e4318c7d (diff) |
btrfs: update timestamps on truncate()
truncate() vs. ftruncate() differ in the VFS; truncate()
doesn't set (ATTR_CTIME | ATTR_MTIME), and it's up to the
fs to do the timestamp updates if the size changes.
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Diffstat (limited to 'fs')
-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 | } |