diff options
-rw-r--r-- | fs/fuse/cuse.c | 5 | ||||
-rw-r--r-- | fs/fuse/dir.c | 119 | ||||
-rw-r--r-- | fs/fuse/file.c | 286 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 22 | ||||
-rw-r--r-- | fs/fuse/inode.c | 29 | ||||
-rw-r--r-- | include/uapi/linux/fuse.h | 7 |
6 files changed, 384 insertions, 84 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index b96a49b37d66..23e363f38302 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -95,7 +95,7 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count, | |||
95 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | 95 | struct iovec iov = { .iov_base = buf, .iov_len = count }; |
96 | struct fuse_io_priv io = { .async = 0, .file = file }; | 96 | struct fuse_io_priv io = { .async = 0, .file = file }; |
97 | 97 | ||
98 | return fuse_direct_io(&io, &iov, 1, count, &pos, 0); | 98 | return fuse_direct_io(&io, &iov, 1, count, &pos, FUSE_DIO_CUSE); |
99 | } | 99 | } |
100 | 100 | ||
101 | static ssize_t cuse_write(struct file *file, const char __user *buf, | 101 | static ssize_t cuse_write(struct file *file, const char __user *buf, |
@@ -109,7 +109,8 @@ static ssize_t cuse_write(struct file *file, const char __user *buf, | |||
109 | * No locking or generic_write_checks(), the server is | 109 | * No locking or generic_write_checks(), the server is |
110 | * responsible for locking and sanity checks. | 110 | * responsible for locking and sanity checks. |
111 | */ | 111 | */ |
112 | return fuse_direct_io(&io, &iov, 1, count, &pos, 1); | 112 | return fuse_direct_io(&io, &iov, 1, count, &pos, |
113 | FUSE_DIO_WRITE | FUSE_DIO_CUSE); | ||
113 | } | 114 | } |
114 | 115 | ||
115 | static int cuse_open(struct inode *inode, struct file *file) | 116 | static int cuse_open(struct inode *inode, struct file *file) |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 1d1292c581c3..5b4e035b364c 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -839,6 +839,14 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, | |||
839 | struct kstat *stat) | 839 | struct kstat *stat) |
840 | { | 840 | { |
841 | unsigned int blkbits; | 841 | unsigned int blkbits; |
842 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
843 | |||
844 | /* see the comment in fuse_change_attributes() */ | ||
845 | if (fc->writeback_cache && S_ISREG(inode->i_mode)) { | ||
846 | attr->size = i_size_read(inode); | ||
847 | attr->mtime = inode->i_mtime.tv_sec; | ||
848 | attr->mtimensec = inode->i_mtime.tv_nsec; | ||
849 | } | ||
842 | 850 | ||
843 | stat->dev = inode->i_sb->s_dev; | 851 | stat->dev = inode->i_sb->s_dev; |
844 | stat->ino = attr->ino; | 852 | stat->ino = attr->ino; |
@@ -1477,12 +1485,16 @@ static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, | |||
1477 | FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); | 1485 | FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); |
1478 | } | 1486 | } |
1479 | 1487 | ||
1480 | static bool update_mtime(unsigned ivalid) | 1488 | static bool update_mtime(unsigned ivalid, bool trust_local_mtime) |
1481 | { | 1489 | { |
1482 | /* Always update if mtime is explicitly set */ | 1490 | /* Always update if mtime is explicitly set */ |
1483 | if (ivalid & ATTR_MTIME_SET) | 1491 | if (ivalid & ATTR_MTIME_SET) |
1484 | return true; | 1492 | return true; |
1485 | 1493 | ||
1494 | /* Or if kernel i_mtime is the official one */ | ||
1495 | if (trust_local_mtime) | ||
1496 | return true; | ||
1497 | |||
1486 | /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ | 1498 | /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ |
1487 | if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) | 1499 | if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) |
1488 | return false; | 1500 | return false; |
@@ -1491,7 +1503,8 @@ static bool update_mtime(unsigned ivalid) | |||
1491 | return true; | 1503 | return true; |
1492 | } | 1504 | } |
1493 | 1505 | ||
1494 | static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) | 1506 | static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, |
1507 | bool trust_local_mtime) | ||
1495 | { | 1508 | { |
1496 | unsigned ivalid = iattr->ia_valid; | 1509 | unsigned ivalid = iattr->ia_valid; |
1497 | 1510 | ||
@@ -1510,11 +1523,11 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) | |||
1510 | if (!(ivalid & ATTR_ATIME_SET)) | 1523 | if (!(ivalid & ATTR_ATIME_SET)) |
1511 | arg->valid |= FATTR_ATIME_NOW; | 1524 | arg->valid |= FATTR_ATIME_NOW; |
1512 | } | 1525 | } |
1513 | if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) { | 1526 | if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_mtime)) { |
1514 | arg->valid |= FATTR_MTIME; | 1527 | arg->valid |= FATTR_MTIME; |
1515 | arg->mtime = iattr->ia_mtime.tv_sec; | 1528 | arg->mtime = iattr->ia_mtime.tv_sec; |
1516 | arg->mtimensec = iattr->ia_mtime.tv_nsec; | 1529 | arg->mtimensec = iattr->ia_mtime.tv_nsec; |
1517 | if (!(ivalid & ATTR_MTIME_SET)) | 1530 | if (!(ivalid & ATTR_MTIME_SET) && !trust_local_mtime) |
1518 | arg->valid |= FATTR_MTIME_NOW; | 1531 | arg->valid |= FATTR_MTIME_NOW; |
1519 | } | 1532 | } |
1520 | } | 1533 | } |
@@ -1563,6 +1576,63 @@ void fuse_release_nowrite(struct inode *inode) | |||
1563 | spin_unlock(&fc->lock); | 1576 | spin_unlock(&fc->lock); |
1564 | } | 1577 | } |
1565 | 1578 | ||
1579 | static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_req *req, | ||
1580 | struct inode *inode, | ||
1581 | struct fuse_setattr_in *inarg_p, | ||
1582 | struct fuse_attr_out *outarg_p) | ||
1583 | { | ||
1584 | req->in.h.opcode = FUSE_SETATTR; | ||
1585 | req->in.h.nodeid = get_node_id(inode); | ||
1586 | req->in.numargs = 1; | ||
1587 | req->in.args[0].size = sizeof(*inarg_p); | ||
1588 | req->in.args[0].value = inarg_p; | ||
1589 | req->out.numargs = 1; | ||
1590 | if (fc->minor < 9) | ||
1591 | req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | ||
1592 | else | ||
1593 | req->out.args[0].size = sizeof(*outarg_p); | ||
1594 | req->out.args[0].value = outarg_p; | ||
1595 | } | ||
1596 | |||
1597 | /* | ||
1598 | * Flush inode->i_mtime to the server | ||
1599 | */ | ||
1600 | int fuse_flush_mtime(struct file *file, bool nofail) | ||
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); | ||
1605 | struct fuse_req *req = NULL; | ||
1606 | struct fuse_setattr_in inarg; | ||
1607 | struct fuse_attr_out outarg; | ||
1608 | int err; | ||
1609 | |||
1610 | if (nofail) { | ||
1611 | req = fuse_get_req_nofail_nopages(fc, file); | ||
1612 | } else { | ||
1613 | req = fuse_get_req_nopages(fc); | ||
1614 | if (IS_ERR(req)) | ||
1615 | return PTR_ERR(req); | ||
1616 | } | ||
1617 | |||
1618 | memset(&inarg, 0, sizeof(inarg)); | ||
1619 | memset(&outarg, 0, sizeof(outarg)); | ||
1620 | |||
1621 | inarg.valid |= FATTR_MTIME; | ||
1622 | inarg.mtime = inode->i_mtime.tv_sec; | ||
1623 | inarg.mtimensec = inode->i_mtime.tv_nsec; | ||
1624 | |||
1625 | fuse_setattr_fill(fc, req, inode, &inarg, &outarg); | ||
1626 | fuse_request_send(fc, req); | ||
1627 | err = req->out.h.error; | ||
1628 | fuse_put_request(fc, req); | ||
1629 | |||
1630 | if (!err) | ||
1631 | clear_bit(FUSE_I_MTIME_DIRTY, &fi->state); | ||
1632 | |||
1633 | return err; | ||
1634 | } | ||
1635 | |||
1566 | /* | 1636 | /* |
1567 | * Set attributes, and at the same time refresh them. | 1637 | * Set attributes, and at the same time refresh them. |
1568 | * | 1638 | * |
@@ -1580,8 +1650,10 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1580 | struct fuse_setattr_in inarg; | 1650 | struct fuse_setattr_in inarg; |
1581 | struct fuse_attr_out outarg; | 1651 | struct fuse_attr_out outarg; |
1582 | bool is_truncate = false; | 1652 | bool is_truncate = false; |
1653 | bool is_wb = fc->writeback_cache; | ||
1583 | loff_t oldsize; | 1654 | loff_t oldsize; |
1584 | int err; | 1655 | int err; |
1656 | bool trust_local_mtime = is_wb && S_ISREG(inode->i_mode); | ||
1585 | 1657 | ||
1586 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1658 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
1587 | attr->ia_valid |= ATTR_FORCE; | 1659 | attr->ia_valid |= ATTR_FORCE; |
@@ -1610,7 +1682,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1610 | 1682 | ||
1611 | memset(&inarg, 0, sizeof(inarg)); | 1683 | memset(&inarg, 0, sizeof(inarg)); |
1612 | memset(&outarg, 0, sizeof(outarg)); | 1684 | memset(&outarg, 0, sizeof(outarg)); |
1613 | iattr_to_fattr(attr, &inarg); | 1685 | iattr_to_fattr(attr, &inarg, trust_local_mtime); |
1614 | if (file) { | 1686 | if (file) { |
1615 | struct fuse_file *ff = file->private_data; | 1687 | struct fuse_file *ff = file->private_data; |
1616 | inarg.valid |= FATTR_FH; | 1688 | inarg.valid |= FATTR_FH; |
@@ -1621,17 +1693,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1621 | inarg.valid |= FATTR_LOCKOWNER; | 1693 | inarg.valid |= FATTR_LOCKOWNER; |
1622 | inarg.lock_owner = fuse_lock_owner_id(fc, current->files); | 1694 | inarg.lock_owner = fuse_lock_owner_id(fc, current->files); |
1623 | } | 1695 | } |
1624 | req->in.h.opcode = FUSE_SETATTR; | 1696 | fuse_setattr_fill(fc, req, inode, &inarg, &outarg); |
1625 | req->in.h.nodeid = get_node_id(inode); | ||
1626 | req->in.numargs = 1; | ||
1627 | req->in.args[0].size = sizeof(inarg); | ||
1628 | req->in.args[0].value = &inarg; | ||
1629 | req->out.numargs = 1; | ||
1630 | if (fc->minor < 9) | ||
1631 | req->out.args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE; | ||
1632 | else | ||
1633 | req->out.args[0].size = sizeof(outarg); | ||
1634 | req->out.args[0].value = &outarg; | ||
1635 | fuse_request_send(fc, req); | 1697 | fuse_request_send(fc, req); |
1636 | err = req->out.h.error; | 1698 | err = req->out.h.error; |
1637 | fuse_put_request(fc, req); | 1699 | fuse_put_request(fc, req); |
@@ -1648,10 +1710,18 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1648 | } | 1710 | } |
1649 | 1711 | ||
1650 | spin_lock(&fc->lock); | 1712 | spin_lock(&fc->lock); |
1713 | /* the kernel maintains i_mtime locally */ | ||
1714 | if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) { | ||
1715 | inode->i_mtime = attr->ia_mtime; | ||
1716 | clear_bit(FUSE_I_MTIME_DIRTY, &fi->state); | ||
1717 | } | ||
1718 | |||
1651 | fuse_change_attributes_common(inode, &outarg.attr, | 1719 | fuse_change_attributes_common(inode, &outarg.attr, |
1652 | attr_timeout(&outarg)); | 1720 | attr_timeout(&outarg)); |
1653 | oldsize = inode->i_size; | 1721 | oldsize = inode->i_size; |
1654 | i_size_write(inode, outarg.attr.size); | 1722 | /* see the comment in fuse_change_attributes() */ |
1723 | if (!is_wb || is_truncate || !S_ISREG(inode->i_mode)) | ||
1724 | i_size_write(inode, outarg.attr.size); | ||
1655 | 1725 | ||
1656 | if (is_truncate) { | 1726 | if (is_truncate) { |
1657 | /* NOTE: this may release/reacquire fc->lock */ | 1727 | /* NOTE: this may release/reacquire fc->lock */ |
@@ -1663,7 +1733,8 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1663 | * Only call invalidate_inode_pages2() after removing | 1733 | * Only call invalidate_inode_pages2() after removing |
1664 | * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. | 1734 | * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock. |
1665 | */ | 1735 | */ |
1666 | if (S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { | 1736 | if ((is_truncate || !is_wb) && |
1737 | S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { | ||
1667 | truncate_pagecache(inode, outarg.attr.size); | 1738 | truncate_pagecache(inode, outarg.attr.size); |
1668 | invalidate_inode_pages2(inode->i_mapping); | 1739 | invalidate_inode_pages2(inode->i_mapping); |
1669 | } | 1740 | } |
@@ -1875,6 +1946,17 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1875 | return err; | 1946 | return err; |
1876 | } | 1947 | } |
1877 | 1948 | ||
1949 | static int fuse_update_time(struct inode *inode, struct timespec *now, | ||
1950 | int flags) | ||
1951 | { | ||
1952 | if (flags & S_MTIME) { | ||
1953 | inode->i_mtime = *now; | ||
1954 | set_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state); | ||
1955 | BUG_ON(!S_ISREG(inode->i_mode)); | ||
1956 | } | ||
1957 | return 0; | ||
1958 | } | ||
1959 | |||
1878 | static const struct inode_operations fuse_dir_inode_operations = { | 1960 | static const struct inode_operations fuse_dir_inode_operations = { |
1879 | .lookup = fuse_lookup, | 1961 | .lookup = fuse_lookup, |
1880 | .mkdir = fuse_mkdir, | 1962 | .mkdir = fuse_mkdir, |
@@ -1914,6 +1996,7 @@ static const struct inode_operations fuse_common_inode_operations = { | |||
1914 | .getxattr = fuse_getxattr, | 1996 | .getxattr = fuse_getxattr, |
1915 | .listxattr = fuse_listxattr, | 1997 | .listxattr = fuse_listxattr, |
1916 | .removexattr = fuse_removexattr, | 1998 | .removexattr = fuse_removexattr, |
1999 | .update_time = fuse_update_time, | ||
1917 | }; | 2000 | }; |
1918 | 2001 | ||
1919 | static const struct inode_operations fuse_symlink_inode_operations = { | 2002 | static const struct inode_operations fuse_symlink_inode_operations = { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 77bcc303c3ae..65df7d8be4f5 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -188,6 +188,22 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | |||
188 | } | 188 | } |
189 | EXPORT_SYMBOL_GPL(fuse_do_open); | 189 | EXPORT_SYMBOL_GPL(fuse_do_open); |
190 | 190 | ||
191 | static void fuse_link_write_file(struct file *file) | ||
192 | { | ||
193 | struct inode *inode = file_inode(file); | ||
194 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
195 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
196 | struct fuse_file *ff = file->private_data; | ||
197 | /* | ||
198 | * file may be written through mmap, so chain it onto the | ||
199 | * inodes's write_file list | ||
200 | */ | ||
201 | spin_lock(&fc->lock); | ||
202 | if (list_empty(&ff->write_entry)) | ||
203 | list_add(&ff->write_entry, &fi->write_files); | ||
204 | spin_unlock(&fc->lock); | ||
205 | } | ||
206 | |||
191 | void fuse_finish_open(struct inode *inode, struct file *file) | 207 | void fuse_finish_open(struct inode *inode, struct file *file) |
192 | { | 208 | { |
193 | struct fuse_file *ff = file->private_data; | 209 | struct fuse_file *ff = file->private_data; |
@@ -208,6 +224,8 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
208 | spin_unlock(&fc->lock); | 224 | spin_unlock(&fc->lock); |
209 | fuse_invalidate_attr(inode); | 225 | fuse_invalidate_attr(inode); |
210 | } | 226 | } |
227 | if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache) | ||
228 | fuse_link_write_file(file); | ||
211 | } | 229 | } |
212 | 230 | ||
213 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) | 231 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) |
@@ -292,6 +310,15 @@ static int fuse_open(struct inode *inode, struct file *file) | |||
292 | 310 | ||
293 | static int fuse_release(struct inode *inode, struct file *file) | 311 | static int fuse_release(struct inode *inode, struct file *file) |
294 | { | 312 | { |
313 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
314 | |||
315 | /* see fuse_vma_close() for !writeback_cache case */ | ||
316 | if (fc->writeback_cache) | ||
317 | filemap_write_and_wait(file->f_mapping); | ||
318 | |||
319 | if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) | ||
320 | fuse_flush_mtime(file, true); | ||
321 | |||
295 | fuse_release_common(file, FUSE_RELEASE); | 322 | fuse_release_common(file, FUSE_RELEASE); |
296 | 323 | ||
297 | /* return value is ignored by VFS */ | 324 | /* return value is ignored by VFS */ |
@@ -333,12 +360,13 @@ u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) | |||
333 | } | 360 | } |
334 | 361 | ||
335 | /* | 362 | /* |
336 | * Check if page is under writeback | 363 | * Check if any page in a range is under writeback |
337 | * | 364 | * |
338 | * This is currently done by walking the list of writepage requests | 365 | * This is currently done by walking the list of writepage requests |
339 | * for the inode, which can be pretty inefficient. | 366 | * for the inode, which can be pretty inefficient. |
340 | */ | 367 | */ |
341 | static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) | 368 | static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from, |
369 | pgoff_t idx_to) | ||
342 | { | 370 | { |
343 | struct fuse_conn *fc = get_fuse_conn(inode); | 371 | struct fuse_conn *fc = get_fuse_conn(inode); |
344 | struct fuse_inode *fi = get_fuse_inode(inode); | 372 | struct fuse_inode *fi = get_fuse_inode(inode); |
@@ -351,8 +379,8 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) | |||
351 | 379 | ||
352 | BUG_ON(req->inode != inode); | 380 | BUG_ON(req->inode != inode); |
353 | curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT; | 381 | curr_index = req->misc.write.in.offset >> PAGE_CACHE_SHIFT; |
354 | if (curr_index <= index && | 382 | if (idx_from < curr_index + req->num_pages && |
355 | index < curr_index + req->num_pages) { | 383 | curr_index <= idx_to) { |
356 | found = true; | 384 | found = true; |
357 | break; | 385 | break; |
358 | } | 386 | } |
@@ -362,6 +390,11 @@ static bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) | |||
362 | return found; | 390 | return found; |
363 | } | 391 | } |
364 | 392 | ||
393 | static inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index) | ||
394 | { | ||
395 | return fuse_range_is_writeback(inode, index, index); | ||
396 | } | ||
397 | |||
365 | /* | 398 | /* |
366 | * Wait for page writeback to be completed. | 399 | * Wait for page writeback to be completed. |
367 | * | 400 | * |
@@ -376,6 +409,21 @@ static int fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index) | |||
376 | return 0; | 409 | return 0; |
377 | } | 410 | } |
378 | 411 | ||
412 | /* | ||
413 | * Wait for all pending writepages on the inode to finish. | ||
414 | * | ||
415 | * This is currently done by blocking further writes with FUSE_NOWRITE | ||
416 | * and waiting for all sent writes to complete. | ||
417 | * | ||
418 | * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage | ||
419 | * could conflict with truncation. | ||
420 | */ | ||
421 | static void fuse_sync_writes(struct inode *inode) | ||
422 | { | ||
423 | fuse_set_nowrite(inode); | ||
424 | fuse_release_nowrite(inode); | ||
425 | } | ||
426 | |||
379 | static int fuse_flush(struct file *file, fl_owner_t id) | 427 | static int fuse_flush(struct file *file, fl_owner_t id) |
380 | { | 428 | { |
381 | struct inode *inode = file_inode(file); | 429 | struct inode *inode = file_inode(file); |
@@ -391,6 +439,14 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
391 | if (fc->no_flush) | 439 | if (fc->no_flush) |
392 | return 0; | 440 | return 0; |
393 | 441 | ||
442 | err = filemap_write_and_wait(file->f_mapping); | ||
443 | if (err) | ||
444 | return err; | ||
445 | |||
446 | mutex_lock(&inode->i_mutex); | ||
447 | fuse_sync_writes(inode); | ||
448 | mutex_unlock(&inode->i_mutex); | ||
449 | |||
394 | req = fuse_get_req_nofail_nopages(fc, file); | 450 | req = fuse_get_req_nofail_nopages(fc, file); |
395 | memset(&inarg, 0, sizeof(inarg)); | 451 | memset(&inarg, 0, sizeof(inarg)); |
396 | inarg.fh = ff->fh; | 452 | inarg.fh = ff->fh; |
@@ -411,21 +467,6 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
411 | return err; | 467 | return err; |
412 | } | 468 | } |
413 | 469 | ||
414 | /* | ||
415 | * Wait for all pending writepages on the inode to finish. | ||
416 | * | ||
417 | * This is currently done by blocking further writes with FUSE_NOWRITE | ||
418 | * and waiting for all sent writes to complete. | ||
419 | * | ||
420 | * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage | ||
421 | * could conflict with truncation. | ||
422 | */ | ||
423 | static void fuse_sync_writes(struct inode *inode) | ||
424 | { | ||
425 | fuse_set_nowrite(inode); | ||
426 | fuse_release_nowrite(inode); | ||
427 | } | ||
428 | |||
429 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | 470 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |
430 | int datasync, int isdir) | 471 | int datasync, int isdir) |
431 | { | 472 | { |
@@ -459,6 +500,12 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
459 | 500 | ||
460 | fuse_sync_writes(inode); | 501 | fuse_sync_writes(inode); |
461 | 502 | ||
503 | if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) { | ||
504 | int err = fuse_flush_mtime(file, false); | ||
505 | if (err) | ||
506 | goto out; | ||
507 | } | ||
508 | |||
462 | req = fuse_get_req_nopages(fc); | 509 | req = fuse_get_req_nopages(fc); |
463 | if (IS_ERR(req)) { | 510 | if (IS_ERR(req)) { |
464 | err = PTR_ERR(req); | 511 | err = PTR_ERR(req); |
@@ -655,7 +702,33 @@ static void fuse_read_update_size(struct inode *inode, loff_t size, | |||
655 | spin_unlock(&fc->lock); | 702 | spin_unlock(&fc->lock); |
656 | } | 703 | } |
657 | 704 | ||
658 | static int fuse_readpage(struct file *file, struct page *page) | 705 | static void fuse_short_read(struct fuse_req *req, struct inode *inode, |
706 | u64 attr_ver) | ||
707 | { | ||
708 | size_t num_read = req->out.args[0].size; | ||
709 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
710 | |||
711 | if (fc->writeback_cache) { | ||
712 | /* | ||
713 | * A hole in a file. Some data after the hole are in page cache, | ||
714 | * but have not reached the client fs yet. So, the hole is not | ||
715 | * present there. | ||
716 | */ | ||
717 | int i; | ||
718 | int start_idx = num_read >> PAGE_CACHE_SHIFT; | ||
719 | size_t off = num_read & (PAGE_CACHE_SIZE - 1); | ||
720 | |||
721 | for (i = start_idx; i < req->num_pages; i++) { | ||
722 | zero_user_segment(req->pages[i], off, PAGE_CACHE_SIZE); | ||
723 | off = 0; | ||
724 | } | ||
725 | } else { | ||
726 | loff_t pos = page_offset(req->pages[0]) + num_read; | ||
727 | fuse_read_update_size(inode, pos, attr_ver); | ||
728 | } | ||
729 | } | ||
730 | |||
731 | static int fuse_do_readpage(struct file *file, struct page *page) | ||
659 | { | 732 | { |
660 | struct fuse_io_priv io = { .async = 0, .file = file }; | 733 | struct fuse_io_priv io = { .async = 0, .file = file }; |
661 | struct inode *inode = page->mapping->host; | 734 | struct inode *inode = page->mapping->host; |
@@ -667,10 +740,6 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
667 | u64 attr_ver; | 740 | u64 attr_ver; |
668 | int err; | 741 | int err; |
669 | 742 | ||
670 | err = -EIO; | ||
671 | if (is_bad_inode(inode)) | ||
672 | goto out; | ||
673 | |||
674 | /* | 743 | /* |
675 | * Page writeback can extend beyond the lifetime of the | 744 | * Page writeback can extend beyond the lifetime of the |
676 | * page-cache page, so make sure we read a properly synced | 745 | * page-cache page, so make sure we read a properly synced |
@@ -679,9 +748,8 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
679 | fuse_wait_on_page_writeback(inode, page->index); | 748 | fuse_wait_on_page_writeback(inode, page->index); |
680 | 749 | ||
681 | req = fuse_get_req(fc, 1); | 750 | req = fuse_get_req(fc, 1); |
682 | err = PTR_ERR(req); | ||
683 | if (IS_ERR(req)) | 751 | if (IS_ERR(req)) |
684 | goto out; | 752 | return PTR_ERR(req); |
685 | 753 | ||
686 | attr_ver = fuse_get_attr_version(fc); | 754 | attr_ver = fuse_get_attr_version(fc); |
687 | 755 | ||
@@ -692,18 +760,32 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
692 | req->page_descs[0].length = count; | 760 | req->page_descs[0].length = count; |
693 | num_read = fuse_send_read(req, &io, pos, count, NULL); | 761 | num_read = fuse_send_read(req, &io, pos, count, NULL); |
694 | err = req->out.h.error; | 762 | err = req->out.h.error; |
695 | fuse_put_request(fc, req); | ||
696 | 763 | ||
697 | if (!err) { | 764 | if (!err) { |
698 | /* | 765 | /* |
699 | * Short read means EOF. If file size is larger, truncate it | 766 | * Short read means EOF. If file size is larger, truncate it |
700 | */ | 767 | */ |
701 | if (num_read < count) | 768 | if (num_read < count) |
702 | fuse_read_update_size(inode, pos + num_read, attr_ver); | 769 | fuse_short_read(req, inode, attr_ver); |
703 | 770 | ||
704 | SetPageUptodate(page); | 771 | SetPageUptodate(page); |
705 | } | 772 | } |
706 | 773 | ||
774 | fuse_put_request(fc, req); | ||
775 | |||
776 | return err; | ||
777 | } | ||
778 | |||
779 | static int fuse_readpage(struct file *file, struct page *page) | ||
780 | { | ||
781 | struct inode *inode = page->mapping->host; | ||
782 | int err; | ||
783 | |||
784 | err = -EIO; | ||
785 | if (is_bad_inode(inode)) | ||
786 | goto out; | ||
787 | |||
788 | err = fuse_do_readpage(file, page); | ||
707 | fuse_invalidate_atime(inode); | 789 | fuse_invalidate_atime(inode); |
708 | out: | 790 | out: |
709 | unlock_page(page); | 791 | unlock_page(page); |
@@ -726,13 +808,9 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
726 | /* | 808 | /* |
727 | * Short read means EOF. If file size is larger, truncate it | 809 | * Short read means EOF. If file size is larger, truncate it |
728 | */ | 810 | */ |
729 | if (!req->out.h.error && num_read < count) { | 811 | if (!req->out.h.error && num_read < count) |
730 | loff_t pos; | 812 | fuse_short_read(req, inode, req->misc.read.attr_ver); |
731 | 813 | ||
732 | pos = page_offset(req->pages[0]) + num_read; | ||
733 | fuse_read_update_size(inode, pos, | ||
734 | req->misc.read.attr_ver); | ||
735 | } | ||
736 | fuse_invalidate_atime(inode); | 814 | fuse_invalidate_atime(inode); |
737 | } | 815 | } |
738 | 816 | ||
@@ -922,16 +1000,21 @@ static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io, | |||
922 | return req->misc.write.out.size; | 1000 | return req->misc.write.out.size; |
923 | } | 1001 | } |
924 | 1002 | ||
925 | void fuse_write_update_size(struct inode *inode, loff_t pos) | 1003 | bool fuse_write_update_size(struct inode *inode, loff_t pos) |
926 | { | 1004 | { |
927 | struct fuse_conn *fc = get_fuse_conn(inode); | 1005 | struct fuse_conn *fc = get_fuse_conn(inode); |
928 | struct fuse_inode *fi = get_fuse_inode(inode); | 1006 | struct fuse_inode *fi = get_fuse_inode(inode); |
1007 | bool ret = false; | ||
929 | 1008 | ||
930 | spin_lock(&fc->lock); | 1009 | spin_lock(&fc->lock); |
931 | fi->attr_version = ++fc->attr_version; | 1010 | fi->attr_version = ++fc->attr_version; |
932 | if (pos > inode->i_size) | 1011 | if (pos > inode->i_size) { |
933 | i_size_write(inode, pos); | 1012 | i_size_write(inode, pos); |
1013 | ret = true; | ||
1014 | } | ||
934 | spin_unlock(&fc->lock); | 1015 | spin_unlock(&fc->lock); |
1016 | |||
1017 | return ret; | ||
935 | } | 1018 | } |
936 | 1019 | ||
937 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | 1020 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, |
@@ -1116,6 +1199,15 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | |||
1116 | struct iov_iter i; | 1199 | struct iov_iter i; |
1117 | loff_t endbyte = 0; | 1200 | loff_t endbyte = 0; |
1118 | 1201 | ||
1202 | if (get_fuse_conn(inode)->writeback_cache) { | ||
1203 | /* Update size (EOF optimization) and mode (SUID clearing) */ | ||
1204 | err = fuse_update_attributes(mapping->host, NULL, file, NULL); | ||
1205 | if (err) | ||
1206 | return err; | ||
1207 | |||
1208 | return generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
1209 | } | ||
1210 | |||
1119 | WARN_ON(iocb->ki_pos != pos); | 1211 | WARN_ON(iocb->ki_pos != pos); |
1120 | 1212 | ||
1121 | ocount = 0; | 1213 | ocount = 0; |
@@ -1289,13 +1381,18 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p) | |||
1289 | 1381 | ||
1290 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, | 1382 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, |
1291 | unsigned long nr_segs, size_t count, loff_t *ppos, | 1383 | unsigned long nr_segs, size_t count, loff_t *ppos, |
1292 | int write) | 1384 | int flags) |
1293 | { | 1385 | { |
1386 | int write = flags & FUSE_DIO_WRITE; | ||
1387 | int cuse = flags & FUSE_DIO_CUSE; | ||
1294 | struct file *file = io->file; | 1388 | struct file *file = io->file; |
1389 | struct inode *inode = file->f_mapping->host; | ||
1295 | struct fuse_file *ff = file->private_data; | 1390 | struct fuse_file *ff = file->private_data; |
1296 | struct fuse_conn *fc = ff->fc; | 1391 | struct fuse_conn *fc = ff->fc; |
1297 | size_t nmax = write ? fc->max_write : fc->max_read; | 1392 | size_t nmax = write ? fc->max_write : fc->max_read; |
1298 | loff_t pos = *ppos; | 1393 | loff_t pos = *ppos; |
1394 | pgoff_t idx_from = pos >> PAGE_CACHE_SHIFT; | ||
1395 | pgoff_t idx_to = (pos + count - 1) >> PAGE_CACHE_SHIFT; | ||
1299 | ssize_t res = 0; | 1396 | ssize_t res = 0; |
1300 | struct fuse_req *req; | 1397 | struct fuse_req *req; |
1301 | struct iov_iter ii; | 1398 | struct iov_iter ii; |
@@ -1309,6 +1406,14 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, | |||
1309 | if (IS_ERR(req)) | 1406 | if (IS_ERR(req)) |
1310 | return PTR_ERR(req); | 1407 | return PTR_ERR(req); |
1311 | 1408 | ||
1409 | if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) { | ||
1410 | if (!write) | ||
1411 | mutex_lock(&inode->i_mutex); | ||
1412 | fuse_sync_writes(inode); | ||
1413 | if (!write) | ||
1414 | mutex_unlock(&inode->i_mutex); | ||
1415 | } | ||
1416 | |||
1312 | while (count) { | 1417 | while (count) { |
1313 | size_t nres; | 1418 | size_t nres; |
1314 | fl_owner_t owner = current->files; | 1419 | fl_owner_t owner = current->files; |
@@ -1397,7 +1502,8 @@ static ssize_t __fuse_direct_write(struct fuse_io_priv *io, | |||
1397 | 1502 | ||
1398 | res = generic_write_checks(file, ppos, &count, 0); | 1503 | res = generic_write_checks(file, ppos, &count, 0); |
1399 | if (!res) | 1504 | if (!res) |
1400 | res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1); | 1505 | res = fuse_direct_io(io, iov, nr_segs, count, ppos, |
1506 | FUSE_DIO_WRITE); | ||
1401 | 1507 | ||
1402 | fuse_invalidate_attr(inode); | 1508 | fuse_invalidate_attr(inode); |
1403 | 1509 | ||
@@ -1885,6 +1991,77 @@ out: | |||
1885 | return err; | 1991 | return err; |
1886 | } | 1992 | } |
1887 | 1993 | ||
1994 | /* | ||
1995 | * It's worthy to make sure that space is reserved on disk for the write, | ||
1996 | * but how to implement it without killing performance need more thinking. | ||
1997 | */ | ||
1998 | static int fuse_write_begin(struct file *file, struct address_space *mapping, | ||
1999 | loff_t pos, unsigned len, unsigned flags, | ||
2000 | struct page **pagep, void **fsdata) | ||
2001 | { | ||
2002 | pgoff_t index = pos >> PAGE_CACHE_SHIFT; | ||
2003 | struct fuse_conn *fc = get_fuse_conn(file->f_dentry->d_inode); | ||
2004 | struct page *page; | ||
2005 | loff_t fsize; | ||
2006 | int err = -ENOMEM; | ||
2007 | |||
2008 | WARN_ON(!fc->writeback_cache); | ||
2009 | |||
2010 | page = grab_cache_page_write_begin(mapping, index, flags); | ||
2011 | if (!page) | ||
2012 | goto error; | ||
2013 | |||
2014 | fuse_wait_on_page_writeback(mapping->host, page->index); | ||
2015 | |||
2016 | if (PageUptodate(page) || len == PAGE_CACHE_SIZE) | ||
2017 | goto success; | ||
2018 | /* | ||
2019 | * Check if the start this page comes after the end of file, in which | ||
2020 | * case the readpage can be optimized away. | ||
2021 | */ | ||
2022 | fsize = i_size_read(mapping->host); | ||
2023 | if (fsize <= (pos & PAGE_CACHE_MASK)) { | ||
2024 | size_t off = pos & ~PAGE_CACHE_MASK; | ||
2025 | if (off) | ||
2026 | zero_user_segment(page, 0, off); | ||
2027 | goto success; | ||
2028 | } | ||
2029 | err = fuse_do_readpage(file, page); | ||
2030 | if (err) | ||
2031 | goto cleanup; | ||
2032 | success: | ||
2033 | *pagep = page; | ||
2034 | return 0; | ||
2035 | |||
2036 | cleanup: | ||
2037 | unlock_page(page); | ||
2038 | page_cache_release(page); | ||
2039 | error: | ||
2040 | return err; | ||
2041 | } | ||
2042 | |||
2043 | static int fuse_write_end(struct file *file, struct address_space *mapping, | ||
2044 | loff_t pos, unsigned len, unsigned copied, | ||
2045 | struct page *page, void *fsdata) | ||
2046 | { | ||
2047 | struct inode *inode = page->mapping->host; | ||
2048 | |||
2049 | if (!PageUptodate(page)) { | ||
2050 | /* Zero any unwritten bytes at the end of the page */ | ||
2051 | size_t endoff = (pos + copied) & ~PAGE_CACHE_MASK; | ||
2052 | if (endoff) | ||
2053 | zero_user_segment(page, endoff, PAGE_CACHE_SIZE); | ||
2054 | SetPageUptodate(page); | ||
2055 | } | ||
2056 | |||
2057 | fuse_write_update_size(inode, pos + copied); | ||
2058 | set_page_dirty(page); | ||
2059 | unlock_page(page); | ||
2060 | page_cache_release(page); | ||
2061 | |||
2062 | return copied; | ||
2063 | } | ||
2064 | |||
1888 | static int fuse_launder_page(struct page *page) | 2065 | static int fuse_launder_page(struct page *page) |
1889 | { | 2066 | { |
1890 | int err = 0; | 2067 | int err = 0; |
@@ -1946,20 +2123,9 @@ static const struct vm_operations_struct fuse_file_vm_ops = { | |||
1946 | 2123 | ||
1947 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | 2124 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) |
1948 | { | 2125 | { |
1949 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) { | 2126 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) |
1950 | struct inode *inode = file_inode(file); | 2127 | fuse_link_write_file(file); |
1951 | struct fuse_conn *fc = get_fuse_conn(inode); | 2128 | |
1952 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
1953 | struct fuse_file *ff = file->private_data; | ||
1954 | /* | ||
1955 | * file may be written through mmap, so chain it onto the | ||
1956 | * inodes's write_file list | ||
1957 | */ | ||
1958 | spin_lock(&fc->lock); | ||
1959 | if (list_empty(&ff->write_entry)) | ||
1960 | list_add(&ff->write_entry, &fi->write_files); | ||
1961 | spin_unlock(&fc->lock); | ||
1962 | } | ||
1963 | file_accessed(file); | 2129 | file_accessed(file); |
1964 | vma->vm_ops = &fuse_file_vm_ops; | 2130 | vma->vm_ops = &fuse_file_vm_ops; |
1965 | return 0; | 2131 | return 0; |
@@ -2606,7 +2772,7 @@ static void fuse_register_polled_file(struct fuse_conn *fc, | |||
2606 | { | 2772 | { |
2607 | spin_lock(&fc->lock); | 2773 | spin_lock(&fc->lock); |
2608 | if (RB_EMPTY_NODE(&ff->polled_node)) { | 2774 | if (RB_EMPTY_NODE(&ff->polled_node)) { |
2609 | struct rb_node **link, *parent; | 2775 | struct rb_node **link, *uninitialized_var(parent); |
2610 | 2776 | ||
2611 | link = fuse_find_polled_node(fc, ff->kh, &parent); | 2777 | link = fuse_find_polled_node(fc, ff->kh, &parent); |
2612 | BUG_ON(*link); | 2778 | BUG_ON(*link); |
@@ -2850,8 +3016,16 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2850 | goto out; | 3016 | goto out; |
2851 | 3017 | ||
2852 | /* we could have extended the file */ | 3018 | /* we could have extended the file */ |
2853 | if (!(mode & FALLOC_FL_KEEP_SIZE)) | 3019 | if (!(mode & FALLOC_FL_KEEP_SIZE)) { |
2854 | fuse_write_update_size(inode, offset + length); | 3020 | bool changed = fuse_write_update_size(inode, offset + length); |
3021 | |||
3022 | if (changed && fc->writeback_cache) { | ||
3023 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
3024 | |||
3025 | inode->i_mtime = current_fs_time(inode->i_sb); | ||
3026 | set_bit(FUSE_I_MTIME_DIRTY, &fi->state); | ||
3027 | } | ||
3028 | } | ||
2855 | 3029 | ||
2856 | if (mode & FALLOC_FL_PUNCH_HOLE) | 3030 | if (mode & FALLOC_FL_PUNCH_HOLE) |
2857 | truncate_pagecache_range(inode, offset, offset + length - 1); | 3031 | truncate_pagecache_range(inode, offset, offset + length - 1); |
@@ -2915,6 +3089,8 @@ static const struct address_space_operations fuse_file_aops = { | |||
2915 | .set_page_dirty = __set_page_dirty_nobuffers, | 3089 | .set_page_dirty = __set_page_dirty_nobuffers, |
2916 | .bmap = fuse_bmap, | 3090 | .bmap = fuse_bmap, |
2917 | .direct_IO = fuse_direct_IO, | 3091 | .direct_IO = fuse_direct_IO, |
3092 | .write_begin = fuse_write_begin, | ||
3093 | .write_end = fuse_write_end, | ||
2918 | }; | 3094 | }; |
2919 | 3095 | ||
2920 | void fuse_init_file_inode(struct inode *inode) | 3096 | void fuse_init_file_inode(struct inode *inode) |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 2da5db2c8bdb..a257ed8ebee6 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -119,6 +119,8 @@ 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, | ||
122 | }; | 124 | }; |
123 | 125 | ||
124 | struct fuse_conn; | 126 | struct fuse_conn; |
@@ -480,6 +482,9 @@ struct fuse_conn { | |||
480 | /** Set if bdi is valid */ | 482 | /** Set if bdi is valid */ |
481 | unsigned bdi_initialized:1; | 483 | unsigned bdi_initialized:1; |
482 | 484 | ||
485 | /** write-back cache policy (default is write-through) */ | ||
486 | unsigned writeback_cache:1; | ||
487 | |||
483 | /* | 488 | /* |
484 | * The following bitfields are only for optimization purposes | 489 | * The following bitfields are only for optimization purposes |
485 | * and hence races in setting them will not cause malfunction | 490 | * and hence races in setting them will not cause malfunction |
@@ -863,9 +868,20 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
863 | 868 | ||
864 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 869 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
865 | bool isdir); | 870 | bool isdir); |
871 | |||
872 | /** | ||
873 | * fuse_direct_io() flags | ||
874 | */ | ||
875 | |||
876 | /** If set, it is WRITE; otherwise - READ */ | ||
877 | #define FUSE_DIO_WRITE (1 << 0) | ||
878 | |||
879 | /** CUSE pass fuse_direct_io() a file which f_mapping->host is not from FUSE */ | ||
880 | #define FUSE_DIO_CUSE (1 << 1) | ||
881 | |||
866 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, | 882 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, |
867 | unsigned long nr_segs, size_t count, loff_t *ppos, | 883 | unsigned long nr_segs, size_t count, loff_t *ppos, |
868 | int write); | 884 | int flags); |
869 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | 885 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, |
870 | unsigned int flags); | 886 | unsigned int flags); |
871 | long fuse_ioctl_common(struct file *file, unsigned int cmd, | 887 | long fuse_ioctl_common(struct file *file, unsigned int cmd, |
@@ -873,7 +889,9 @@ long fuse_ioctl_common(struct file *file, unsigned int cmd, | |||
873 | unsigned fuse_file_poll(struct file *file, poll_table *wait); | 889 | unsigned fuse_file_poll(struct file *file, poll_table *wait); |
874 | int fuse_dev_release(struct inode *inode, struct file *file); | 890 | int fuse_dev_release(struct inode *inode, struct file *file); |
875 | 891 | ||
876 | void fuse_write_update_size(struct inode *inode, loff_t pos); | 892 | bool fuse_write_update_size(struct inode *inode, loff_t pos); |
893 | |||
894 | int fuse_flush_mtime(struct file *file, bool nofail); | ||
877 | 895 | ||
878 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | 896 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, |
879 | struct file *file); | 897 | struct file *file); |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9c761b611c54..b4bff1b15028 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -170,8 +170,11 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |||
170 | inode->i_blocks = attr->blocks; | 170 | inode->i_blocks = attr->blocks; |
171 | inode->i_atime.tv_sec = attr->atime; | 171 | inode->i_atime.tv_sec = attr->atime; |
172 | inode->i_atime.tv_nsec = attr->atimensec; | 172 | inode->i_atime.tv_nsec = attr->atimensec; |
173 | inode->i_mtime.tv_sec = attr->mtime; | 173 | /* mtime from server may be stale due to local buffered write */ |
174 | inode->i_mtime.tv_nsec = attr->mtimensec; | 174 | if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) { |
175 | inode->i_mtime.tv_sec = attr->mtime; | ||
176 | inode->i_mtime.tv_nsec = attr->mtimensec; | ||
177 | } | ||
175 | inode->i_ctime.tv_sec = attr->ctime; | 178 | inode->i_ctime.tv_sec = attr->ctime; |
176 | inode->i_ctime.tv_nsec = attr->ctimensec; | 179 | inode->i_ctime.tv_nsec = attr->ctimensec; |
177 | 180 | ||
@@ -197,6 +200,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
197 | { | 200 | { |
198 | struct fuse_conn *fc = get_fuse_conn(inode); | 201 | struct fuse_conn *fc = get_fuse_conn(inode); |
199 | struct fuse_inode *fi = get_fuse_inode(inode); | 202 | struct fuse_inode *fi = get_fuse_inode(inode); |
203 | bool is_wb = fc->writeback_cache; | ||
200 | loff_t oldsize; | 204 | loff_t oldsize; |
201 | struct timespec old_mtime; | 205 | struct timespec old_mtime; |
202 | 206 | ||
@@ -211,10 +215,16 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, | |||
211 | fuse_change_attributes_common(inode, attr, attr_valid); | 215 | fuse_change_attributes_common(inode, attr, attr_valid); |
212 | 216 | ||
213 | oldsize = inode->i_size; | 217 | oldsize = inode->i_size; |
214 | i_size_write(inode, attr->size); | 218 | /* |
219 | * In case of writeback_cache enabled, the cached writes beyond EOF | ||
220 | * extend local i_size without keeping userspace server in sync. So, | ||
221 | * attr->size coming from server can be stale. We cannot trust it. | ||
222 | */ | ||
223 | if (!is_wb || !S_ISREG(inode->i_mode)) | ||
224 | i_size_write(inode, attr->size); | ||
215 | spin_unlock(&fc->lock); | 225 | spin_unlock(&fc->lock); |
216 | 226 | ||
217 | if (S_ISREG(inode->i_mode)) { | 227 | if (!is_wb && S_ISREG(inode->i_mode)) { |
218 | bool inval = false; | 228 | bool inval = false; |
219 | 229 | ||
220 | if (oldsize != attr->size) { | 230 | if (oldsize != attr->size) { |
@@ -243,6 +253,8 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | |||
243 | { | 253 | { |
244 | inode->i_mode = attr->mode & S_IFMT; | 254 | inode->i_mode = attr->mode & S_IFMT; |
245 | inode->i_size = attr->size; | 255 | inode->i_size = attr->size; |
256 | inode->i_mtime.tv_sec = attr->mtime; | ||
257 | inode->i_mtime.tv_nsec = attr->mtimensec; | ||
246 | if (S_ISREG(inode->i_mode)) { | 258 | if (S_ISREG(inode->i_mode)) { |
247 | fuse_init_common(inode); | 259 | fuse_init_common(inode); |
248 | fuse_init_file_inode(inode); | 260 | fuse_init_file_inode(inode); |
@@ -289,7 +301,9 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
289 | return NULL; | 301 | return NULL; |
290 | 302 | ||
291 | if ((inode->i_state & I_NEW)) { | 303 | if ((inode->i_state & I_NEW)) { |
292 | inode->i_flags |= S_NOATIME|S_NOCMTIME; | 304 | inode->i_flags |= S_NOATIME; |
305 | if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) | ||
306 | inode->i_flags |= S_NOCMTIME; | ||
293 | inode->i_generation = generation; | 307 | inode->i_generation = generation; |
294 | inode->i_data.backing_dev_info = &fc->bdi; | 308 | inode->i_data.backing_dev_info = &fc->bdi; |
295 | fuse_init_inode(inode, attr); | 309 | fuse_init_inode(inode, attr); |
@@ -873,6 +887,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
873 | } | 887 | } |
874 | if (arg->flags & FUSE_ASYNC_DIO) | 888 | if (arg->flags & FUSE_ASYNC_DIO) |
875 | fc->async_dio = 1; | 889 | fc->async_dio = 1; |
890 | if (arg->flags & FUSE_WRITEBACK_CACHE) | ||
891 | fc->writeback_cache = 1; | ||
876 | } else { | 892 | } else { |
877 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 893 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
878 | fc->no_lock = 1; | 894 | fc->no_lock = 1; |
@@ -900,7 +916,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
900 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | | 916 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
901 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | | 917 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | |
902 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | | 918 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | |
903 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO; | 919 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | |
920 | FUSE_WRITEBACK_CACHE; | ||
904 | req->in.h.opcode = FUSE_INIT; | 921 | req->in.h.opcode = FUSE_INIT; |
905 | req->in.numargs = 1; | 922 | req->in.numargs = 1; |
906 | req->in.args[0].size = sizeof(*arg); | 923 | req->in.args[0].size = sizeof(*arg); |
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 60bb2f9f7b74..cf4750e1bb49 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h | |||
@@ -93,6 +93,9 @@ | |||
93 | * | 93 | * |
94 | * 7.22 | 94 | * 7.22 |
95 | * - add FUSE_ASYNC_DIO | 95 | * - add FUSE_ASYNC_DIO |
96 | * | ||
97 | * 7.23 | ||
98 | * - add FUSE_WRITEBACK_CACHE | ||
96 | */ | 99 | */ |
97 | 100 | ||
98 | #ifndef _LINUX_FUSE_H | 101 | #ifndef _LINUX_FUSE_H |
@@ -128,7 +131,7 @@ | |||
128 | #define FUSE_KERNEL_VERSION 7 | 131 | #define FUSE_KERNEL_VERSION 7 |
129 | 132 | ||
130 | /** Minor version number of this interface */ | 133 | /** Minor version number of this interface */ |
131 | #define FUSE_KERNEL_MINOR_VERSION 22 | 134 | #define FUSE_KERNEL_MINOR_VERSION 23 |
132 | 135 | ||
133 | /** The node ID of the root inode */ | 136 | /** The node ID of the root inode */ |
134 | #define FUSE_ROOT_ID 1 | 137 | #define FUSE_ROOT_ID 1 |
@@ -219,6 +222,7 @@ struct fuse_file_lock { | |||
219 | * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one) | 222 | * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one) |
220 | * FUSE_READDIRPLUS_AUTO: adaptive readdirplus | 223 | * FUSE_READDIRPLUS_AUTO: adaptive readdirplus |
221 | * FUSE_ASYNC_DIO: asynchronous direct I/O submission | 224 | * FUSE_ASYNC_DIO: asynchronous direct I/O submission |
225 | * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes | ||
222 | */ | 226 | */ |
223 | #define FUSE_ASYNC_READ (1 << 0) | 227 | #define FUSE_ASYNC_READ (1 << 0) |
224 | #define FUSE_POSIX_LOCKS (1 << 1) | 228 | #define FUSE_POSIX_LOCKS (1 << 1) |
@@ -236,6 +240,7 @@ struct fuse_file_lock { | |||
236 | #define FUSE_DO_READDIRPLUS (1 << 13) | 240 | #define FUSE_DO_READDIRPLUS (1 << 13) |
237 | #define FUSE_READDIRPLUS_AUTO (1 << 14) | 241 | #define FUSE_READDIRPLUS_AUTO (1 << 14) |
238 | #define FUSE_ASYNC_DIO (1 << 15) | 242 | #define FUSE_ASYNC_DIO (1 << 15) |
243 | #define FUSE_WRITEBACK_CACHE (1 << 16) | ||
239 | 244 | ||
240 | /** | 245 | /** |
241 | * CUSE INIT request/reply flags | 246 | * CUSE INIT request/reply flags |