aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-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,