diff options
author | Maxim Patlasov <MPatlasov@parallels.com> | 2014-04-28 08:19:25 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-04-28 08:19:25 -0400 |
commit | 3ad22c62dd23ad26c8737c300f455de60ba01f40 (patch) | |
tree | fb861c617f46885bb29a21ba8e50eebd27ed4968 | |
parent | 31f3267b4ba16b12fb9dd3b1953ea0f221cc2ab4 (diff) |
fuse: clear FUSE_I_CTIME_DIRTY flag on setattr
The patch addresses two use-cases when the flag may be safely cleared:
1. fuse_do_setattr() is called with ATTR_CTIME flag set in attr->ia_valid.
In this case attr->ia_ctime bears actual value. In-kernel fuse must send it
to the userspace server and then assign the value to inode->i_ctime.
2. fuse_do_setattr() is called with ATTR_SIZE flag set in attr->ia_valid,
whereas ATTR_CTIME is not set (truncate(2)).
In this case in-kernel fuse must sent "now" to the userspace server and then
assign the value to inode->i_ctime.
In both cases we could clear I_DIRTY_SYNC, but that needs more thought.
Signed-off-by: Maxim Patlasov <MPatlasov@parallels.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
-rw-r--r-- | fs/fuse/dir.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index f62ab8eedb5f..843dcf1222eb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1518,7 +1518,7 @@ static bool update_mtime(unsigned ivalid, bool trust_local_mtime) | |||
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, | 1520 | static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, |
1521 | bool trust_local_mtime) | 1521 | bool trust_local_cmtime) |
1522 | { | 1522 | { |
1523 | unsigned ivalid = iattr->ia_valid; | 1523 | unsigned ivalid = iattr->ia_valid; |
1524 | 1524 | ||
@@ -1537,13 +1537,18 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, | |||
1537 | if (!(ivalid & ATTR_ATIME_SET)) | 1537 | if (!(ivalid & ATTR_ATIME_SET)) |
1538 | arg->valid |= FATTR_ATIME_NOW; | 1538 | arg->valid |= FATTR_ATIME_NOW; |
1539 | } | 1539 | } |
1540 | if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_mtime)) { | 1540 | if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { |
1541 | arg->valid |= FATTR_MTIME; | 1541 | arg->valid |= FATTR_MTIME; |
1542 | arg->mtime = iattr->ia_mtime.tv_sec; | 1542 | arg->mtime = iattr->ia_mtime.tv_sec; |
1543 | arg->mtimensec = iattr->ia_mtime.tv_nsec; | 1543 | arg->mtimensec = iattr->ia_mtime.tv_nsec; |
1544 | if (!(ivalid & ATTR_MTIME_SET) && !trust_local_mtime) | 1544 | if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) |
1545 | arg->valid |= FATTR_MTIME_NOW; | 1545 | arg->valid |= FATTR_MTIME_NOW; |
1546 | } | 1546 | } |
1547 | if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { | ||
1548 | arg->valid |= FATTR_CTIME; | ||
1549 | arg->ctime = iattr->ia_ctime.tv_sec; | ||
1550 | arg->ctimensec = iattr->ia_ctime.tv_nsec; | ||
1551 | } | ||
1547 | } | 1552 | } |
1548 | 1553 | ||
1549 | /* | 1554 | /* |
@@ -1666,7 +1671,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1666 | bool is_wb = fc->writeback_cache; | 1671 | bool is_wb = fc->writeback_cache; |
1667 | loff_t oldsize; | 1672 | loff_t oldsize; |
1668 | int err; | 1673 | int err; |
1669 | bool trust_local_mtime = is_wb && S_ISREG(inode->i_mode); | 1674 | bool trust_local_cmtime = is_wb && S_ISREG(inode->i_mode); |
1670 | 1675 | ||
1671 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1676 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
1672 | attr->ia_valid |= ATTR_FORCE; | 1677 | attr->ia_valid |= ATTR_FORCE; |
@@ -1691,13 +1696,13 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1691 | if (is_truncate) { | 1696 | if (is_truncate) { |
1692 | fuse_set_nowrite(inode); | 1697 | fuse_set_nowrite(inode); |
1693 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); | 1698 | set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); |
1694 | if (trust_local_mtime && attr->ia_size != inode->i_size) | 1699 | if (trust_local_cmtime && attr->ia_size != inode->i_size) |
1695 | attr->ia_valid |= ATTR_MTIME; | 1700 | attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; |
1696 | } | 1701 | } |
1697 | 1702 | ||
1698 | memset(&inarg, 0, sizeof(inarg)); | 1703 | memset(&inarg, 0, sizeof(inarg)); |
1699 | memset(&outarg, 0, sizeof(outarg)); | 1704 | memset(&outarg, 0, sizeof(outarg)); |
1700 | iattr_to_fattr(attr, &inarg, trust_local_mtime); | 1705 | iattr_to_fattr(attr, &inarg, trust_local_cmtime); |
1701 | if (file) { | 1706 | if (file) { |
1702 | struct fuse_file *ff = file->private_data; | 1707 | struct fuse_file *ff = file->private_data; |
1703 | inarg.valid |= FATTR_FH; | 1708 | inarg.valid |= FATTR_FH; |
@@ -1726,8 +1731,11 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, | |||
1726 | 1731 | ||
1727 | spin_lock(&fc->lock); | 1732 | spin_lock(&fc->lock); |
1728 | /* the kernel maintains i_mtime locally */ | 1733 | /* the kernel maintains i_mtime locally */ |
1729 | if (trust_local_mtime && (attr->ia_valid & ATTR_MTIME)) { | 1734 | if (trust_local_cmtime) { |
1730 | inode->i_mtime = attr->ia_mtime; | 1735 | if (attr->ia_valid & ATTR_MTIME) |
1736 | inode->i_mtime = attr->ia_mtime; | ||
1737 | if (attr->ia_valid & ATTR_CTIME) | ||
1738 | inode->i_ctime = attr->ia_ctime; | ||
1731 | /* FIXME: clear I_DIRTY_SYNC? */ | 1739 | /* FIXME: clear I_DIRTY_SYNC? */ |
1732 | } | 1740 | } |
1733 | 1741 | ||