diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/dir.c | 28 | ||||
-rw-r--r-- | fs/fuse/file.c | 44 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 5 | ||||
-rw-r--r-- | fs/fuse/inode.c | 1 |
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 | */ |
1600 | int fuse_flush_mtime(struct file *file, bool nofail) | 1600 | int 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 | ||
1667 | static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, | 1662 | static 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 | ||
1678 | static 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 | |||
1686 | int 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 | |||
1683 | static int fuse_writepage_locked(struct page *page) | 1701 | static 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 | ||
126 | struct fuse_conn; | 124 | struct fuse_conn; |
@@ -891,7 +889,8 @@ int fuse_dev_release(struct inode *inode, struct file *file); | |||
891 | 889 | ||
892 | bool fuse_write_update_size(struct inode *inode, loff_t pos); | 890 | bool fuse_write_update_size(struct inode *inode, loff_t pos); |
893 | 891 | ||
894 | int fuse_flush_mtime(struct file *file, bool nofail); | 892 | int fuse_flush_mtime(struct inode *inode, struct fuse_file *ff); |
893 | int fuse_write_inode(struct inode *inode, struct writeback_control *wbc); | ||
895 | 894 | ||
896 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 895 | int 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, |