Merge branch 'for-3.5-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj...
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_dquot.c
index 1155208fa830f2953ca0e1019f59b1b9379af7e2..bf27fcca4843480376b097cbab1bc2e4f6c5e261 100644 (file)
@@ -19,7 +19,6 @@
 #include "xfs_fs.h"
 #include "xfs_bit.h"
 #include "xfs_log.h"
-#include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
@@ -857,7 +856,7 @@ xfs_qm_dqflush_done(
                /* xfs_trans_ail_delete() drops the AIL lock. */
                spin_lock(&ailp->xa_lock);
                if (lip->li_lsn == qip->qli_flush_lsn)
-                       xfs_trans_ail_delete(ailp, lip);
+                       xfs_trans_ail_delete(ailp, lip, SHUTDOWN_CORRUPT_INCORE);
                else
                        spin_unlock(&ailp->xa_lock);
        }
@@ -878,8 +877,8 @@ xfs_qm_dqflush_done(
  */
 int
 xfs_qm_dqflush(
-       xfs_dquot_t             *dqp,
-       uint                    flags)
+       struct xfs_dquot        *dqp,
+       struct xfs_buf          **bpp)
 {
        struct xfs_mount        *mp = dqp->q_mount;
        struct xfs_buf          *bp;
@@ -891,25 +890,30 @@ xfs_qm_dqflush(
 
        trace_xfs_dqflush(dqp);
 
-       /*
-        * If not dirty, or it's pinned and we are not supposed to block, nada.
-        */
-       if (!XFS_DQ_IS_DIRTY(dqp) ||
-           ((flags & SYNC_TRYLOCK) && atomic_read(&dqp->q_pincount) > 0)) {
-               xfs_dqfunlock(dqp);
-               return 0;
-       }
+       *bpp = NULL;
+
        xfs_qm_dqunpin_wait(dqp);
 
        /*
         * This may have been unpinned because the filesystem is shutting
         * down forcibly. If that's the case we must not write this dquot
-        * to disk, because the log record didn't make it to disk!
+        * to disk, because the log record didn't make it to disk.
+        *
+        * We also have to remove the log item from the AIL in this case,
+        * as we wait for an emptry AIL as part of the unmount process.
         */
        if (XFS_FORCED_SHUTDOWN(mp)) {
+               struct xfs_log_item     *lip = &dqp->q_logitem.qli_item;
                dqp->dq_flags &= ~XFS_DQ_DIRTY;
-               xfs_dqfunlock(dqp);
-               return XFS_ERROR(EIO);
+
+               spin_lock(&mp->m_ail->xa_lock);
+               if (lip->li_flags & XFS_LI_IN_AIL)
+                       xfs_trans_ail_delete(mp->m_ail, lip,
+                                            SHUTDOWN_CORRUPT_INCORE);
+               else
+                       spin_unlock(&mp->m_ail->xa_lock);
+               error = XFS_ERROR(EIO);
+               goto out_unlock;
        }
 
        /*
@@ -917,11 +921,8 @@ xfs_qm_dqflush(
         */
        error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
                                   mp->m_quotainfo->qi_dqchunklen, 0, &bp);
-       if (error) {
-               ASSERT(error != ENOENT);
-               xfs_dqfunlock(dqp);
-               return error;
-       }
+       if (error)
+               goto out_unlock;
 
        /*
         * Calculate the location of the dquot inside the buffer.
@@ -967,20 +968,13 @@ xfs_qm_dqflush(
                xfs_log_force(mp, 0);
        }
 
-       if (flags & SYNC_WAIT)
-               error = xfs_bwrite(bp);
-       else
-               xfs_buf_delwri_queue(bp);
-
-       xfs_buf_relse(bp);
-
        trace_xfs_dqflush_done(dqp);
+       *bpp = bp;
+       return 0;
 
-       /*
-        * dqp is still locked, but caller is free to unlock it now.
-        */
-       return error;
-
+out_unlock:
+       xfs_dqfunlock(dqp);
+       return XFS_ERROR(EIO);
 }
 
 /*
@@ -1011,39 +1005,6 @@ xfs_dqlock2(
        }
 }
 
-/*
- * Give the buffer a little push if it is incore and
- * wait on the flush lock.
- */
-void
-xfs_dqflock_pushbuf_wait(
-       xfs_dquot_t     *dqp)
-{
-       xfs_mount_t     *mp = dqp->q_mount;
-       xfs_buf_t       *bp;
-
-       /*
-        * Check to see if the dquot has been flushed delayed
-        * write.  If so, grab its buffer and send it
-        * out immediately.  We'll be able to acquire
-        * the flush lock when the I/O completes.
-        */
-       bp = xfs_incore(mp->m_ddev_targp, dqp->q_blkno,
-                       mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK);
-       if (!bp)
-               goto out_lock;
-
-       if (XFS_BUF_ISDELAYWRITE(bp)) {
-               if (xfs_buf_ispinned(bp))
-                       xfs_log_force(mp, 0);
-               xfs_buf_delwri_promote(bp);
-               wake_up_process(bp->b_target->bt_task);
-       }
-       xfs_buf_relse(bp);
-out_lock:
-       xfs_dqflock(dqp);
-}
-
 int __init
 xfs_qm_init(void)
 {