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>
This commit is contained in:

committed by
Miklos Szeredi

parent
8373200b12
commit
b0aa760652
@@ -308,6 +308,9 @@ static int fuse_open(struct inode *inode, struct file *file)
|
||||
|
||||
static int fuse_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state))
|
||||
fuse_flush_mtime(file, true);
|
||||
|
||||
fuse_release_common(file, FUSE_RELEASE);
|
||||
|
||||
/* return value is ignored by VFS */
|
||||
@@ -475,6 +478,12 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
|
||||
|
||||
fuse_sync_writes(inode);
|
||||
|
||||
if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) {
|
||||
int err = fuse_flush_mtime(file, false);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
req = fuse_get_req_nopages(fc);
|
||||
if (IS_ERR(req)) {
|
||||
err = PTR_ERR(req);
|
||||
@@ -960,16 +969,21 @@ static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io,
|
||||
return req->misc.write.out.size;
|
||||
}
|
||||
|
||||
void fuse_write_update_size(struct inode *inode, loff_t pos)
|
||||
bool fuse_write_update_size(struct inode *inode, loff_t pos)
|
||||
{
|
||||
struct fuse_conn *fc = get_fuse_conn(inode);
|
||||
struct fuse_inode *fi = get_fuse_inode(inode);
|
||||
bool ret = false;
|
||||
|
||||
spin_lock(&fc->lock);
|
||||
fi->attr_version = ++fc->attr_version;
|
||||
if (pos > inode->i_size)
|
||||
if (pos > inode->i_size) {
|
||||
i_size_write(inode, pos);
|
||||
ret = true;
|
||||
}
|
||||
spin_unlock(&fc->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file,
|
||||
@@ -2877,8 +2891,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
|
||||
goto out;
|
||||
|
||||
/* we could have extended the file */
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE))
|
||||
fuse_write_update_size(inode, offset + length);
|
||||
if (!(mode & FALLOC_FL_KEEP_SIZE)) {
|
||||
bool changed = fuse_write_update_size(inode, offset + length);
|
||||
|
||||
if (changed && fc->writeback_cache) {
|
||||
struct fuse_inode *fi = get_fuse_inode(inode);
|
||||
|
||||
inode->i_mtime = current_fs_time(inode->i_sb);
|
||||
set_bit(FUSE_I_MTIME_DIRTY, &fi->state);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode & FALLOC_FL_PUNCH_HOLE)
|
||||
truncate_pagecache_range(inode, offset, offset + length - 1);
|
||||
|
Reference in New Issue
Block a user