提交 1e18bda8 编写于 作者: M Miklos Szeredi

fuse: add .write_inode

...and flush mtime from this.  This allows us to use the kernel
infrastructure for writing out dirty metadata (mtime at this point, but
ctime in the next patches and also maybe atime).
Signed-off-by: NMiklos Szeredi <mszeredi@suse.cz>
上级 22401e7b
...@@ -1597,23 +1597,17 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req, ...@@ -1597,23 +1597,17 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
/* /*
* Flush inode->i_mtime to the server * Flush inode->i_mtime to the server
*/ */
int fuse_flush_mtime(struct file *file, bool nofail) int fuse_flush_mtime(struct inode *inode, struct fuse_file *ff)
{ {
struct inode *inode = file->f_mapping->host;
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req = NULL; struct fuse_req *req;
struct fuse_setattr_in inarg; struct fuse_setattr_in inarg;
struct fuse_attr_out outarg; struct fuse_attr_out outarg;
int err; int err;
if (nofail) {
req = fuse_get_req_nofail_nopages(fc, file);
} else {
req = fuse_get_req_nopages(fc); req = fuse_get_req_nopages(fc);
if (IS_ERR(req)) if (IS_ERR(req))
return PTR_ERR(req); return PTR_ERR(req);
}
memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg));
memset(&outarg, 0, sizeof(outarg)); memset(&outarg, 0, sizeof(outarg));
...@@ -1621,15 +1615,15 @@ int fuse_flush_mtime(struct file *file, bool nofail) ...@@ -1621,15 +1615,15 @@ int fuse_flush_mtime(struct file *file, bool nofail)
inarg.valid |= FATTR_MTIME; inarg.valid |= FATTR_MTIME;
inarg.mtime = inode->i_mtime.tv_sec; inarg.mtime = inode->i_mtime.tv_sec;
inarg.mtimensec = inode->i_mtime.tv_nsec; inarg.mtimensec = inode->i_mtime.tv_nsec;
if (ff) {
inarg.valid |= FATTR_FH;
inarg.fh = ff->fh;
}
fuse_setattr_fill(fc, req, inode, &inarg, &outarg); fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
fuse_request_send(fc, req); fuse_request_send(fc, req);
err = req->out.h.error; err = req->out.h.error;
fuse_put_request(fc, req); fuse_put_request(fc, req);
if (!err)
clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
return err; return err;
} }
...@@ -1715,7 +1709,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, ...@@ -1715,7 +1709,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
/* the kernel maintains i_mtime locally */ /* the kernel maintains i_mtime locally */
if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) { if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) {
inode->i_mtime = attr->ia_mtime; inode->i_mtime = attr->ia_mtime;
clear_bit(FUSE_I_MTIME_DIRTY, &fi->state); /* FIXME: clear I_DIRTY_SYNC? */
} }
fuse_change_attributes_common(inode, &outarg.attr, fuse_change_attributes_common(inode, &outarg.attr,
...@@ -1953,7 +1947,7 @@ static int fuse_update_time(struct inode *inode, struct timespec *now, ...@@ -1953,7 +1947,7 @@ static int fuse_update_time(struct inode *inode, struct timespec *now,
{ {
if (flags & S_MTIME) { if (flags & S_MTIME) {
inode->i_mtime = *now; inode->i_mtime = *now;
set_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state); mark_inode_dirty_sync(inode);
BUG_ON(!S_ISREG(inode->i_mode)); BUG_ON(!S_ISREG(inode->i_mode));
} }
return 0; return 0;
......
...@@ -324,10 +324,7 @@ static int fuse_release(struct inode *inode, struct file *file) ...@@ -324,10 +324,7 @@ static int fuse_release(struct inode *inode, struct file *file)
/* see fuse_vma_close() for !writeback_cache case */ /* see fuse_vma_close() for !writeback_cache case */
if (fc->writeback_cache) if (fc->writeback_cache)
filemap_write_and_wait(file->f_mapping); write_inode_now(inode, 1);
if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state))
fuse_flush_mtime(file, true);
fuse_release_common(file, FUSE_RELEASE); fuse_release_common(file, FUSE_RELEASE);
...@@ -449,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) ...@@ -449,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
if (fc->no_flush) if (fc->no_flush)
return 0; return 0;
err = filemap_write_and_wait(file->f_mapping); err = write_inode_now(inode, 1);
if (err) if (err)
return err; return err;
...@@ -502,12 +499,10 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, ...@@ -502,12 +499,10 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
goto out; goto out;
fuse_sync_writes(inode); fuse_sync_writes(inode);
err = sync_inode_metadata(inode, 1);
if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) {
err = fuse_flush_mtime(file, false);
if (err) if (err)
goto out; goto out;
}
if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
goto out; goto out;
...@@ -1664,13 +1659,13 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) ...@@ -1664,13 +1659,13 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
fuse_writepage_free(fc, req); fuse_writepage_free(fc, req);
} }
static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
struct fuse_inode *fi) struct fuse_inode *fi)
{ {
struct fuse_file *ff = NULL; struct fuse_file *ff = NULL;
spin_lock(&fc->lock); spin_lock(&fc->lock);
if (!WARN_ON(list_empty(&fi->write_files))) { if (!list_empty(&fi->write_files)) {
ff = list_entry(fi->write_files.next, struct fuse_file, ff = list_entry(fi->write_files.next, struct fuse_file,
write_entry); write_entry);
fuse_file_get(ff); fuse_file_get(ff);
...@@ -1680,6 +1675,29 @@ static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, ...@@ -1680,6 +1675,29 @@ static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
return ff; return ff;
} }
static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
struct fuse_inode *fi)
{
struct fuse_file *ff = __fuse_write_file_get(fc, fi);
WARN_ON(!ff);
return ff;
}
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_file *ff;
int err;
ff = __fuse_write_file_get(fc, fi);
err = fuse_flush_mtime(inode, ff);
if (ff)
fuse_file_put(ff, 0);
return err;
}
static int fuse_writepage_locked(struct page *page) static int fuse_writepage_locked(struct page *page)
{ {
struct address_space *mapping = page->mapping; struct address_space *mapping = page->mapping;
......
...@@ -119,8 +119,6 @@ enum { ...@@ -119,8 +119,6 @@ enum {
FUSE_I_INIT_RDPLUS, FUSE_I_INIT_RDPLUS,
/** An operation changing file size is in progress */ /** An operation changing file size is in progress */
FUSE_I_SIZE_UNSTABLE, FUSE_I_SIZE_UNSTABLE,
/** i_mtime has been updated locally; a flush to userspace needed */
FUSE_I_MTIME_DIRTY,
}; };
struct fuse_conn; struct fuse_conn;
...@@ -891,7 +889,8 @@ int fuse_dev_release(struct inode *inode, struct file *file); ...@@ -891,7 +889,8 @@ int fuse_dev_release(struct inode *inode, struct file *file);
bool fuse_write_update_size(struct inode *inode, loff_t pos); bool fuse_write_update_size(struct inode *inode, loff_t pos);
int fuse_flush_mtime(struct file *file, bool nofail); int fuse_flush_mtime(struct inode *inode, struct fuse_file *ff);
int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
int fuse_do_setattr(struct inode *inode, struct iattr *attr, int fuse_do_setattr(struct inode *inode, struct iattr *attr,
struct file *file); struct file *file);
......
...@@ -788,6 +788,7 @@ static const struct super_operations fuse_super_operations = { ...@@ -788,6 +788,7 @@ static const struct super_operations fuse_super_operations = {
.alloc_inode = fuse_alloc_inode, .alloc_inode = fuse_alloc_inode,
.destroy_inode = fuse_destroy_inode, .destroy_inode = fuse_destroy_inode,
.evict_inode = fuse_evict_inode, .evict_inode = fuse_evict_inode,
.write_inode = fuse_write_inode,
.drop_inode = generic_delete_inode, .drop_inode = generic_delete_inode,
.remount_fs = fuse_remount_fs, .remount_fs = fuse_remount_fs,
.put_super = fuse_put_super, .put_super = fuse_put_super,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册