diff options
author | Maxim Patlasov <MPatlasov@parallels.com> | 2014-04-28 08:19:24 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-28 08:19:24 -0400 |
commit | 31f3267b4ba16b12fb9dd3b1953ea0f221cc2ab4 (patch) | |
tree | 415623b0ba1a63d0c9bc2fdf189bc66cd68a650c | |
parent | 8b47e73e91c064cd75e8bf458ce738e1bfe2e700 (diff) |
fuse: trust kernel i_ctime only
Let the kernel maintain i_ctime locally: update i_ctime explicitly on
truncate, fallocate, open(O_TRUNC), setxattr, removexattr, link, rename,
unlink.
The inode flag I_DIRTY_SYNC serves as indication that local i_ctime should
be flushed to the server eventually. The patch sets the flag and updates
i_ctime in course of operations listed above.
Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r-- | fs/fuse/dir.c | 22 | ||||
-rw-r--r-- | fs/fuse/inode.c | 6 |
2 files changed, 24 insertions, 4 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 65357bd1d17b..f62ab8eedb5f 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -679,6 +679,14 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, | |||
679 | return create_new_entry(fc, req, dir, entry, S_IFLNK); | 679 | return create_new_entry(fc, req, dir, entry, S_IFLNK); |
680 | } | 680 | } |
681 | 681 | ||
682 | static inline void fuse_update_ctime(struct inode *inode) | ||
683 | { | ||
684 | if (!IS_NOCMTIME(inode)) { | ||
685 | inode->i_ctime = current_fs_time(inode->i_sb); | ||
686 | mark_inode_dirty_sync(inode); | ||
687 | } | ||
688 | } | ||
689 | |||
682 | static int fuse_unlink(struct inode *dir, struct dentry *entry) | 690 | static int fuse_unlink(struct inode *dir, struct dentry *entry) |
683 | { | 691 | { |
684 | int err; | 692 | int err; |
@@ -713,6 +721,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
713 | fuse_invalidate_attr(inode); | 721 | fuse_invalidate_attr(inode); |
714 | fuse_invalidate_attr(dir); | 722 | fuse_invalidate_attr(dir); |
715 | fuse_invalidate_entry_cache(entry); | 723 | fuse_invalidate_entry_cache(entry); |
724 | fuse_update_ctime(inode); | ||
716 | } else if (err == -EINTR) | 725 | } else if (err == -EINTR) |
717 | fuse_invalidate_entry(entry); | 726 | fuse_invalidate_entry(entry); |
718 | return err; | 727 | return err; |
@@ -771,6 +780,7 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
771 | if (!err) { | 780 | if (!err) { |
772 | /* ctime changes */ | 781 | /* ctime changes */ |
773 | fuse_invalidate_attr(oldent->d_inode); | 782 | fuse_invalidate_attr(oldent->d_inode); |
783 | fuse_update_ctime(oldent->d_inode); | ||
774 | 784 | ||
775 | fuse_invalidate_attr(olddir); | 785 | fuse_invalidate_attr(olddir); |
776 | if (olddir != newdir) | 786 | if (olddir != newdir) |
@@ -780,6 +790,7 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
780 | if (newent->d_inode) { | 790 | if (newent->d_inode) { |
781 | fuse_invalidate_attr(newent->d_inode); | 791 | fuse_invalidate_attr(newent->d_inode); |
782 | fuse_invalidate_entry_cache(newent); | 792 | fuse_invalidate_entry_cache(newent); |
793 | fuse_update_ctime(newent->d_inode); | ||
783 | } | 794 | } |
784 | } else if (err == -EINTR) { | 795 | } else if (err == -EINTR) { |
785 | /* If request was interrupted, DEITY only knows if the | 796 | /* If request was interrupted, DEITY only knows if the |
@@ -829,6 +840,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
829 | inc_nlink(inode); | 840 | inc_nlink(inode); |
830 | spin_unlock(&fc->lock); | 841 | spin_unlock(&fc->lock); |
831 | fuse_invalidate_attr(inode); | 842 | fuse_invalidate_attr(inode); |
843 | fuse_update_ctime(inode); | ||
832 | } else if (err == -EINTR) { | 844 | } else if (err == -EINTR) { |
833 | fuse_invalidate_attr(inode); | 845 | fuse_invalidate_attr(inode); |
834 | } | 846 | } |
@@ -846,6 +858,8 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, | |||
846 | attr->size = i_size_read(inode); | 858 | attr->size = i_size_read(inode); |
847 | attr->mtime = inode->i_mtime.tv_sec; | 859 | attr->mtime = inode->i_mtime.tv_sec; |
848 | attr->mtimensec = inode->i_mtime.tv_nsec; | 860 | attr->mtimensec = inode->i_mtime.tv_nsec; |
861 | attr->ctime = inode->i_ctime.tv_sec; | ||
862 | attr->ctimensec = inode->i_ctime.tv_nsec; | ||
849 | } | 863 | } |
850 | 864 | ||
851 | stat->dev = inode->i_sb->s_dev; | 865 | stat->dev = inode->i_sb->s_dev; |
@@ -1811,8 +1825,10 @@ static int fuse_setxattr(struct dentry *entry, const char *name, | |||
1811 | fc->no_setxattr = 1; | 1825 | fc->no_setxattr = 1; |
1812 | err = -EOPNOTSUPP; | 1826 | err = -EOPNOTSUPP; |
1813 | } | 1827 | } |
1814 | if (!err) | 1828 | if (!err) { |
1815 | fuse_invalidate_attr(inode); | 1829 | fuse_invalidate_attr(inode); |
1830 | fuse_update_ctime(inode); | ||
1831 | } | ||
1816 | return err; | 1832 | return err; |
1817 | } | 1833 | } |
1818 | 1834 | ||
@@ -1942,8 +1958,10 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1942 | fc->no_removexattr = 1; | 1958 | fc->no_removexattr = 1; |
1943 | err = -EOPNOTSUPP; | 1959 | err = -EOPNOTSUPP; |
1944 | } | 1960 | } |
1945 | if (!err) | 1961 | if (!err) { |
1946 | fuse_invalidate_attr(inode); | 1962 | fuse_invalidate_attr(inode); |
1963 | fuse_update_ctime(inode); | ||
1964 | } | ||
1947 | return err; | 1965 | return err; |
1948 | } | 1966 | } |
1949 | 1967 | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 560eafcdd6a7..e9ecb1878109 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -175,9 +175,9 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |||
175 | if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { | 175 | if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { |
176 | inode->i_mtime.tv_sec = attr->mtime; | 176 | inode->i_mtime.tv_sec = attr->mtime; |
177 | inode->i_mtime.tv_nsec = attr->mtimensec; | 177 | inode->i_mtime.tv_nsec = attr->mtimensec; |
178 | inode->i_ctime.tv_sec = attr->ctime; | ||
179 | inode->i_ctime.tv_nsec = attr->ctimensec; | ||
178 | } | 180 | } |
179 | inode->i_ctime.tv_sec = attr->ctime; | ||
180 | inode->i_ctime.tv_nsec = attr->ctimensec; | ||
181 | 181 | ||
182 | if (attr->blksize != 0) | 182 | if (attr->blksize != 0) |
183 | inode->i_blkbits = ilog2(attr->blksize); | 183 | inode->i_blkbits = ilog2(attr->blksize); |
@@ -256,6 +256,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | |||
256 | inode->i_size = attr->size; | 256 | inode->i_size = attr->size; |
257 | inode->i_mtime.tv_sec = attr->mtime; | 257 | inode->i_mtime.tv_sec = attr->mtime; |
258 | inode->i_mtime.tv_nsec = attr->mtimensec; | 258 | inode->i_mtime.tv_nsec = attr->mtimensec; |
259 | inode->i_ctime.tv_sec = attr->ctime; | ||
260 | inode->i_ctime.tv_nsec = attr->ctimensec; | ||
259 | if (S_ISREG(inode->i_mode)) { | 261 | if (S_ISREG(inode->i_mode)) { |
260 | fuse_init_common(inode); | 262 | fuse_init_common(inode); |
261 | fuse_init_file_inode(inode); | 263 | fuse_init_file_inode(inode); |