aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-04-28 08:19:23 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2014-04-28 08:19:23 -0400
commit1e18bda86e2dcc4ecb176213ee34649c93ad1396 (patch)
tree0862a86519028449c13b6e4ecd6762d91533341c /fs/fuse
parent22401e7b7a686bff02549cd648ba6f73f8dba868 (diff)
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: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dir.c28
-rw-r--r--fs/fuse/file.c44
-rw-r--r--fs/fuse/fuse_i.h5
-rw-r--r--fs/fuse/inode.c1
4 files changed, 45 insertions, 33 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 5e361b122526..8c233834591f 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1597,23 +1597,17 @@ static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req,
1597/* 1597/*
1598 * Flush inode->i_mtime to the server 1598 * Flush inode->i_mtime to the server
1599 */ 1599 */
1600int fuse_flush_mtime(struct file *file, bool nofail) 1600int fuse_flush_mtime(struct inode *inode, struct fuse_file *ff)
1601{ 1601{
1602 struct inode *inode = file->f_mapping->host;
1603 struct fuse_inode *fi = get_fuse_inode(inode);
1604 struct fuse_conn *fc = get_fuse_conn(inode); 1602 struct fuse_conn *fc = get_fuse_conn(inode);
1605 struct fuse_req *req = NULL; 1603 struct fuse_req *req;
1606 struct fuse_setattr_in inarg; 1604 struct fuse_setattr_in inarg;
1607 struct fuse_attr_out outarg; 1605 struct fuse_attr_out outarg;
1608 int err; 1606 int err;
1609 1607
1610 if (nofail) { 1608 req = fuse_get_req_nopages(fc);
1611 req = fuse_get_req_nofail_nopages(fc, file); 1609 if (IS_ERR(req))
1612 } else { 1610 return PTR_ERR(req);
1613 req = fuse_get_req_nopages(fc);
1614 if (IS_ERR(req))
1615 return PTR_ERR(req);
1616 }
1617 1611
1618 memset(&inarg, 0, sizeof(inarg)); 1612 memset(&inarg, 0, sizeof(inarg));
1619 memset(&outarg, 0, sizeof(outarg)); 1613 memset(&outarg, 0, sizeof(outarg));
@@ -1621,15 +1615,15 @@ int fuse_flush_mtime(struct file *file, bool nofail)
1621 inarg.valid |= FATTR_MTIME; 1615 inarg.valid |= FATTR_MTIME;
1622 inarg.mtime = inode->i_mtime.tv_sec; 1616 inarg.mtime = inode->i_mtime.tv_sec;
1623 inarg.mtimensec = inode->i_mtime.tv_nsec; 1617 inarg.mtimensec = inode->i_mtime.tv_nsec;
1624 1618 if (ff) {
1619 inarg.valid |= FATTR_FH;
1620 inarg.fh = ff->fh;
1621 }
1625 fuse_setattr_fill(fc, req, inode, &inarg, &outarg); 1622 fuse_setattr_fill(fc, req, inode, &inarg, &outarg);
1626 fuse_request_send(fc, req); 1623 fuse_request_send(fc, req);
1627 err = req->out.h.error; 1624 err = req->out.h.error;
1628 fuse_put_request(fc, req); 1625 fuse_put_request(fc, req);
1629 1626
1630 if (!err)
1631 clear_bit(FUSE_I_MTIME_DIRTY, &fi->state);
1632
1633 return err; 1627 return err;
1634} 1628}
1635 1629
@@ -1715,7 +1709,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr,
1715 /* the kernel maintains i_mtime locally */ 1709 /* the kernel maintains i_mtime locally */
1716 if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) { 1710 if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) {
1717 inode->i_mtime = attr->ia_mtime; 1711 inode->i_mtime = attr->ia_mtime;
1718 clear_bit(FUSE_I_MTIME_DIRTY, &fi->state); 1712 /* FIXME: clear I_DIRTY_SYNC? */
1719 } 1713 }
1720 1714
1721 fuse_change_attributes_common(inode, &outarg.attr, 1715 fuse_change_attributes_common(inode, &outarg.attr,
@@ -1953,7 +1947,7 @@ static int fuse_update_time(struct inode *inode, struct timespec *now,
1953{ 1947{
1954 if (flags & S_MTIME) { 1948 if (flags & S_MTIME) {
1955 inode->i_mtime = *now; 1949 inode->i_mtime = *now;
1956 set_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state); 1950 mark_inode_dirty_sync(inode);
1957 BUG_ON(!S_ISREG(inode->i_mode)); 1951 BUG_ON(!S_ISREG(inode->i_mode));
1958 } 1952 }
1959 return 0; 1953 return 0;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 65586a567d0d..d228c3962ffd 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -324,10 +324,7 @@ static int fuse_release(struct inode *inode, struct file *file)
324 324
325 /* see fuse_vma_close() for !writeback_cache case */ 325 /* see fuse_vma_close() for !writeback_cache case */
326 if (fc->writeback_cache) 326 if (fc->writeback_cache)
327 filemap_write_and_wait(file->f_mapping); 327 write_inode_now(inode, 1);
328
329 if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state))
330 fuse_flush_mtime(file, true);
331 328
332 fuse_release_common(file, FUSE_RELEASE); 329 fuse_release_common(file, FUSE_RELEASE);
333 330
@@ -449,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id)
449 if (fc->no_flush) 446 if (fc->no_flush)
450 return 0; 447 return 0;
451 448
452 err = filemap_write_and_wait(file->f_mapping); 449 err = write_inode_now(inode, 1);
453 if (err) 450 if (err)
454 return err; 451 return err;
455 452
@@ -502,12 +499,10 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
502 goto out; 499 goto out;
503 500
504 fuse_sync_writes(inode); 501 fuse_sync_writes(inode);
502 err = sync_inode_metadata(inode, 1);
503 if (err)
504 goto out;
505 505
506 if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) {
507 err = fuse_flush_mtime(file, false);
508 if (err)
509 goto out;
510 }
511 if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) 506 if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
512 goto out; 507 goto out;
513 508
@@ -1664,13 +1659,13 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req)
1664 fuse_writepage_free(fc, req); 1659 fuse_writepage_free(fc, req);
1665} 1660}
1666 1661
1667static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, 1662static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
1668 struct fuse_inode *fi) 1663 struct fuse_inode *fi)
1669{ 1664{
1670 struct fuse_file *ff = NULL; 1665 struct fuse_file *ff = NULL;
1671 1666
1672 spin_lock(&fc->lock); 1667 spin_lock(&fc->lock);
1673 if (!WARN_ON(list_empty(&fi->write_files))) { 1668 if (!list_empty(&fi->write_files)) {
1674 ff = list_entry(fi->write_files.next, struct fuse_file, 1669 ff = list_entry(fi->write_files.next, struct fuse_file,
1675 write_entry); 1670 write_entry);
1676 fuse_file_get(ff); 1671 fuse_file_get(ff);
@@ -1680,6 +1675,29 @@ static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
1680 return ff; 1675 return ff;
1681} 1676}
1682 1677
1678static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
1679 struct fuse_inode *fi)
1680{
1681 struct fuse_file *ff = __fuse_write_file_get(fc, fi);
1682 WARN_ON(!ff);
1683 return ff;
1684}
1685
1686int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
1687{
1688 struct fuse_conn *fc = get_fuse_conn(inode);
1689 struct fuse_inode *fi = get_fuse_inode(inode);
1690 struct fuse_file *ff;
1691 int err;
1692
1693 ff = __fuse_write_file_get(fc, fi);
1694 err = fuse_flush_mtime(inode, ff);
1695 if (ff)
1696 fuse_file_put(ff, 0);
1697
1698 return err;
1699}
1700
1683static int fuse_writepage_locked(struct page *page) 1701static int fuse_writepage_locked(struct page *page)
1684{ 1702{
1685 struct address_space *mapping = page->mapping; 1703 struct address_space *mapping = page->mapping;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index adfa2d505c1a..d2f10054b9a1 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -119,8 +119,6 @@ enum {
119 FUSE_I_INIT_RDPLUS, 119 FUSE_I_INIT_RDPLUS,
120 /** An operation changing file size is in progress */ 120 /** An operation changing file size is in progress */
121 FUSE_I_SIZE_UNSTABLE, 121 FUSE_I_SIZE_UNSTABLE,
122 /** i_mtime has been updated locally; a flush to userspace needed */
123 FUSE_I_MTIME_DIRTY,
124}; 122};
125 123
126struct fuse_conn; 124struct fuse_conn;
@@ -891,7 +889,8 @@ int fuse_dev_release(struct inode *inode, struct file *file);
891 889
892bool fuse_write_update_size(struct inode *inode, loff_t pos); 890bool fuse_write_update_size(struct inode *inode, loff_t pos);
893 891
894int fuse_flush_mtime(struct file *file, bool nofail); 892int fuse_flush_mtime(struct inode *inode, struct fuse_file *ff);
893int fuse_write_inode(struct inode *inode, struct writeback_control *wbc);
895 894
896int fuse_do_setattr(struct inode *inode, struct iattr *attr, 895int fuse_do_setattr(struct inode *inode, struct iattr *attr,
897 struct file *file); 896 struct file *file);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 299e553fcdfd..5997e4940512 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -788,6 +788,7 @@ static const struct super_operations fuse_super_operations = {
788 .alloc_inode = fuse_alloc_inode, 788 .alloc_inode = fuse_alloc_inode,
789 .destroy_inode = fuse_destroy_inode, 789 .destroy_inode = fuse_destroy_inode,
790 .evict_inode = fuse_evict_inode, 790 .evict_inode = fuse_evict_inode,
791 .write_inode = fuse_write_inode,
791 .drop_inode = generic_delete_inode, 792 .drop_inode = generic_delete_inode,
792 .remount_fs = fuse_remount_fs, 793 .remount_fs = fuse_remount_fs,
793 .put_super = fuse_put_super, 794 .put_super = fuse_put_super,