*/
        if (!(inode->i_state & I_DIRTY_ALL))
                inode_cgwb_move_to_attached(inode, wb);
-       else if (!(inode->i_state & I_SYNC_QUEUED) &&
-                (inode->i_state & I_DIRTY))
-               redirty_tail_locked(inode, wb);
+       else if (!(inode->i_state & I_SYNC_QUEUED)) {
+               if ((inode->i_state & I_DIRTY))
+                       redirty_tail_locked(inode, wb);
+               else if (inode->i_state & I_DIRTY_TIME) {
+                       inode->dirtied_when = jiffies;
+                       inode_io_list_move_locked(inode, wb, &wb->b_dirty_time);
+               }
+       }
 
        spin_unlock(&wb->list_lock);
        inode_sync_complete(inode);
        trace_writeback_mark_inode_dirty(inode, flags);
 
        if (flags & I_DIRTY_INODE) {
+               /*
+                * Inode timestamp update will piggback on this dirtying.
+                * We tell ->dirty_inode callback that timestamps need to
+                * be updated by setting I_DIRTY_TIME in flags.
+                */
+               if (inode->i_state & I_DIRTY_TIME) {
+                       spin_lock(&inode->i_lock);
+                       if (inode->i_state & I_DIRTY_TIME) {
+                               inode->i_state &= ~I_DIRTY_TIME;
+                               flags |= I_DIRTY_TIME;
+                       }
+                       spin_unlock(&inode->i_lock);
+               }
+
                /*
                 * Notify the filesystem about the inode being dirtied, so that
                 * (if needed) it can update on-disk fields and journal the
                 */
                trace_writeback_dirty_inode_start(inode, flags);
                if (sb->s_op->dirty_inode)
-                       sb->s_op->dirty_inode(inode, flags & I_DIRTY_INODE);
+                       sb->s_op->dirty_inode(inode,
+                               flags & (I_DIRTY_INODE | I_DIRTY_TIME));
                trace_writeback_dirty_inode(inode, flags);
 
                /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */
         */
        smp_mb();
 
-       if (((inode->i_state & flags) == flags) ||
-           (dirtytime && (inode->i_state & I_DIRTY_INODE)))
+       if ((inode->i_state & flags) == flags)
                return;
 
        spin_lock(&inode->i_lock);
-       if (dirtytime && (inode->i_state & I_DIRTY_INODE))
-               goto out_unlock_inode;
        if ((inode->i_state & flags) != flags) {
                const int was_dirty = inode->i_state & I_DIRTY;
 
                inode_attach_wb(inode, NULL);
 
-               /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */
-               if (flags & I_DIRTY_INODE)
-                       inode->i_state &= ~I_DIRTY_TIME;
                inode->i_state |= flags;
 
                /*
 out_unlock:
        if (wb)
                spin_unlock(&wb->list_lock);
-out_unlock_inode:
        spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL(__mark_inode_dirty);
 
 static void
 xfs_fs_dirty_inode(
        struct inode                    *inode,
-       int                             flag)
+       int                             flags)
 {
        struct xfs_inode                *ip = XFS_I(inode);
        struct xfs_mount                *mp = ip->i_mount;
 
        if (!(inode->i_sb->s_flags & SB_LAZYTIME))
                return;
-       if (flag != I_DIRTY_SYNC || !(inode->i_state & I_DIRTY_TIME))
+
+       /*
+        * Only do the timestamp update if the inode is dirty (I_DIRTY_SYNC)
+        * and has dirty timestamp (I_DIRTY_TIME). I_DIRTY_TIME can be passed
+        * in flags possibly together with I_DIRTY_SYNC.
+        */
+       if ((flags & ~I_DIRTY_TIME) != I_DIRTY_SYNC || !(flags & I_DIRTY_TIME))
                return;
 
        if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp))
 
  *                     don't have to write inode on fdatasync() when only
  *                     e.g. the timestamps have changed.
  * I_DIRTY_PAGES       Inode has dirty pages.  Inode itself may be clean.
- * I_DIRTY_TIME                The inode itself only has dirty timestamps, and the
+ * I_DIRTY_TIME                The inode itself has dirty timestamps, and the
  *                     lazytime mount option is enabled.  We keep track of this
  *                     separately from I_DIRTY_SYNC in order to implement
  *                     lazytime.  This gets cleared if I_DIRTY_INODE
- *                     (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set.  I.e.
- *                     either I_DIRTY_TIME *or* I_DIRTY_INODE can be set in
- *                     i_state, but not both.  I_DIRTY_PAGES may still be set.
+ *                     (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. But
+ *                     I_DIRTY_TIME can still be set if I_DIRTY_SYNC is already
+ *                     in place because writeback might already be in progress
+ *                     and we don't want to lose the time update
  * I_NEW               Serves as both a mutex and completion notification.
  *                     New inodes set I_NEW.  If two processes both create
  *                     the same inode, one of them will release its inode and