Use the new completion flush code to implement the dquot flush lock.
Removes one of the final users of semaphores in the XFS code base.
SGI-PV: 981498
SGI-Modid: xfs-linux-melb:xfs-kern:31822a
Signed-off-by: David Chinner <david@fromorbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
        if (brandnewdquot) {
                dqp->dq_flnext = dqp->dq_flprev = dqp;
                mutex_init(&dqp->q_qlock);
-               initnsema(&dqp->q_flock, 1, "fdq");
                sv_init(&dqp->q_pinwait, SV_DEFAULT, "pdq");
 
+               /*
+                * Because we want to use a counting completion, complete
+                * the flush completion once to allow a single access to
+                * the flush completion without blocking.
+                */
+               init_completion(&dqp->q_flush);
+               complete(&dqp->q_flush);
+
 #ifdef XFS_DQUOT_TRACE
                dqp->q_trace = ktrace_alloc(DQUOT_TRACE_SIZE, KM_SLEEP);
                xfs_dqtrace_entry(dqp, "DQINIT");
        ASSERT(! XFS_DQ_IS_ON_FREELIST(dqp));
 
        mutex_destroy(&dqp->q_qlock);
-       freesema(&dqp->q_flock);
        sv_destroy(&dqp->q_pinwait);
 
 #ifdef XFS_DQUOT_TRACE
        int                     error;
 
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
+       ASSERT(!completion_done(&dqp->q_flush));
        xfs_dqtrace_entry(dqp, "DQFLUSH");
 
        /*
        xfs_dqfunlock(dqp);
 }
 
-
-int
-xfs_qm_dqflock_nowait(
-       xfs_dquot_t *dqp)
-{
-       int locked;
-
-       locked = cpsema(&((dqp)->q_flock));
-
-       /* XXX ifdef these out */
-       if (locked)
-               (dqp)->dq_flags |= XFS_DQ_FLOCKED;
-       return (locked);
-}
-
-
 int
 xfs_qm_dqlock_nowait(
        xfs_dquot_t *dqp)
 {
-       return (mutex_trylock(&((dqp)->q_qlock)));
+       return mutex_trylock(&dqp->q_qlock);
 }
 
 void
 xfs_dqlock(
        xfs_dquot_t *dqp)
 {
-       mutex_lock(&(dqp->q_qlock));
+       mutex_lock(&dqp->q_qlock);
 }
 
 void
         * if we're turning off quotas. Basically, we need this flush
         * lock, and are willing to block on it.
         */
-       if (! xfs_qm_dqflock_nowait(dqp)) {
+       if (!xfs_dqflock_nowait(dqp)) {
                /*
                 * Block on the flush lock after nudging dquot buffer,
                 * if it is incore.
 
        xfs_qcnt_t       q_res_icount;  /* total inos allocd+reserved */
        xfs_qcnt_t       q_res_rtbcount;/* total realtime blks used+reserved */
        mutex_t          q_qlock;       /* quota lock */
-       sema_t           q_flock;       /* flush lock */
+       struct completion q_flush;      /* flush completion queue */
        uint             q_pincount;    /* pin count for this dquot */
        sv_t             q_pinwait;     /* sync var for pinning */
 #ifdef XFS_DQUOT_TRACE
 
 
 /*
- * The following three routines simply manage the q_flock
- * semaphore embedded in the dquot.  This semaphore synchronizes
- * processes attempting to flush the in-core dquot back to disk.
+ * Manage the q_flush completion queue embedded in the dquot.  This completion
+ * queue synchronizes processes attempting to flush the in-core dquot back to
+ * disk.
  */
-#define xfs_dqflock(dqp)        { psema(&((dqp)->q_flock), PINOD | PRECALC);\
-                                  (dqp)->dq_flags |= XFS_DQ_FLOCKED; }
-#define xfs_dqfunlock(dqp)      { ASSERT(issemalocked(&((dqp)->q_flock))); \
-                                  vsema(&((dqp)->q_flock)); \
-                                  (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); }
+static inline void xfs_dqflock(xfs_dquot_t *dqp)
+{
+       wait_for_completion(&dqp->q_flush);
+}
+
+static inline int xfs_dqflock_nowait(xfs_dquot_t *dqp)
+{
+       return try_wait_for_completion(&dqp->q_flush);
+}
+
+static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
+{
+       complete(&dqp->q_flush);
+}
 
-#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock)))
 #define XFS_DQ_IS_ON_FREELIST(dqp)  ((dqp)->dq_flnext != (dqp))
 #define XFS_DQ_IS_DIRTY(dqp)   ((dqp)->dq_flags & XFS_DQ_DIRTY)
 #define XFS_QM_ISUDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_USER)
 extern int             xfs_qm_dqpurge(xfs_dquot_t *);
 extern void            xfs_qm_dqunpin_wait(xfs_dquot_t *);
 extern int             xfs_qm_dqlock_nowait(xfs_dquot_t *);
-extern int             xfs_qm_dqflock_nowait(xfs_dquot_t *);
 extern void            xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void            xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
 
        dqp = logitem->qli_dquot;
 
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       ASSERT(XFS_DQ_IS_FLUSH_LOCKED(dqp));
+       ASSERT(!completion_done(&dqp->q_flush));
 
        /*
         * Since we were able to lock the dquot's flush lock and
         * inode flush completed and the inode was taken off the AIL.
         * So, just get out.
         */
-       if (!issemalocked(&(dqp->q_flock))  ||
+       if (completion_done(&dqp->q_flush)  ||
            ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {
                qip->qli_pushbuf_flag = 0;
                xfs_dqunlock(dqp);
        if (bp != NULL) {
                if (XFS_BUF_ISDELAYWRITE(bp)) {
                        dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
-                                 issemalocked(&(dqp->q_flock)));
+                                 !completion_done(&dqp->q_flush));
                        qip->qli_pushbuf_flag = 0;
                        xfs_dqunlock(dqp);
 
                return (XFS_ITEM_LOCKED);
 
        retval = XFS_ITEM_SUCCESS;
-       if (! xfs_qm_dqflock_nowait(dqp)) {
+       if (!xfs_dqflock_nowait(dqp)) {
                /*
                 * The dquot is already being flushed.  It may have been
                 * flushed delayed write, however, and we don't want to
 
                xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY");
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        /*
                         * If we can't grab the flush lock then check
                         * to see if the dquot has been flushed delayed
 
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        if (nowait) {
                                xfs_dqunlock(dqp);
                                continue;
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        dqp = dqp->dq_flnext;
                        continue;
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        continue;
                }