aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
authorMaxim Patlasov <MPatlasov@parallels.com>2013-12-26 10:51:11 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-02 09:38:48 -0400
commitb0aa760652179072119582375f8dc896ed5b5dfd (patch)
treecbc990b308b9894eba032101db994b05e75ad444 /fs/fuse/inode.c
parent8373200b124d03de7fa2e99be56de8642e604e9e (diff)
fuse: Trust kernel i_mtime only
Let the kernel maintain i_mtime locally: - clear S_NOCMTIME - implement i_op->update_time() - flush mtime on fsync and last close - update i_mtime explicitly on truncate and fallocate Fuse inode flag FUSE_I_MTIME_DIRTY serves as indication that local i_mtime should be flushed to the server eventually. Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index c668c8436894..1061b0d9b86d 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -170,8 +170,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
170 inode->i_blocks = attr->blocks; 170 inode->i_blocks = attr->blocks;
171 inode->i_atime.tv_sec = attr->atime; 171 inode->i_atime.tv_sec = attr->atime;
172 inode->i_atime.tv_nsec = attr->atimensec; 172 inode->i_atime.tv_nsec = attr->atimensec;
173 inode->i_mtime.tv_sec = attr->mtime; 173 /* mtime from server may be stale due to local buffered write */
174 inode->i_mtime.tv_nsec = attr->mtimensec; 174 if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) {
175 inode->i_mtime.tv_sec = attr->mtime;
176 inode->i_mtime.tv_nsec = attr->mtimensec;
177 }
175 inode->i_ctime.tv_sec = attr->ctime; 178 inode->i_ctime.tv_sec = attr->ctime;
176 inode->i_ctime.tv_nsec = attr->ctimensec; 179 inode->i_ctime.tv_nsec = attr->ctimensec;
177 180
@@ -250,6 +253,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
250{ 253{
251 inode->i_mode = attr->mode & S_IFMT; 254 inode->i_mode = attr->mode & S_IFMT;
252 inode->i_size = attr->size; 255 inode->i_size = attr->size;
256 inode->i_mtime.tv_sec = attr->mtime;
257 inode->i_mtime.tv_nsec = attr->mtimensec;
253 if (S_ISREG(inode->i_mode)) { 258 if (S_ISREG(inode->i_mode)) {
254 fuse_init_common(inode); 259 fuse_init_common(inode);
255 fuse_init_file_inode(inode); 260 fuse_init_file_inode(inode);
@@ -296,7 +301,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
296 return NULL; 301 return NULL;
297 302
298 if ((inode->i_state & I_NEW)) { 303 if ((inode->i_state & I_NEW)) {
299 inode->i_flags |= S_NOATIME|S_NOCMTIME; 304 inode->i_flags |= S_NOATIME;
305 if (!fc->writeback_cache || !S_ISREG(inode->i_mode))
306 inode->i_flags |= S_NOCMTIME;
300 inode->i_generation = generation; 307 inode->i_generation = generation;
301 inode->i_data.backing_dev_info = &fc->bdi; 308 inode->i_data.backing_dev_info = &fc->bdi;
302 fuse_init_inode(inode, attr); 309 fuse_init_inode(inode, attr);