When ATTR_ATIME_SET and ATTR_MTIME_SET are set in the ia_valid mask, the
notify_change() logic takes that to mean that the request should set
those values explicitly, and not override them with "now".

With the advent of delegated timestamps, similar functionality is needed
for the ctime. Add a ATTR_CTIME_SET flag, and use that to indicate that
the ctime should be accepted as-is. Also, clean up the if statements to
eliminate the extra negatives.

Signed-off-by: Jeff Layton <jlay...@kernel.org>
---
 fs/attr.c          | 15 +++++++++------
 include/linux/fs.h |  1 +
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/fs/attr.c b/fs/attr.c
index 
9caf63d20d03e86c535e9c8c91d49c2a34d34b7a..f0dabd2985989d283a931536a5fc53eda366b373
 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -463,15 +463,18 @@ int notify_change(struct mnt_idmap *idmap, struct dentry 
*dentry,
 
        now = current_time(inode);
 
-       attr->ia_ctime = now;
-       if (!(ia_valid & ATTR_ATIME_SET))
-               attr->ia_atime = now;
-       else
+       if (ia_valid & ATTR_ATIME_SET)
                attr->ia_atime = timestamp_truncate(attr->ia_atime, inode);
-       if (!(ia_valid & ATTR_MTIME_SET))
-               attr->ia_mtime = now;
        else
+               attr->ia_atime = now;
+       if (ia_valid & ATTR_CTIME_SET)
+               attr->ia_ctime = timestamp_truncate(attr->ia_ctime, inode);
+       else
+               attr->ia_ctime = now;
+       if (ia_valid & ATTR_MTIME_SET)
                attr->ia_mtime = timestamp_truncate(attr->ia_mtime, inode);
+       else
+               attr->ia_mtime = now;
 
        if (ia_valid & ATTR_KILL_PRIV) {
                error = security_inode_need_killpriv(dentry);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 
040c0036320fdf87a2379d494ab408a7991875bd..f18f45e88545c39716b917b1378fb7248367b41d
 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -237,6 +237,7 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t 
offset,
 #define ATTR_ATIME_SET (1 << 7)
 #define ATTR_MTIME_SET (1 << 8)
 #define ATTR_FORCE     (1 << 9) /* Not a change, but a change it */
+#define ATTR_CTIME_SET (1 << 10)
 #define ATTR_KILL_SUID (1 << 11)
 #define ATTR_KILL_SGID (1 << 12)
 #define ATTR_FILE      (1 << 13)

-- 
2.50.1


Reply via email to