fs: record I_DIRTY_TIME even if inode already has I_DIRTY_INODE
[platform/kernel/linux-rpi.git] / fs / fs-writeback.c
index 9761470..2a27f02 100644 (file)
@@ -1745,9 +1745,14 @@ static int writeback_single_inode(struct inode *inode,
         */
        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);
@@ -2401,6 +2406,20 @@ void __mark_inode_dirty(struct inode *inode, int 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
                 * inode.  This is only needed when the inode itself is being
@@ -2409,7 +2428,8 @@ void __mark_inode_dirty(struct inode *inode, int flags)
                 */
                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. */
@@ -2430,21 +2450,15 @@ void __mark_inode_dirty(struct inode *inode, int flags)
         */
        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;
 
                /*
@@ -2517,7 +2531,6 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 out_unlock:
        if (wb)
                spin_unlock(&wb->list_lock);
-out_unlock_inode:
        spin_unlock(&inode->i_lock);
 }
 EXPORT_SYMBOL(__mark_inode_dirty);