}
 
 void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
-                                  u64 attr_valid)
+                                  u64 attr_valid, u32 cache_mask)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
        inode->i_atime.tv_sec   = attr->atime;
        inode->i_atime.tv_nsec  = attr->atimensec;
        /* mtime from server may be stale due to local buffered write */
-       if (!fc->writeback_cache || !S_ISREG(inode->i_mode)) {
+       if (!(cache_mask & STATX_MTIME)) {
                inode->i_mtime.tv_sec   = attr->mtime;
                inode->i_mtime.tv_nsec  = attr->mtimensec;
+       }
+       if (!(cache_mask & STATX_CTIME)) {
                inode->i_ctime.tv_sec   = attr->ctime;
                inode->i_ctime.tv_nsec  = attr->ctimensec;
        }
        inode->i_flags &= ~S_NOSEC;
 }
 
+u32 fuse_get_cache_mask(struct inode *inode)
+{
+       struct fuse_conn *fc = get_fuse_conn(inode);
+
+       if (!fc->writeback_cache || !S_ISREG(inode->i_mode))
+               return 0;
+
+       return STATX_MTIME | STATX_CTIME | STATX_SIZE;
+}
+
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
                            u64 attr_valid, u64 attr_version)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
-       bool is_wb = fc->writeback_cache && S_ISREG(inode->i_mode);
+       u32 cache_mask;
        loff_t oldsize;
        struct timespec64 old_mtime;
 
         * may update i_size.  In these cases trust the cached value in the
         * inode.
         */
-       if (is_wb) {
+       cache_mask = fuse_get_cache_mask(inode);
+       if (cache_mask & STATX_SIZE)
                attr->size = i_size_read(inode);
+
+       if (cache_mask & STATX_MTIME) {
                attr->mtime = inode->i_mtime.tv_sec;
                attr->mtimensec = inode->i_mtime.tv_nsec;
+       }
+       if (cache_mask & STATX_CTIME) {
                attr->ctime = inode->i_ctime.tv_sec;
                attr->ctimensec = inode->i_ctime.tv_nsec;
        }
        }
 
        old_mtime = inode->i_mtime;
-       fuse_change_attributes_common(inode, attr, attr_valid);
+       fuse_change_attributes_common(inode, attr, attr_valid, cache_mask);
 
        oldsize = inode->i_size;
        /*
         * extend local i_size without keeping userspace server in sync. So,
         * attr->size coming from server can be stale. We cannot trust it.
         */
-       if (!is_wb)
+       if (!(cache_mask & STATX_SIZE))
                i_size_write(inode, attr->size);
        spin_unlock(&fi->lock);
 
-       if (!is_wb && S_ISREG(inode->i_mode)) {
+       if (!cache_mask && S_ISREG(inode->i_mode)) {
                bool inval = false;
 
                if (oldsize != attr->size) {