]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Jan 2012 21:05:29 +0000 (13:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 8 Jan 2012 21:05:29 +0000 (13:05 -0800)
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (22 commits)
  xfs: mark the xfssyncd workqueue as non-reentrant
  xfs: simplify xfs_qm_detach_gdquots
  xfs: fix acl count validation in xfs_acl_from_disk()
  xfs: remove unused XBT_FORCE_SLEEP bit
  xfs: remove XFS_QMOPT_DQSUSER
  xfs: kill xfs_qm_idtodq
  xfs: merge xfs_qm_dqinit_core into the only caller
  xfs: add a xfs_dqhold helper
  xfs: simplify xfs_qm_dqattach_grouphint
  xfs: nest qm_dqfrlist_lock inside the dquot qlock
  xfs: flatten the dquot lock ordering
  xfs: implement lazy removal for the dquot freelist
  xfs: remove XFS_DQ_INACTIVE
  xfs: cleanup xfs_qm_dqlookup
  xfs: cleanup dquot locking helpers
  xfs: remove the sync_mode argument to xfs_qm_dqflush_all
  xfs: remove xfs_qm_sync
  xfs: make sure to really flush all dquots in xfs_qm_quotacheck
  xfs: untangle SYNC_WAIT and SYNC_TRYLOCK meanings for xfs_qm_dqflush
  xfs: remove the lid_size field in struct log_item_desc
  ...

Fix up trivial conflict in fs/xfs/xfs_sync.c

19 files changed:
fs/xfs/xfs_acl.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_dquot.c
fs/xfs/xfs_dquot.h
fs/xfs/xfs_dquot_item.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_mount.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.h
fs/xfs/xfs_quota.h
fs/xfs/xfs_super.c
fs/xfs/xfs_sync.c
fs/xfs/xfs_trace.h
fs/xfs/xfs_trans.c
fs/xfs/xfs_trans.h

index 76e4266d2e7e4a8fc3bfc609016e4de467b7e5cf..ac702a6eab9b05f6e1e4b9e3dde769a06262f84b 100644 (file)
@@ -39,7 +39,7 @@ xfs_acl_from_disk(struct xfs_acl *aclp)
        struct posix_acl_entry *acl_e;
        struct posix_acl *acl;
        struct xfs_acl_entry *ace;
-       int count, i;
+       unsigned int count, i;
 
        count = be32_to_cpu(aclp->acl_cnt);
        if (count > XFS_ACL_MAX_ENTRIES)
index cf0ac056815f19bf3051fdb72194972477cd4cd1..2277bcae395f32dd11d5354cdab87c56d9965de7 100644 (file)
@@ -1701,12 +1701,8 @@ xfsbufd(
                struct list_head tmp;
                struct blk_plug plug;
 
-               if (unlikely(freezing(current))) {
-                       set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
+               if (unlikely(freezing(current)))
                        refrigerator();
-               } else {
-                       clear_bit(XBT_FORCE_SLEEP, &target->bt_flags);
-               }
 
                /* sleep for a long time if there is nothing to do. */
                if (list_empty(&target->bt_delwri_queue))
index 5bab046e859fc8c0aaa6a237ccd35ce754e8397d..df7ffb0affe73f795ab4eee512cf7035e2c0b6f7 100644 (file)
@@ -90,8 +90,7 @@ typedef unsigned int xfs_buf_flags_t;
        { _XBF_DELWRI_Q,        "DELWRI_Q" }
 
 typedef enum {
-       XBT_FORCE_SLEEP = 0,
-       XBT_FORCE_FLUSH = 1,
+       XBT_FORCE_FLUSH = 0,
 } xfs_buftarg_flags_t;
 
 typedef struct xfs_buftarg {
index 25d7280e9f6bb9de30822fed909cda099d7fbee1..b4ff40b5f918f2462ed1482d1b8f3446bc0a18d0 100644 (file)
 #include "xfs_qm.h"
 #include "xfs_trace.h"
 
-
 /*
-   LOCK ORDER
-
-   inode lock              (ilock)
-   dquot hash-chain lock    (hashlock)
  xqm dquot freelist lock  (freelistlock
  mount's dquot list lock  (mplistlock)
-   user dquot lock - lock ordering among dquots is based on the uid or gid
-   group dquot lock - similar to udquots. Between the two dquots, the udquot
-                     has to be locked first.
-   pin lock - the dquot lock must be held to take this lock.
  flush lock - ditto.
-*/
+ * Lock order:
+ *
+ * ip->i_lock
+ *   qh->qh_lock
*     qi->qi_dqlist_lock
*       dquot->q_qlock (xfs_dqlock() and friends)
+ *         dquot->q_flush (xfs_dqflock() and friends)
+ *         xfs_Gqm->qm_dqfrlist_lock
+ *
+ * If two dquots need to be locked the order is user before group/project,
* otherwise by the lowest id first, see xfs_dqlock2.
+ */
 
 #ifdef DEBUG
 xfs_buftarg_t *xfs_dqerror_target;
@@ -154,24 +153,6 @@ xfs_qm_dqdestroy(
        atomic_dec(&xfs_Gqm->qm_totaldquots);
 }
 
-/*
- * This is what a 'fresh' dquot inside a dquot chunk looks like on disk.
- */
-STATIC void
-xfs_qm_dqinit_core(
-       xfs_dqid_t      id,
-       uint            type,
-       xfs_dqblk_t     *d)
-{
-       /*
-        * Caller has zero'd the entire dquot 'chunk' already.
-        */
-       d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
-       d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
-       d->dd_diskdq.d_id = cpu_to_be32(id);
-       d->dd_diskdq.d_flags = type;
-}
-
 /*
  * If default limits are in force, push them into the dquot now.
  * We overwrite the dquot limits only if they are zero and this
@@ -328,8 +309,13 @@ xfs_qm_init_dquot_blk(
        curid = id - (id % q->qi_dqperchunk);
        ASSERT(curid >= 0);
        memset(d, 0, BBTOB(q->qi_dqchunklen));
-       for (i = 0; i < q->qi_dqperchunk; i++, d++, curid++)
-               xfs_qm_dqinit_core(curid, type, d);
+       for (i = 0; i < q->qi_dqperchunk; i++, d++, curid++) {
+               d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC);
+               d->dd_diskdq.d_version = XFS_DQUOT_VERSION;
+               d->dd_diskdq.d_id = cpu_to_be32(curid);
+               d->dd_diskdq.d_flags = type;
+       }
+
        xfs_trans_dquot_buf(tp, bp,
                            (type & XFS_DQ_USER ? XFS_BLF_UDQUOT_BUF :
                            ((type & XFS_DQ_PROJ) ? XFS_BLF_PDQUOT_BUF :
@@ -564,36 +550,62 @@ xfs_qm_dqtobp(
  * Read in the ondisk dquot using dqtobp() then copy it to an incore version,
  * and release the buffer immediately.
  *
+ * If XFS_QMOPT_DQALLOC is set, allocate a dquot on disk if it needed.
  */
-/* ARGSUSED */
-STATIC int
+int
 xfs_qm_dqread(
-       xfs_trans_t     **tpp,
-       xfs_dqid_t      id,
-       xfs_dquot_t     *dqp,   /* dquot to get filled in */
-       uint            flags)
+       struct xfs_mount        *mp,
+       xfs_dqid_t              id,
+       uint                    type,
+       uint                    flags,
+       struct xfs_dquot        **O_dqpp)
 {
-       xfs_disk_dquot_t *ddqp;
-       xfs_buf_t        *bp;
-       int              error;
-       xfs_trans_t      *tp;
+       struct xfs_dquot        *dqp;
+       struct xfs_disk_dquot   *ddqp;
+       struct xfs_buf          *bp;
+       struct xfs_trans        *tp = NULL;
+       int                     error;
+       int                     cancelflags = 0;
 
-       ASSERT(tpp);
+       dqp = xfs_qm_dqinit(mp, id, type);
 
        trace_xfs_dqread(dqp);
 
+       if (flags & XFS_QMOPT_DQALLOC) {
+               tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC);
+               error = xfs_trans_reserve(tp, XFS_QM_DQALLOC_SPACE_RES(mp),
+                               XFS_WRITE_LOG_RES(mp) +
+                               /*
+                                * Round the chunklen up to the next multiple
+                                * of 128 (buf log item chunk size)).
+                                */
+                               BBTOB(mp->m_quotainfo->qi_dqchunklen) - 1 + 128,
+                               0,
+                               XFS_TRANS_PERM_LOG_RES,
+                               XFS_WRITE_LOG_COUNT);
+               if (error)
+                       goto error1;
+               cancelflags = XFS_TRANS_RELEASE_LOG_RES;
+       }
+
        /*
         * get a pointer to the on-disk dquot and the buffer containing it
         * dqp already knows its own type (GROUP/USER).
         */
-       if ((error = xfs_qm_dqtobp(tpp, dqp, &ddqp, &bp, flags))) {
-               return (error);
+       error = xfs_qm_dqtobp(&tp, dqp, &ddqp, &bp, flags);
+       if (error) {
+               /*
+                * This can happen if quotas got turned off (ESRCH),
+                * or if the dquot didn't exist on disk and we ask to
+                * allocate (ENOENT).
+                */
+               trace_xfs_dqread_fail(dqp);
+               cancelflags |= XFS_TRANS_ABORT;
+               goto error1;
        }
-       tp = *tpp;
 
        /* copy everything from disk dquot to the incore dquot */
        memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
-       ASSERT(be32_to_cpu(dqp->q_core.d_id) == id);
        xfs_qm_dquot_logitem_init(dqp);
 
        /*
@@ -622,77 +634,22 @@ xfs_qm_dqread(
        ASSERT(xfs_buf_islocked(bp));
        xfs_trans_brelse(tp, bp);
 
-       return (error);
-}
-
-
-/*
- * allocate an incore dquot from the kernel heap,
- * and fill its core with quota information kept on disk.
- * If XFS_QMOPT_DQALLOC is set, it'll allocate a dquot on disk
- * if it wasn't already allocated.
- */
-STATIC int
-xfs_qm_idtodq(
-       xfs_mount_t     *mp,
-       xfs_dqid_t      id,      /* gid or uid, depending on type */
-       uint            type,    /* UDQUOT or GDQUOT */
-       uint            flags,   /* DQALLOC, DQREPAIR */
-       xfs_dquot_t     **O_dqpp)/* OUT : incore dquot, not locked */
-{
-       xfs_dquot_t     *dqp;
-       int             error;
-       xfs_trans_t     *tp;
-       int             cancelflags=0;
-
-       dqp = xfs_qm_dqinit(mp, id, type);
-       tp = NULL;
-       if (flags & XFS_QMOPT_DQALLOC) {
-               tp = xfs_trans_alloc(mp, XFS_TRANS_QM_DQALLOC);
-               error = xfs_trans_reserve(tp, XFS_QM_DQALLOC_SPACE_RES(mp),
-                               XFS_WRITE_LOG_RES(mp) +
-                               BBTOB(mp->m_quotainfo->qi_dqchunklen) - 1 +
-                               128,
-                               0,
-                               XFS_TRANS_PERM_LOG_RES,
-                               XFS_WRITE_LOG_COUNT);
-               if (error) {
-                       cancelflags = 0;
-                       goto error0;
-               }
-               cancelflags = XFS_TRANS_RELEASE_LOG_RES;
-       }
-
-       /*
-        * Read it from disk; xfs_dqread() takes care of
-        * all the necessary initialization of dquot's fields (locks, etc)
-        */
-       if ((error = xfs_qm_dqread(&tp, id, dqp, flags))) {
-               /*
-                * This can happen if quotas got turned off (ESRCH),
-                * or if the dquot didn't exist on disk and we ask to
-                * allocate (ENOENT).
-                */
-               trace_xfs_dqread_fail(dqp);
-               cancelflags |= XFS_TRANS_ABORT;
-               goto error0;
-       }
        if (tp) {
-               if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES)))
-                       goto error1;
+               error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
+               if (error)
+                       goto error0;
        }
 
        *O_dqpp = dqp;
-       return (0);
+       return error;
 
- error0:
-       ASSERT(error);
+error1:
        if (tp)
                xfs_trans_cancel(tp, cancelflags);
- error1:
+error0:
        xfs_qm_dqdestroy(dqp);
        *O_dqpp = NULL;
-       return (error);
+       return error;
 }
 
 /*
@@ -710,12 +667,9 @@ xfs_qm_dqlookup(
        xfs_dquot_t             **O_dqpp)
 {
        xfs_dquot_t             *dqp;
-       uint                    flist_locked;
 
        ASSERT(mutex_is_locked(&qh->qh_lock));
 
-       flist_locked = B_FALSE;
-
        /*
         * Traverse the hashchain looking for a match
         */
@@ -725,70 +679,31 @@ xfs_qm_dqlookup(
                 * dqlock to look at the id field of the dquot, since the
                 * id can't be modified without the hashlock anyway.
                 */
-               if (be32_to_cpu(dqp->q_core.d_id) == id && dqp->q_mount == mp) {
-                       trace_xfs_dqlookup_found(dqp);
+               if (be32_to_cpu(dqp->q_core.d_id) != id || dqp->q_mount != mp)
+                       continue;
 
-                       /*
-                        * All in core dquots must be on the dqlist of mp
-                        */
-                       ASSERT(!list_empty(&dqp->q_mplist));
-
-                       xfs_dqlock(dqp);
-                       if (dqp->q_nrefs == 0) {
-                               ASSERT(!list_empty(&dqp->q_freelist));
-                               if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
-                                       trace_xfs_dqlookup_want(dqp);
-
-                                       /*
-                                        * We may have raced with dqreclaim_one()
-                                        * (and lost). So, flag that we don't
-                                        * want the dquot to be reclaimed.
-                                        */
-                                       dqp->dq_flags |= XFS_DQ_WANT;
-                                       xfs_dqunlock(dqp);
-                                       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-                                       xfs_dqlock(dqp);
-                                       dqp->dq_flags &= ~(XFS_DQ_WANT);
-                               }
-                               flist_locked = B_TRUE;
-                       }
+               trace_xfs_dqlookup_found(dqp);
 
-                       /*
-                        * id couldn't have changed; we had the hashlock all
-                        * along
-                        */
-                       ASSERT(be32_to_cpu(dqp->q_core.d_id) == id);
-
-                       if (flist_locked) {
-                               if (dqp->q_nrefs != 0) {
-                                       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-                                       flist_locked = B_FALSE;
-                               } else {
-                                       /* take it off the freelist */
-                                       trace_xfs_dqlookup_freelist(dqp);
-                                       list_del_init(&dqp->q_freelist);
-                                       xfs_Gqm->qm_dqfrlist_cnt--;
-                               }
-                       }
+               xfs_dqlock(dqp);
+               if (dqp->dq_flags & XFS_DQ_FREEING) {
+                       *O_dqpp = NULL;
+                       xfs_dqunlock(dqp);
+                       return -1;
+               }
 
-                       XFS_DQHOLD(dqp);
+               dqp->q_nrefs++;
 
-                       if (flist_locked)
-                               mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-                       /*
-                        * move the dquot to the front of the hashchain
-                        */
-                       ASSERT(mutex_is_locked(&qh->qh_lock));
-                       list_move(&dqp->q_hashlist, &qh->qh_list);
-                       trace_xfs_dqlookup_done(dqp);
-                       *O_dqpp = dqp;
-                       return 0;
-               }
+               /*
+                * move the dquot to the front of the hashchain
+                */
+               list_move(&dqp->q_hashlist, &qh->qh_list);
+               trace_xfs_dqlookup_done(dqp);
+               *O_dqpp = dqp;
+               return 0;
        }
 
        *O_dqpp = NULL;
-       ASSERT(mutex_is_locked(&qh->qh_lock));
-       return (1);
+       return 1;
 }
 
 /*
@@ -829,11 +744,7 @@ xfs_qm_dqget(
                        return (EIO);
                }
        }
-#endif
-
- again:
 
-#ifdef DEBUG
        ASSERT(type == XFS_DQ_USER ||
               type == XFS_DQ_PROJ ||
               type == XFS_DQ_GROUP);
@@ -845,13 +756,21 @@ xfs_qm_dqget(
                        ASSERT(ip->i_gdquot == NULL);
        }
 #endif
+
+restart:
        mutex_lock(&h->qh_lock);
 
        /*
         * Look in the cache (hashtable).
         * The chain is kept locked during lookup.
         */
-       if (xfs_qm_dqlookup(mp, id, h, O_dqpp) == 0) {
+       switch (xfs_qm_dqlookup(mp, id, h, O_dqpp)) {
+       case -1:
+               XQM_STATS_INC(xqmstats.xs_qm_dquot_dups);
+               mutex_unlock(&h->qh_lock);
+               delay(1);
+               goto restart;
+       case 0:
                XQM_STATS_INC(xqmstats.xs_qm_dqcachehits);
                /*
                 * The dquot was found, moved to the front of the chain,
@@ -862,9 +781,11 @@ xfs_qm_dqget(
                ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp));
                mutex_unlock(&h->qh_lock);
                trace_xfs_dqget_hit(*O_dqpp);
-               return (0);     /* success */
+               return 0;       /* success */
+       default:
+               XQM_STATS_INC(xqmstats.xs_qm_dqcachemisses);
+               break;
        }
-       XQM_STATS_INC(xqmstats.xs_qm_dqcachemisses);
 
        /*
         * Dquot cache miss. We don't want to keep the inode lock across
@@ -882,41 +803,18 @@ xfs_qm_dqget(
        version = h->qh_version;
        mutex_unlock(&h->qh_lock);
 
-       /*
-        * Allocate the dquot on the kernel heap, and read the ondisk
-        * portion off the disk. Also, do all the necessary initialization
-        * This can return ENOENT if dquot didn't exist on disk and we didn't
-        * ask it to allocate; ESRCH if quotas got turned off suddenly.
-        */
-       if ((error = xfs_qm_idtodq(mp, id, type,
-                                 flags & (XFS_QMOPT_DQALLOC|XFS_QMOPT_DQREPAIR|
-                                          XFS_QMOPT_DOWARN),
-                                 &dqp))) {
-               if (ip)
-                       xfs_ilock(ip, XFS_ILOCK_EXCL);
-               return (error);
-       }
+       error = xfs_qm_dqread(mp, id, type, flags, &dqp);
 
-       /*
-        * See if this is mount code calling to look at the overall quota limits
-        * which are stored in the id == 0 user or group's dquot.
-        * Since we may not have done a quotacheck by this point, just return
-        * the dquot without attaching it to any hashtables, lists, etc, or even
-        * taking a reference.
-        * The caller must dqdestroy this once done.
-        */
-       if (flags & XFS_QMOPT_DQSUSER) {
-               ASSERT(id == 0);
-               ASSERT(! ip);
-               goto dqret;
-       }
+       if (ip)
+               xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+       if (error)
+               return error;
 
        /*
         * Dquot lock comes after hashlock in the lock ordering
         */
        if (ip) {
-               xfs_ilock(ip, XFS_ILOCK_EXCL);
-
                /*
                 * A dquot could be attached to this inode by now, since
                 * we had dropped the ilock.
@@ -961,16 +859,21 @@ xfs_qm_dqget(
                 * lock order between the two dquots here since dqp isn't
                 * on any findable lists yet.
                 */
-               if (xfs_qm_dqlookup(mp, id, h, &tmpdqp) == 0) {
+               switch (xfs_qm_dqlookup(mp, id, h, &tmpdqp)) {
+               case 0:
+               case -1:
                        /*
-                        * Duplicate found. Just throw away the new dquot
-                        * and start over.
+                        * Duplicate found, either in cache or on its way out.
+                        * Just throw away the new dquot and start over.
                         */
-                       xfs_qm_dqput(tmpdqp);
+                       if (tmpdqp)
+                               xfs_qm_dqput(tmpdqp);
                        mutex_unlock(&h->qh_lock);
                        xfs_qm_dqdestroy(dqp);
                        XQM_STATS_INC(xqmstats.xs_qm_dquot_dups);
-                       goto again;
+                       goto restart;
+               default:
+                       break;
                }
        }
 
@@ -1015,67 +918,49 @@ xfs_qm_dqget(
  */
 void
 xfs_qm_dqput(
-       xfs_dquot_t     *dqp)
+       struct xfs_dquot        *dqp)
 {
-       xfs_dquot_t     *gdqp;
+       struct xfs_dquot        *gdqp;
 
        ASSERT(dqp->q_nrefs > 0);
        ASSERT(XFS_DQ_IS_LOCKED(dqp));
 
        trace_xfs_dqput(dqp);
 
-       if (dqp->q_nrefs != 1) {
-               dqp->q_nrefs--;
+recurse:
+       if (--dqp->q_nrefs > 0) {
                xfs_dqunlock(dqp);
                return;
        }
 
+       trace_xfs_dqput_free(dqp);
+
+       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
+       if (list_empty(&dqp->q_freelist)) {
+               list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
+               xfs_Gqm->qm_dqfrlist_cnt++;
+       }
+       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
+
        /*
-        * drop the dqlock and acquire the freelist and dqlock
-        * in the right order; but try to get it out-of-order first
+        * If we just added a udquot to the freelist, then we want to release
+        * the gdquot reference that it (probably) has. Otherwise it'll keep
+        * the gdquot from getting reclaimed.
         */
-       if (!mutex_trylock(&xfs_Gqm->qm_dqfrlist_lock)) {
-               trace_xfs_dqput_wait(dqp);
-               xfs_dqunlock(dqp);
-               mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-               xfs_dqlock(dqp);
+       gdqp = dqp->q_gdquot;
+       if (gdqp) {
+               xfs_dqlock(gdqp);
+               dqp->q_gdquot = NULL;
        }
+       xfs_dqunlock(dqp);
 
-       while (1) {
-               gdqp = NULL;
-
-               /* We can't depend on nrefs being == 1 here */
-               if (--dqp->q_nrefs == 0) {
-                       trace_xfs_dqput_free(dqp);
-
-                       list_add_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
-                       xfs_Gqm->qm_dqfrlist_cnt++;
-
-                       /*
-                        * If we just added a udquot to the freelist, then
-                        * we want to release the gdquot reference that
-                        * it (probably) has. Otherwise it'll keep the
-                        * gdquot from getting reclaimed.
-                        */
-                       if ((gdqp = dqp->q_gdquot)) {
-                               /*
-                                * Avoid a recursive dqput call
-                                */
-                               xfs_dqlock(gdqp);
-                               dqp->q_gdquot = NULL;
-                       }
-               }
-               xfs_dqunlock(dqp);
-
-               /*
-                * If we had a group quota inside the user quota as a hint,
-                * release it now.
-                */
-               if (! gdqp)
-                       break;
+       /*
+        * If we had a group quota hint, release it now.
+        */
+       if (gdqp) {
                dqp = gdqp;
+               goto recurse;
        }
-       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
 }
 
 /*
@@ -1169,7 +1054,7 @@ xfs_qm_dqflush(
         * If not dirty, or it's pinned and we are not supposed to block, nada.
         */
        if (!XFS_DQ_IS_DIRTY(dqp) ||
-           (!(flags & SYNC_WAIT) && atomic_read(&dqp->q_pincount) > 0)) {
+           ((flags & SYNC_TRYLOCK) && atomic_read(&dqp->q_pincount) > 0)) {
                xfs_dqfunlock(dqp);
                return 0;
        }
@@ -1257,40 +1142,17 @@ xfs_qm_dqflush(
 
 }
 
-int
-xfs_qm_dqlock_nowait(
-       xfs_dquot_t *dqp)
-{
-       return mutex_trylock(&dqp->q_qlock);
-}
-
-void
-xfs_dqlock(
-       xfs_dquot_t *dqp)
-{
-       mutex_lock(&dqp->q_qlock);
-}
-
 void
 xfs_dqunlock(
        xfs_dquot_t *dqp)
 {
-       mutex_unlock(&(dqp->q_qlock));
+       xfs_dqunlock_nonotify(dqp);
        if (dqp->q_logitem.qli_dquot == dqp) {
-               /* Once was dqp->q_mount, but might just have been cleared */
                xfs_trans_unlocked_item(dqp->q_logitem.qli_item.li_ailp,
-                                       (xfs_log_item_t*)&(dqp->q_logitem));
+                                       &dqp->q_logitem.qli_item);
        }
 }
 
-
-void
-xfs_dqunlock_nonotify(
-       xfs_dquot_t *dqp)
-{
-       mutex_unlock(&(dqp->q_qlock));
-}
-
 /*
  * Lock two xfs_dquot structures.
  *
@@ -1319,43 +1181,18 @@ xfs_dqlock2(
        }
 }
 
-
 /*
- * Take a dquot out of the mount's dqlist as well as the hashlist.
- * This is called via unmount as well as quotaoff, and the purge
- * will always succeed unless there are soft (temp) references
- * outstanding.
- *
- * This returns 0 if it was purged, 1 if it wasn't. It's not an error code
- * that we're returning! XXXsup - not cool.
+ * Take a dquot out of the mount's dqlist as well as the hashlist.  This is
+ * called via unmount as well as quotaoff, and the purge will always succeed.
  */
-/* ARGSUSED */
-int
+void
 xfs_qm_dqpurge(
-       xfs_dquot_t     *dqp)
+       struct xfs_dquot        *dqp)
 {
-       xfs_dqhash_t    *qh = dqp->q_hash;
-       xfs_mount_t     *mp = dqp->q_mount;
-
-       ASSERT(mutex_is_locked(&mp->m_quotainfo->qi_dqlist_lock));
-       ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock));
+       struct xfs_mount        *mp = dqp->q_mount;
+       struct xfs_dqhash       *qh = dqp->q_hash;
 
        xfs_dqlock(dqp);
-       /*
-        * We really can't afford to purge a dquot that is
-        * referenced, because these are hard refs.
-        * It shouldn't happen in general because we went thru _all_ inodes in
-        * dqrele_all_inodes before calling this and didn't let the mountlock go.
-        * However it is possible that we have dquots with temporary
-        * references that are not attached to an inode. e.g. see xfs_setattr().
-        */
-       if (dqp->q_nrefs != 0) {
-               xfs_dqunlock(dqp);
-               mutex_unlock(&dqp->q_hash->qh_lock);
-               return (1);
-       }
-
-       ASSERT(!list_empty(&dqp->q_freelist));
 
        /*
         * If we're turning off quotas, we have to make sure that, for
@@ -1370,23 +1207,18 @@ xfs_qm_dqpurge(
                 * Block on the flush lock after nudging dquot buffer,
                 * if it is incore.
                 */
-               xfs_qm_dqflock_pushbuf_wait(dqp);
+               xfs_dqflock_pushbuf_wait(dqp);
        }
 
        /*
-        * XXXIf we're turning this type of quotas off, we don't care
+        * If we are turning this type of quotas off, we don't care
         * about the dirty metadata sitting in this dquot. OTOH, if
         * we're unmounting, we do care, so we flush it and wait.
         */
        if (XFS_DQ_IS_DIRTY(dqp)) {
                int     error;
 
-               /* dqflush unlocks dqflock */
                /*
-                * Given that dqpurge is a very rare occurrence, it is OK
-                * that we're holding the hashlist and mplist locks
-                * across the disk write. But, ... XXXsup
-                *
                 * We don't care about getting disk errors here. We need
                 * to purge this dquot anyway, so we go ahead regardless.
                 */
@@ -1396,38 +1228,44 @@ xfs_qm_dqpurge(
                                __func__, dqp);
                xfs_dqflock(dqp);
        }
+
        ASSERT(atomic_read(&dqp->q_pincount) == 0);
        ASSERT(XFS_FORCED_SHUTDOWN(mp) ||
               !(dqp->q_logitem.qli_item.li_flags & XFS_LI_IN_AIL));
 
+       xfs_dqfunlock(dqp);
+       xfs_dqunlock(dqp);
+
+       mutex_lock(&qh->qh_lock);
        list_del_init(&dqp->q_hashlist);
        qh->qh_version++;
+       mutex_unlock(&qh->qh_lock);
+
+       mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
        list_del_init(&dqp->q_mplist);
        mp->m_quotainfo->qi_dqreclaims++;
        mp->m_quotainfo->qi_dquots--;
+       mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
+
        /*
-        * XXX Move this to the front of the freelist, if we can get the
-        * freelist lock.
+        * We move dquots to the freelist as soon as their reference count
+        * hits zero, so it really should be on the freelist here.
         */
+       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
        ASSERT(!list_empty(&dqp->q_freelist));
+       list_del_init(&dqp->q_freelist);
+       xfs_Gqm->qm_dqfrlist_cnt--;
+       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
 
-       dqp->q_mount = NULL;
-       dqp->q_hash = NULL;
-       dqp->dq_flags = XFS_DQ_INACTIVE;
-       memset(&dqp->q_core, 0, sizeof(dqp->q_core));
-       xfs_dqfunlock(dqp);
-       xfs_dqunlock(dqp);
-       mutex_unlock(&qh->qh_lock);
-       return (0);
+       xfs_qm_dqdestroy(dqp);
 }
 
-
 /*
  * Give the buffer a little push if it is incore and
  * wait on the flush lock.
  */
 void
-xfs_qm_dqflock_pushbuf_wait(
+xfs_dqflock_pushbuf_wait(
        xfs_dquot_t     *dqp)
 {
        xfs_mount_t     *mp = dqp->q_mount;
index 34b7e945dbfadbcf22b2fb900326e53d9f196f3a..a1d91d8f18027b9e217f07ff8769d9d4a21fe2a1 100644 (file)
@@ -80,8 +80,6 @@ enum {
        XFS_QLOCK_NESTED,
 };
 
-#define XFS_DQHOLD(dqp)                ((dqp)->q_nrefs++)
-
 /*
  * Manage the q_flush completion queue embedded in the dquot.  This completion
  * queue synchronizes processes attempting to flush the in-core dquot back to
@@ -102,6 +100,21 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
        complete(&dqp->q_flush);
 }
 
+static inline int xfs_dqlock_nowait(struct xfs_dquot *dqp)
+{
+       return mutex_trylock(&dqp->q_qlock);
+}
+
+static inline void xfs_dqlock(struct xfs_dquot *dqp)
+{
+       mutex_lock(&dqp->q_qlock);
+}
+
+static inline void xfs_dqunlock_nonotify(struct xfs_dquot *dqp)
+{
+       mutex_unlock(&dqp->q_qlock);
+}
+
 #define XFS_DQ_IS_LOCKED(dqp)  (mutex_is_locked(&((dqp)->q_qlock)))
 #define XFS_DQ_IS_DIRTY(dqp)   ((dqp)->dq_flags & XFS_DQ_DIRTY)
 #define XFS_QM_ISUDQ(dqp)      ((dqp)->dq_flags & XFS_DQ_USER)
@@ -116,12 +129,12 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
                                     (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
                                     (XFS_IS_OQUOTA_ON((d)->q_mount))))
 
+extern int             xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
+                                       uint, struct xfs_dquot  **);
 extern void            xfs_qm_dqdestroy(xfs_dquot_t *);
 extern int             xfs_qm_dqflush(xfs_dquot_t *, uint);
-extern int             xfs_qm_dqpurge(xfs_dquot_t *);
+extern void            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 void            xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
 extern void            xfs_qm_adjust_dqtimers(xfs_mount_t *,
                                        xfs_disk_dquot_t *);
 extern void            xfs_qm_adjust_dqlimits(xfs_mount_t *,
@@ -129,9 +142,17 @@ extern void                xfs_qm_adjust_dqlimits(xfs_mount_t *,
 extern int             xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
                                        xfs_dqid_t, uint, uint, xfs_dquot_t **);
 extern void            xfs_qm_dqput(xfs_dquot_t *);
-extern void            xfs_dqlock(xfs_dquot_t *);
-extern void            xfs_dqlock2(xfs_dquot_t *, xfs_dquot_t *);
-extern void            xfs_dqunlock(xfs_dquot_t *);
-extern void            xfs_dqunlock_nonotify(xfs_dquot_t *);
+
+extern void            xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *);
+extern void            xfs_dqunlock(struct xfs_dquot *);
+extern void            xfs_dqflock_pushbuf_wait(struct xfs_dquot *dqp);
+
+static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
+{
+       xfs_dqlock(dqp);
+       dqp->q_nrefs++;
+       xfs_dqunlock(dqp);
+       return dqp;
+}
 
 #endif /* __XFS_DQUOT_H__ */
index 0dee0b71029d8406add271b9f20350e6b8a97859..34baeae4526580c193ec5741bbaac4a165dadf0c 100644 (file)
@@ -73,7 +73,6 @@ xfs_qm_dquot_logitem_format(
        logvec->i_len  = sizeof(xfs_disk_dquot_t);
        logvec->i_type = XLOG_REG_TYPE_DQUOT;
 
-       ASSERT(2 == lip->li_desc->lid_size);
        qlip->qli_format.qlf_size = 2;
 
 }
@@ -134,7 +133,7 @@ xfs_qm_dquot_logitem_push(
         * lock without sleeping, then there must not have been
         * anyone in the process of flushing the dquot.
         */
-       error = xfs_qm_dqflush(dqp, 0);
+       error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK);
        if (error)
                xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p",
                        __func__, error, dqp);
@@ -237,7 +236,7 @@ xfs_qm_dquot_logitem_trylock(
        if (atomic_read(&dqp->q_pincount) > 0)
                return XFS_ITEM_PINNED;
 
-       if (!xfs_qm_dqlock_nowait(dqp))
+       if (!xfs_dqlock_nowait(dqp))
                return XFS_ITEM_LOCKED;
 
        if (!xfs_dqflock_nowait(dqp)) {
index abaafdbb3e658e9c484fb82dcfd5b63afade43e9..cfd6c7f8cc3c09450e1ad6dfff372f12938d1d42 100644 (file)
@@ -437,7 +437,6 @@ xfs_inode_item_format(
         * Assert that no attribute-related log flags are set.
         */
        if (!XFS_IFORK_Q(ip)) {
-               ASSERT(nvecs == lip->li_desc->lid_size);
                iip->ili_format.ilf_size = nvecs;
                ASSERT(!(iip->ili_format.ilf_fields &
                         (XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT)));
@@ -521,7 +520,6 @@ xfs_inode_item_format(
                break;
        }
 
-       ASSERT(nvecs == lip->li_desc->lid_size);
        iip->ili_format.ilf_size = nvecs;
 }
 
index 34817adf4b9ed837da47d6f9ccfa977829fdd33c..e2cc3568c2998ccc45be81b5381c1bf9f91fcf9f 100644 (file)
@@ -760,38 +760,6 @@ xfs_log_item_init(
        INIT_LIST_HEAD(&item->li_cil);
 }
 
-/*
- * Write region vectors to log.  The write happens using the space reservation
- * of the ticket (tic).  It is not a requirement that all writes for a given
- * transaction occur with one call to xfs_log_write(). However, it is important
- * to note that the transaction reservation code makes an assumption about the
- * number of log headers a transaction requires that may be violated if you
- * don't pass all the transaction vectors in one call....
- */
-int
-xfs_log_write(
-       struct xfs_mount        *mp,
-       struct xfs_log_iovec    reg[],
-       int                     nentries,
-       struct xlog_ticket      *tic,
-       xfs_lsn_t               *start_lsn)
-{
-       struct log              *log = mp->m_log;
-       int                     error;
-       struct xfs_log_vec      vec = {
-               .lv_niovecs = nentries,
-               .lv_iovecp = reg,
-       };
-
-       if (XLOG_FORCED_SHUTDOWN(log))
-               return XFS_ERROR(EIO);
-
-       error = xlog_write(log, &vec, tic, start_lsn, NULL, 0);
-       if (error)
-               xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
-       return error;
-}
-
 void
 xfs_log_move_tail(xfs_mount_t  *mp,
                  xfs_lsn_t     tail_lsn)
@@ -1685,7 +1653,7 @@ xlog_print_tic_res(
        };
 
        xfs_warn(mp,
-               "xfs_log_write: reservation summary:\n"
+               "xlog_write: reservation summary:\n"
                "  trans type  = %s (%u)\n"
                "  unit res    = %d bytes\n"
                "  current res = %d bytes\n"
@@ -1714,7 +1682,7 @@ xlog_print_tic_res(
        }
 
        xfs_alert_tag(mp, XFS_PTAG_LOGRES,
-               "xfs_log_write: reservation ran out. Need to up reservation");
+               "xlog_write: reservation ran out. Need to up reservation");
        xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 }
 
@@ -1968,23 +1936,21 @@ xlog_write(
        *start_lsn = 0;
 
        len = xlog_write_calc_vec_length(ticket, log_vector);
-       if (log->l_cilp) {
-               /*
-                * Region headers and bytes are already accounted for.
-                * We only need to take into account start records and
-                * split regions in this function.
-                */
-               if (ticket->t_flags & XLOG_TIC_INITED)
-                       ticket->t_curr_res -= sizeof(xlog_op_header_t);
 
-               /*
-                * Commit record headers need to be accounted for. These
-                * come in as separate writes so are easy to detect.
-                */
-               if (flags & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS))
-                       ticket->t_curr_res -= sizeof(xlog_op_header_t);
-       } else
-               ticket->t_curr_res -= len;
+       /*
+        * Region headers and bytes are already accounted for.
+        * We only need to take into account start records and
+        * split regions in this function.
+        */
+       if (ticket->t_flags & XLOG_TIC_INITED)
+               ticket->t_curr_res -= sizeof(xlog_op_header_t);
+
+       /*
+        * Commit record headers need to be accounted for. These
+        * come in as separate writes so are easy to detect.
+        */
+       if (flags & (XLOG_COMMIT_TRANS | XLOG_UNMOUNT_TRANS))
+               ticket->t_curr_res -= sizeof(xlog_op_header_t);
 
        if (ticket->t_curr_res < 0)
                xlog_print_tic_res(log->l_mp, ticket);
@@ -2931,8 +2897,7 @@ _xfs_log_force(
 
        XFS_STATS_INC(xs_log_force);
 
-       if (log->l_cilp)
-               xlog_cil_force(log);
+       xlog_cil_force(log);
 
        spin_lock(&log->l_icloglock);
 
@@ -3081,11 +3046,9 @@ _xfs_log_force_lsn(
 
        XFS_STATS_INC(xs_log_force);
 
-       if (log->l_cilp) {
-               lsn = xlog_cil_force_lsn(log, lsn);
-               if (lsn == NULLCOMMITLSN)
-                       return 0;
-       }
+       lsn = xlog_cil_force_lsn(log, lsn);
+       if (lsn == NULLCOMMITLSN)
+               return 0;
 
 try_again:
        spin_lock(&log->l_icloglock);
@@ -3653,7 +3616,7 @@ xfs_log_force_umount(
         * completed transactions are flushed to disk with the xfs_log_force()
         * call below.
         */
-       if (!logerror && (mp->m_flags & XFS_MOUNT_DELAYLOG))
+       if (!logerror)
                xlog_cil_force(log);
 
        /*
index 3f7bf451c03446f920484a03eb6e073706127a2f..2aee3b22d29c26d9d11b92f9e1531cab1c2540e3 100644 (file)
@@ -174,11 +174,6 @@ int          xfs_log_reserve(struct xfs_mount *mp,
                          __uint8_t        clientid,
                          uint             flags,
                          uint             t_type);
-int      xfs_log_write(struct xfs_mount *mp,
-                       xfs_log_iovec_t  region[],
-                       int              nentries,
-                       struct xlog_ticket *ticket,
-                       xfs_lsn_t        *start_lsn);
 int      xfs_log_unmount_write(struct xfs_mount *mp);
 void      xfs_log_unmount(struct xfs_mount *mp);
 int      xfs_log_force_umount(struct xfs_mount *mp, int logerror);
@@ -189,8 +184,7 @@ void          xlog_iodone(struct xfs_buf *);
 struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
 void     xfs_log_ticket_put(struct xlog_ticket *ticket);
 
-void   xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
-                               struct xfs_log_vec *log_vector,
+int    xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
                                xfs_lsn_t *commit_lsn, int flags);
 bool   xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
 
index c7755d5a5fbe967ed58bb04ffcc0d47d082a87e4..26db6b13f1f9a87e3e84b52d925753f380fbc401 100644 (file)
 #include "xfs_discard.h"
 
 /*
- * Perform initial CIL structure initialisation. If the CIL is not
- * enabled in this filesystem, ensure the log->l_cilp is null so
- * we can check this conditional to determine if we are doing delayed
- * logging or not.
+ * Perform initial CIL structure initialisation.
  */
 int
 xlog_cil_init(
@@ -44,10 +41,6 @@ xlog_cil_init(
        struct xfs_cil  *cil;
        struct xfs_cil_ctx *ctx;
 
-       log->l_cilp = NULL;
-       if (!(log->l_mp->m_flags & XFS_MOUNT_DELAYLOG))
-               return 0;
-
        cil = kmem_zalloc(sizeof(*cil), KM_SLEEP|KM_MAYFAIL);
        if (!cil)
                return ENOMEM;
@@ -80,9 +73,6 @@ void
 xlog_cil_destroy(
        struct log      *log)
 {
-       if (!log->l_cilp)
-               return;
-
        if (log->l_cilp->xc_ctx) {
                if (log->l_cilp->xc_ctx->ticket)
                        xfs_log_ticket_put(log->l_cilp->xc_ctx->ticket);
@@ -137,9 +127,6 @@ void
 xlog_cil_init_post_recovery(
        struct log      *log)
 {
-       if (!log->l_cilp)
-               return;
-
        log->l_cilp->xc_ctx->ticket = xlog_cil_ticket_alloc(log);
        log->l_cilp->xc_ctx->sequence = 1;
        log->l_cilp->xc_ctx->commit_lsn = xlog_assign_lsn(log->l_curr_cycle,
@@ -172,37 +159,73 @@ xlog_cil_init_post_recovery(
  * format the regions into the iclog as though they are being formatted
  * directly out of the objects themselves.
  */
-static void
-xlog_cil_format_items(
-       struct log              *log,
-       struct xfs_log_vec      *log_vector)
+static struct xfs_log_vec *
+xlog_cil_prepare_log_vecs(
+       struct xfs_trans        *tp)
 {
-       struct xfs_log_vec *lv;
+       struct xfs_log_item_desc *lidp;
+       struct xfs_log_vec      *lv = NULL;
+       struct xfs_log_vec      *ret_lv = NULL;
 
-       ASSERT(log_vector);
-       for (lv = log_vector; lv; lv = lv->lv_next) {
+
+       /* Bail out if we didn't find a log item.  */
+       if (list_empty(&tp->t_items)) {
+               ASSERT(0);
+               return NULL;
+       }
+
+       list_for_each_entry(lidp, &tp->t_items, lid_trans) {
+               struct xfs_log_vec *new_lv;
                void    *ptr;
                int     index;
                int     len = 0;
+               uint    niovecs;
+
+               /* Skip items which aren't dirty in this transaction. */
+               if (!(lidp->lid_flags & XFS_LID_DIRTY))
+                       continue;
+
+               /* Skip items that do not have any vectors for writing */
+               niovecs = IOP_SIZE(lidp->lid_item);
+               if (!niovecs)
+                       continue;
+
+               new_lv = kmem_zalloc(sizeof(*new_lv) +
+                               niovecs * sizeof(struct xfs_log_iovec),
+                               KM_SLEEP);
+
+               /* The allocated iovec region lies beyond the log vector. */
+               new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
+               new_lv->lv_niovecs = niovecs;
+               new_lv->lv_item = lidp->lid_item;
 
                /* build the vector array and calculate it's length */
-               IOP_FORMAT(lv->lv_item, lv->lv_iovecp);
-               for (index = 0; index < lv->lv_niovecs; index++)
-                       len += lv->lv_iovecp[index].i_len;
+               IOP_FORMAT(new_lv->lv_item, new_lv->lv_iovecp);
+               for (index = 0; index < new_lv->lv_niovecs; index++)
+                       len += new_lv->lv_iovecp[index].i_len;
 
-               lv->lv_buf_len = len;
-               lv->lv_buf = kmem_alloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
-               ptr = lv->lv_buf;
+               new_lv->lv_buf_len = len;
+               new_lv->lv_buf = kmem_alloc(new_lv->lv_buf_len,
+                               KM_SLEEP|KM_NOFS);
+               ptr = new_lv->lv_buf;
 
-               for (index = 0; index < lv->lv_niovecs; index++) {
-                       struct xfs_log_iovec *vec = &lv->lv_iovecp[index];
+               for (index = 0; index < new_lv->lv_niovecs; index++) {
+                       struct xfs_log_iovec *vec = &new_lv->lv_iovecp[index];
 
                        memcpy(ptr, vec->i_addr, vec->i_len);
                        vec->i_addr = ptr;
                        ptr += vec->i_len;
                }
-               ASSERT(ptr == lv->lv_buf + lv->lv_buf_len);
+               ASSERT(ptr == new_lv->lv_buf + new_lv->lv_buf_len);
+
+               if (!ret_lv)
+                       ret_lv = new_lv;
+               else
+                       lv->lv_next = new_lv;
+               lv = new_lv;
        }
+
+       return ret_lv;
 }
 
 /*
@@ -635,28 +658,30 @@ out_abort:
  * background commit, returns without it held once background commits are
  * allowed again.
  */
-void
+int
 xfs_log_commit_cil(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
-       struct xfs_log_vec      *log_vector,
        xfs_lsn_t               *commit_lsn,
        int                     flags)
 {
        struct log              *log = mp->m_log;
        int                     log_flags = 0;
        int                     push = 0;
+       struct xfs_log_vec      *log_vector;
 
        if (flags & XFS_TRANS_RELEASE_LOG_RES)
                log_flags = XFS_LOG_REL_PERM_RESERV;
 
        /*
-        * do all the hard work of formatting items (including memory
+        * Do all the hard work of formatting items (including memory
         * allocation) outside the CIL context lock. This prevents stalling CIL
         * pushes when we are low on memory and a transaction commit spends a
         * lot of time in memory reclaim.
         */
-       xlog_cil_format_items(log, log_vector);
+       log_vector = xlog_cil_prepare_log_vecs(tp);
+       if (!log_vector)
+               return ENOMEM;
 
        /* lock out background commit */
        down_read(&log->l_cilp->xc_ctx_lock);
@@ -709,6 +734,7 @@ xfs_log_commit_cil(
         */
        if (push)
                xlog_cil_push(log, 0);
+       return 0;
 }
 
 /*
@@ -786,8 +812,6 @@ xfs_log_item_in_current_chkpt(
 {
        struct xfs_cil_ctx *ctx;
 
-       if (!(lip->li_mountp->m_flags & XFS_MOUNT_DELAYLOG))
-               return false;
        if (list_empty(&lip->li_cil))
                return false;
 
index bb24dac42a2517fe57c79db2763f1b38ca56b83d..19f69e232509019ffa1ac99381e75cb0279ee908 100644 (file)
@@ -219,7 +219,6 @@ typedef struct xfs_mount {
 #define XFS_MOUNT_WSYNC                (1ULL << 0)     /* for nfs - all metadata ops
                                                   must be synchronous except
                                                   for space allocations */
-#define XFS_MOUNT_DELAYLOG     (1ULL << 1)     /* delayed logging is enabled */
 #define XFS_MOUNT_WAS_CLEAN    (1ULL << 3)
 #define XFS_MOUNT_FS_SHUTDOWN  (1ULL << 4)     /* atomic stop of all filesystem
                                                   operations, typically for
index 0bbb1a41998bc95563813ef8a584e104aad5c462..671f37eae1c7bbe3c9f89fd78b9c51b9195f4e32 100644 (file)
@@ -154,12 +154,17 @@ STATIC void
 xfs_qm_destroy(
        struct xfs_qm   *xqm)
 {
-       struct xfs_dquot *dqp, *n;
        int             hsize, i;
 
        ASSERT(xqm != NULL);
        ASSERT(xqm->qm_nrefs == 0);
+
        unregister_shrinker(&xfs_qm_shaker);
+
+       mutex_lock(&xqm->qm_dqfrlist_lock);
+       ASSERT(list_empty(&xqm->qm_dqfrlist));
+       mutex_unlock(&xqm->qm_dqfrlist_lock);
+
        hsize = xqm->qm_dqhashmask + 1;
        for (i = 0; i < hsize; i++) {
                xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
@@ -171,17 +176,6 @@ xfs_qm_destroy(
        xqm->qm_grp_dqhtable = NULL;
        xqm->qm_dqhashmask = 0;
 
-       /* frlist cleanup */
-       mutex_lock(&xqm->qm_dqfrlist_lock);
-       list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
-               xfs_dqlock(dqp);
-               list_del_init(&dqp->q_freelist);
-               xfs_Gqm->qm_dqfrlist_cnt--;
-               xfs_dqunlock(dqp);
-               xfs_qm_dqdestroy(dqp);
-       }
-       mutex_unlock(&xqm->qm_dqfrlist_lock);
-       mutex_destroy(&xqm->qm_dqfrlist_lock);
        kmem_free(xqm);
 }
 
@@ -232,33 +226,9 @@ STATIC void
 xfs_qm_rele_quotafs_ref(
        struct xfs_mount *mp)
 {
-       xfs_dquot_t     *dqp, *n;
-
        ASSERT(xfs_Gqm);
        ASSERT(xfs_Gqm->qm_nrefs > 0);
 
-       /*
-        * Go thru the freelist and destroy all inactive dquots.
-        */
-       mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-
-       list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) {
-               xfs_dqlock(dqp);
-               if (dqp->dq_flags & XFS_DQ_INACTIVE) {
-                       ASSERT(dqp->q_mount == NULL);
-                       ASSERT(! XFS_DQ_IS_DIRTY(dqp));
-                       ASSERT(list_empty(&dqp->q_hashlist));
-                       ASSERT(list_empty(&dqp->q_mplist));
-                       list_del_init(&dqp->q_freelist);
-                       xfs_Gqm->qm_dqfrlist_cnt--;
-                       xfs_dqunlock(dqp);
-                       xfs_qm_dqdestroy(dqp);
-               } else {
-                       xfs_dqunlock(dqp);
-               }
-       }
-       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-
        /*
         * Destroy the entire XQM. If somebody mounts with quotaon, this'll
         * be restarted.
@@ -415,8 +385,7 @@ xfs_qm_unmount_quotas(
  */
 STATIC int
 xfs_qm_dqflush_all(
-       struct xfs_mount        *mp,
-       int                     sync_mode)
+       struct xfs_mount        *mp)
 {
        struct xfs_quotainfo    *q = mp->m_quotainfo;
        int                     recl;
@@ -429,7 +398,8 @@ again:
        mutex_lock(&q->qi_dqlist_lock);
        list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) {
                xfs_dqlock(dqp);
-               if (! XFS_DQ_IS_DIRTY(dqp)) {
+               if ((dqp->dq_flags & XFS_DQ_FREEING) ||
+                   !XFS_DQ_IS_DIRTY(dqp)) {
                        xfs_dqunlock(dqp);
                        continue;
                }
@@ -444,14 +414,14 @@ again:
                         * out immediately.  We'll be able to acquire
                         * the flush lock when the I/O completes.
                         */
-                       xfs_qm_dqflock_pushbuf_wait(dqp);
+                       xfs_dqflock_pushbuf_wait(dqp);
                }
                /*
                 * Let go of the mplist lock. We don't want to hold it
                 * across a disk write.
                 */
                mutex_unlock(&q->qi_dqlist_lock);
-               error = xfs_qm_dqflush(dqp, sync_mode);
+               error = xfs_qm_dqflush(dqp, 0);
                xfs_dqunlock(dqp);
                if (error)
                        return error;
@@ -468,6 +438,7 @@ again:
        /* return ! busy */
        return 0;
 }
+
 /*
  * Release the group dquot pointers the user dquots may be
  * carrying around as a hint. mplist is locked on entry and exit.
@@ -478,31 +449,26 @@ xfs_qm_detach_gdquots(
 {
        struct xfs_quotainfo    *q = mp->m_quotainfo;
        struct xfs_dquot        *dqp, *gdqp;
-       int                     nrecl;
 
  again:
        ASSERT(mutex_is_locked(&q->qi_dqlist_lock));
        list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) {
                xfs_dqlock(dqp);
-               if ((gdqp = dqp->q_gdquot)) {
-                       xfs_dqlock(gdqp);
-                       dqp->q_gdquot = NULL;
-               }
-               xfs_dqunlock(dqp);
-
-               if (gdqp) {
-                       /*
-                        * Can't hold the mplist lock across a dqput.
-                        * XXXmust convert to marker based iterations here.
-                        */
-                       nrecl = q->qi_dqreclaims;
+               if (dqp->dq_flags & XFS_DQ_FREEING) {
+                       xfs_dqunlock(dqp);
                        mutex_unlock(&q->qi_dqlist_lock);
-                       xfs_qm_dqput(gdqp);
-
+                       delay(1);
                        mutex_lock(&q->qi_dqlist_lock);
-                       if (nrecl != q->qi_dqreclaims)
-                               goto again;
+                       goto again;
                }
+
+               gdqp = dqp->q_gdquot;
+               if (gdqp)
+                       dqp->q_gdquot = NULL;
+               xfs_dqunlock(dqp);
+
+               if (gdqp)
+                       xfs_qm_dqrele(gdqp);
        }
 }
 
@@ -520,8 +486,8 @@ xfs_qm_dqpurge_int(
        struct xfs_quotainfo    *q = mp->m_quotainfo;
        struct xfs_dquot        *dqp, *n;
        uint                    dqtype;
-       int                     nrecl;
-       int                     nmisses;
+       int                     nmisses = 0;
+       LIST_HEAD               (dispose_list);
 
        if (!q)
                return 0;
@@ -540,47 +506,26 @@ xfs_qm_dqpurge_int(
         */
        xfs_qm_detach_gdquots(mp);
 
-      again:
-       nmisses = 0;
-       ASSERT(mutex_is_locked(&q->qi_dqlist_lock));
        /*
-        * Try to get rid of all of the unwanted dquots. The idea is to
-        * get them off mplist and hashlist, but leave them on freelist.
+        * Try to get rid of all of the unwanted dquots.
         */
        list_for_each_entry_safe(dqp, n, &q->qi_dqlist, q_mplist) {
-               /*
-                * It's OK to look at the type without taking dqlock here.
-                * We're holding the mplist lock here, and that's needed for
-                * a dqreclaim.
-                */
-               if ((dqp->dq_flags & dqtype) == 0)
-                       continue;
-
-               if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
-                       nrecl = q->qi_dqreclaims;
-                       mutex_unlock(&q->qi_dqlist_lock);
-                       mutex_lock(&dqp->q_hash->qh_lock);
-                       mutex_lock(&q->qi_dqlist_lock);
-
-                       /*
-                        * XXXTheoretically, we can get into a very long
-                        * ping pong game here.
-                        * No one can be adding dquots to the mplist at
-                        * this point, but somebody might be taking things off.
-                        */
-                       if (nrecl != q->qi_dqreclaims) {
-                               mutex_unlock(&dqp->q_hash->qh_lock);
-                               goto again;
-                       }
+               xfs_dqlock(dqp);
+               if ((dqp->dq_flags & dqtype) != 0 &&
+                   !(dqp->dq_flags & XFS_DQ_FREEING)) {
+                       if (dqp->q_nrefs == 0) {
+                               dqp->dq_flags |= XFS_DQ_FREEING;
+                               list_move_tail(&dqp->q_mplist, &dispose_list);
+                       } else
+                               nmisses++;
                }
-
-               /*
-                * Take the dquot off the mplist and hashlist. It may remain on
-                * freelist in INACTIVE state.
-                */
-               nmisses += xfs_qm_dqpurge(dqp);
+               xfs_dqunlock(dqp);
        }
        mutex_unlock(&q->qi_dqlist_lock);
+
+       list_for_each_entry_safe(dqp, n, &dispose_list, q_mplist)
+               xfs_qm_dqpurge(dqp);
+
        return nmisses;
 }
 
@@ -648,12 +593,9 @@ xfs_qm_dqattach_one(
                 */
                dqp = udqhint->q_gdquot;
                if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
-                       xfs_dqlock(dqp);
-                       XFS_DQHOLD(dqp);
                        ASSERT(*IO_idqpp == NULL);
-                       *IO_idqpp = dqp;
 
-                       xfs_dqunlock(dqp);
+                       *IO_idqpp = xfs_qm_dqhold(dqp);
                        xfs_dqunlock(udqhint);
                        return 0;
                }
@@ -693,11 +635,7 @@ xfs_qm_dqattach_one(
 
 /*
  * Given a udquot and gdquot, attach a ptr to the group dquot in the
- * udquot as a hint for future lookups. The idea sounds simple, but the
- * execution isn't, because the udquot might have a group dquot attached
- * already and getting rid of that gets us into lock ordering constraints.
- * The process is complicated more by the fact that the dquots may or may not
- * be locked on entry.
+ * udquot as a hint for future lookups.
  */
 STATIC void
 xfs_qm_dqattach_grouphint(
@@ -708,45 +646,17 @@ xfs_qm_dqattach_grouphint(
 
        xfs_dqlock(udq);
 
-       if ((tmp = udq->q_gdquot)) {
-               if (tmp == gdq) {
-                       xfs_dqunlock(udq);
-                       return;
-               }
+       tmp = udq->q_gdquot;
+       if (tmp) {
+               if (tmp == gdq)
+                       goto done;
 
                udq->q_gdquot = NULL;
-               /*
-                * We can't keep any dqlocks when calling dqrele,
-                * because the freelist lock comes before dqlocks.
-                */
-               xfs_dqunlock(udq);
-               /*
-                * we took a hard reference once upon a time in dqget,
-                * so give it back when the udquot no longer points at it
-                * dqput() does the unlocking of the dquot.
-                */
                xfs_qm_dqrele(tmp);
-
-               xfs_dqlock(udq);
-               xfs_dqlock(gdq);
-
-       } else {
-               ASSERT(XFS_DQ_IS_LOCKED(udq));
-               xfs_dqlock(gdq);
-       }
-
-       ASSERT(XFS_DQ_IS_LOCKED(udq));
-       ASSERT(XFS_DQ_IS_LOCKED(gdq));
-       /*
-        * Somebody could have attached a gdquot here,
-        * when we dropped the uqlock. If so, just do nothing.
-        */
-       if (udq->q_gdquot == NULL) {
-               XFS_DQHOLD(gdq);
-               udq->q_gdquot = gdq;
        }
 
-       xfs_dqunlock(gdq);
+       udq->q_gdquot = xfs_qm_dqhold(gdq);
+done:
        xfs_dqunlock(udq);
 }
 
@@ -813,17 +723,13 @@ xfs_qm_dqattach_locked(
                ASSERT(ip->i_gdquot);
 
                /*
-                * We may or may not have the i_udquot locked at this point,
-                * but this check is OK since we don't depend on the i_gdquot to
-                * be accurate 100% all the time. It is just a hint, and this
-                * will succeed in general.
-                */
-               if (ip->i_udquot->q_gdquot == ip->i_gdquot)
-                       goto done;
-               /*
-                * Attach i_gdquot to the gdquot hint inside the i_udquot.
+                * We do not have i_udquot locked at this point, but this check
+                * is OK since we don't depend on the i_gdquot to be accurate
+                * 100% all the time. It is just a hint, and this will
+                * succeed in general.
                 */
-               xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
+               if (ip->i_udquot->q_gdquot != ip->i_gdquot)
+                       xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
        }
 
  done:
@@ -879,100 +785,6 @@ xfs_qm_dqdetach(
        }
 }
 
-int
-xfs_qm_sync(
-       struct xfs_mount        *mp,
-       int                     flags)
-{
-       struct xfs_quotainfo    *q = mp->m_quotainfo;
-       int                     recl, restarts;
-       struct xfs_dquot        *dqp;
-       int                     error;
-
-       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
-               return 0;
-
-       restarts = 0;
-
-  again:
-       mutex_lock(&q->qi_dqlist_lock);
-       /*
-        * dqpurge_all() also takes the mplist lock and iterate thru all dquots
-        * in quotaoff. However, if the QUOTA_ACTIVE bits are not cleared
-        * when we have the mplist lock, we know that dquots will be consistent
-        * as long as we have it locked.
-        */
-       if (!XFS_IS_QUOTA_ON(mp)) {
-               mutex_unlock(&q->qi_dqlist_lock);
-               return 0;
-       }
-       ASSERT(mutex_is_locked(&q->qi_dqlist_lock));
-       list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) {
-               /*
-                * If this is vfs_sync calling, then skip the dquots that
-                * don't 'seem' to be dirty. ie. don't acquire dqlock.
-                * This is very similar to what xfs_sync does with inodes.
-                */
-               if (flags & SYNC_TRYLOCK) {
-                       if (!XFS_DQ_IS_DIRTY(dqp))
-                               continue;
-                       if (!xfs_qm_dqlock_nowait(dqp))
-                               continue;
-               } else {
-                       xfs_dqlock(dqp);
-               }
-
-               /*
-                * Now, find out for sure if this dquot is dirty or not.
-                */
-               if (! XFS_DQ_IS_DIRTY(dqp)) {
-                       xfs_dqunlock(dqp);
-                       continue;
-               }
-
-               /* XXX a sentinel would be better */
-               recl = q->qi_dqreclaims;
-               if (!xfs_dqflock_nowait(dqp)) {
-                       if (flags & SYNC_TRYLOCK) {
-                               xfs_dqunlock(dqp);
-                               continue;
-                       }
-                       /*
-                        * If we can't grab the flush lock then if the caller
-                        * really wanted us to give this our best shot, so
-                        * see if we can give a push to the buffer before we wait
-                        * on the flush lock. At this point, we know that
-                        * even though the dquot is being flushed,
-                        * it has (new) dirty data.
-                        */
-                       xfs_qm_dqflock_pushbuf_wait(dqp);
-               }
-               /*
-                * Let go of the mplist lock. We don't want to hold it
-                * across a disk write
-                */
-               mutex_unlock(&q->qi_dqlist_lock);
-               error = xfs_qm_dqflush(dqp, flags);
-               xfs_dqunlock(dqp);
-               if (error && XFS_FORCED_SHUTDOWN(mp))
-                       return 0;       /* Need to prevent umount failure */
-               else if (error)
-                       return error;
-
-               mutex_lock(&q->qi_dqlist_lock);
-               if (recl != q->qi_dqreclaims) {
-                       if (++restarts >= XFS_QM_SYNC_MAX_RESTARTS)
-                               break;
-
-                       mutex_unlock(&q->qi_dqlist_lock);
-                       goto again;
-               }
-       }
-
-       mutex_unlock(&q->qi_dqlist_lock);
-       return 0;
-}
-
 /*
  * The hash chains and the mplist use the same xfs_dqhash structure as
  * their list head, but we can take the mplist qh_lock and one of the
@@ -1034,18 +846,21 @@ xfs_qm_init_quotainfo(
        /*
         * We try to get the limits from the superuser's limits fields.
         * This is quite hacky, but it is standard quota practice.
+        *
         * We look at the USR dquot with id == 0 first, but if user quotas
         * are not enabled we goto the GRP dquot with id == 0.
         * We don't really care to keep separate default limits for user
         * and group quotas, at least not at this point.
+        *
+        * Since we may not have done a quotacheck by this point, just read
+        * the dquot without attaching it to any hashtables or lists.
         */
-       error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
-                            XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER : 
-                            (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
-                               XFS_DQ_PROJ),
-                            XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
-                            &dqp);
-       if (! error) {
+       error = xfs_qm_dqread(mp, 0,
+                       XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
+                        (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
+                         XFS_DQ_PROJ),
+                       XFS_QMOPT_DOWARN, &dqp);
+       if (!error) {
                xfs_disk_dquot_t        *ddqp = &dqp->q_core;
 
                /*
@@ -1072,11 +887,6 @@ xfs_qm_init_quotainfo(
                qinf->qi_rtbhardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit);
                qinf->qi_rtbsoftlimit = be64_to_cpu(ddqp->d_rtb_softlimit);
  
-               /*
-                * We sent the XFS_QMOPT_DQSUSER flag to dqget because
-                * we don't want this dquot cached. We haven't done a
-                * quotacheck yet, and quotacheck doesn't like incore dquots.
-                */
                xfs_qm_dqdestroy(dqp);
        } else {
                qinf->qi_btimelimit = XFS_QM_BTIMELIMIT;
@@ -1661,7 +1471,7 @@ xfs_qm_quotacheck(
         * successfully.
         */
        if (!error)
-               error = xfs_qm_dqflush_all(mp, 0);
+               error = xfs_qm_dqflush_all(mp);
 
        /*
         * We can get this error if we couldn't do a dquot allocation inside
@@ -1793,59 +1603,33 @@ xfs_qm_init_quotainos(
 
 
 /*
- * Just pop the least recently used dquot off the freelist and
- * recycle it. The returned dquot is locked.
+ * Pop the least recently used dquot off the freelist and recycle it.
  */
-STATIC xfs_dquot_t *
+STATIC struct xfs_dquot *
 xfs_qm_dqreclaim_one(void)
 {
-       xfs_dquot_t     *dqpout;
-       xfs_dquot_t     *dqp;
-       int             restarts;
-       int             startagain;
-
-       restarts = 0;
-       dqpout = NULL;
+       struct xfs_dquot        *dqp;
+       int                     restarts = 0;
 
-       /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */
-again:
-       startagain = 0;
        mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
-
+restart:
        list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) {
                struct xfs_mount *mp = dqp->q_mount;
-               xfs_dqlock(dqp);
+
+               if (!xfs_dqlock_nowait(dqp))
+                       continue;
 
                /*
-                * We are racing with dqlookup here. Naturally we don't
-                * want to reclaim a dquot that lookup wants. We release the
-                * freelist lock and start over, so that lookup will grab
-                * both the dquot and the freelistlock.
+                * This dquot has already been grabbed by dqlookup.
+                * Remove it from the freelist and try again.
                 */
-               if (dqp->dq_flags & XFS_DQ_WANT) {
-                       ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE));
-
+               if (dqp->q_nrefs) {
                        trace_xfs_dqreclaim_want(dqp);
                        XQM_STATS_INC(xqmstats.xs_qm_dqwants);
-                       restarts++;
-                       startagain = 1;
-                       goto dqunlock;
-               }
 
-               /*
-                * If the dquot is inactive, we are assured that it is
-                * not on the mplist or the hashlist, and that makes our
-                * life easier.
-                */
-               if (dqp->dq_flags & XFS_DQ_INACTIVE) {
-                       ASSERT(mp == NULL);
-                       ASSERT(! XFS_DQ_IS_DIRTY(dqp));
-                       ASSERT(list_empty(&dqp->q_hashlist));
-                       ASSERT(list_empty(&dqp->q_mplist));
                        list_del_init(&dqp->q_freelist);
                        xfs_Gqm->qm_dqfrlist_cnt--;
-                       dqpout = dqp;
-                       XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims);
+                       restarts++;
                        goto dqunlock;
                }
 
@@ -1874,64 +1658,49 @@ again:
                         * We flush it delayed write, so don't bother
                         * releasing the freelist lock.
                         */
-                       error = xfs_qm_dqflush(dqp, 0);
+                       error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK);
                        if (error) {
                                xfs_warn(mp, "%s: dquot %p flush failed",
                                        __func__, dqp);
                        }
                        goto dqunlock;
                }
+               xfs_dqfunlock(dqp);
 
                /*
-                * We're trying to get the hashlock out of order. This races
-                * with dqlookup; so, we giveup and goto the next dquot if
-                * we couldn't get the hashlock. This way, we won't starve
-                * a dqlookup process that holds the hashlock that is
-                * waiting for the freelist lock.
+                * Prevent lookup now that we are going to reclaim the dquot.
+                * Once XFS_DQ_FREEING is set lookup won't touch the dquot,
+                * thus we can drop the lock now.
                 */
-               if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
-                       restarts++;
-                       goto dqfunlock;
-               }
+               dqp->dq_flags |= XFS_DQ_FREEING;
+               xfs_dqunlock(dqp);
 
-               /*
-                * This races with dquot allocation code as well as dqflush_all
-                * and reclaim code. So, if we failed to grab the mplist lock,
-                * giveup everything and start over.
-                */
-               if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) {
-                       restarts++;
-                       startagain = 1;
-                       goto qhunlock;
-               }
+               mutex_lock(&dqp->q_hash->qh_lock);
+               list_del_init(&dqp->q_hashlist);
+               dqp->q_hash->qh_version++;
+               mutex_unlock(&dqp->q_hash->qh_lock);
 
-               ASSERT(dqp->q_nrefs == 0);
+               mutex_lock(&mp->m_quotainfo->qi_dqlist_lock);
                list_del_init(&dqp->q_mplist);
                mp->m_quotainfo->qi_dquots--;
                mp->m_quotainfo->qi_dqreclaims++;
-               list_del_init(&dqp->q_hashlist);
-               dqp->q_hash->qh_version++;
+               mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
+
+               ASSERT(dqp->q_nrefs == 0);
                list_del_init(&dqp->q_freelist);
                xfs_Gqm->qm_dqfrlist_cnt--;
-               dqpout = dqp;
-               mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock);
-qhunlock:
-               mutex_unlock(&dqp->q_hash->qh_lock);
-dqfunlock:
-               xfs_dqfunlock(dqp);
+
+               mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
+               return dqp;
 dqunlock:
                xfs_dqunlock(dqp);
-               if (dqpout)
-                       break;
                if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
                        break;
-               if (startagain) {
-                       mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-                       goto again;
-               }
+               goto restart;
        }
+
        mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
-       return dqpout;
+       return NULL;
 }
 
 /*
@@ -2151,10 +1920,7 @@ xfs_qm_vop_dqalloc(
                         * this to caller
                         */
                        ASSERT(ip->i_udquot);
-                       uq = ip->i_udquot;
-                       xfs_dqlock(uq);
-                       XFS_DQHOLD(uq);
-                       xfs_dqunlock(uq);
+                       uq = xfs_qm_dqhold(ip->i_udquot);
                }
        }
        if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
@@ -2175,10 +1941,7 @@ xfs_qm_vop_dqalloc(
                        xfs_ilock(ip, lockflags);
                } else {
                        ASSERT(ip->i_gdquot);
-                       gq = ip->i_gdquot;
-                       xfs_dqlock(gq);
-                       XFS_DQHOLD(gq);
-                       xfs_dqunlock(gq);
+                       gq = xfs_qm_dqhold(ip->i_gdquot);
                }
        } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
                if (xfs_get_projid(ip) != prid) {
@@ -2198,10 +1961,7 @@ xfs_qm_vop_dqalloc(
                        xfs_ilock(ip, lockflags);
                } else {
                        ASSERT(ip->i_gdquot);
-                       gq = ip->i_gdquot;
-                       xfs_dqlock(gq);
-                       XFS_DQHOLD(gq);
-                       xfs_dqunlock(gq);
+                       gq = xfs_qm_dqhold(ip->i_gdquot);
                }
        }
        if (uq)
@@ -2251,14 +2011,10 @@ xfs_qm_vop_chown(
        xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
 
        /*
-        * Take an extra reference, because the inode
-        * is going to keep this dquot pointer even
-        * after the trans_commit.
+        * Take an extra reference, because the inode is going to keep
+        * this dquot pointer even after the trans_commit.
         */
-       xfs_dqlock(newdq);
-       XFS_DQHOLD(newdq);
-       xfs_dqunlock(newdq);
-       *IO_olddq = newdq;
+       *IO_olddq = xfs_qm_dqhold(newdq);
 
        return prevdq;
 }
@@ -2390,25 +2146,21 @@ xfs_qm_vop_create_dqattach(
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
        if (udqp) {
-               xfs_dqlock(udqp);
-               XFS_DQHOLD(udqp);
-               xfs_dqunlock(udqp);
                ASSERT(ip->i_udquot == NULL);
-               ip->i_udquot = udqp;
                ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
+
+               ip->i_udquot = xfs_qm_dqhold(udqp);
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
        if (gdqp) {
-               xfs_dqlock(gdqp);
-               XFS_DQHOLD(gdqp);
-               xfs_dqunlock(gdqp);
                ASSERT(ip->i_gdquot == NULL);
-               ip->i_gdquot = gdqp;
                ASSERT(XFS_IS_OQUOTA_ON(mp));
                ASSERT((XFS_IS_GQUOTA_ON(mp) ?
                        ip->i_d.di_gid : xfs_get_projid(ip)) ==
                                be32_to_cpu(gdqp->q_core.d_id));
+
+               ip->i_gdquot = xfs_qm_dqhold(gdqp);
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
 }
index 43b9abe1052c4029a6250ec79fe56b27d69fdd43..9b4f3adefbc5dca36d3157ca3f99b3ba92f22da8 100644 (file)
@@ -32,12 +32,6 @@ extern struct xfs_qm *xfs_Gqm;
 extern kmem_zone_t     *qm_dqzone;
 extern kmem_zone_t     *qm_dqtrxzone;
 
-/*
- * Used in xfs_qm_sync called by xfs_sync to count the max times that it can
- * iterate over the mountpt's dquot list in one call.
- */
-#define XFS_QM_SYNC_MAX_RESTARTS       7
-
 /*
  * Ditto, for xfs_qm_dqreclaim_one.
  */
index a595f29567fedda40964ae11eb1e885859acb238..8a0807e0f979eff06d930c39cdd11b3e03b2fcc4 100644 (file)
@@ -87,8 +87,7 @@ typedef struct xfs_dqblk {
 #define XFS_DQ_PROJ            0x0002          /* project quota */
 #define XFS_DQ_GROUP           0x0004          /* a group quota */
 #define XFS_DQ_DIRTY           0x0008          /* dquot is dirty */
-#define XFS_DQ_WANT            0x0010          /* for lookup/reclaim race */
-#define XFS_DQ_INACTIVE                0x0020          /* dq off mplist & hashlist */
+#define XFS_DQ_FREEING         0x0010          /* dquot is beeing torn down */
 
 #define XFS_DQ_ALLTYPES                (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
 
@@ -97,8 +96,7 @@ typedef struct xfs_dqblk {
        { XFS_DQ_PROJ,          "PROJ" }, \
        { XFS_DQ_GROUP,         "GROUP" }, \
        { XFS_DQ_DIRTY,         "DIRTY" }, \
-       { XFS_DQ_WANT,          "WANT" }, \
-       { XFS_DQ_INACTIVE,      "INACTIVE" }
+       { XFS_DQ_FREEING,       "FREEING" }
 
 /*
  * In the worst case, when both user and group quotas are on,
@@ -199,7 +197,6 @@ typedef struct xfs_qoff_logformat {
 #define XFS_QMOPT_UQUOTA       0x0000004 /* user dquot requested */
 #define XFS_QMOPT_PQUOTA       0x0000008 /* project dquot requested */
 #define XFS_QMOPT_FORCE_RES    0x0000010 /* ignore quota limits */
-#define XFS_QMOPT_DQSUSER      0x0000020 /* don't cache super users dquot */
 #define XFS_QMOPT_SBVERSION    0x0000040 /* change superblock version num */
 #define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if needed */
 #define XFS_QMOPT_DQREPAIR     0x0001000 /* repair dquot if damaged */
@@ -326,7 +323,6 @@ extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint);
 extern void xfs_qm_dqdetach(struct xfs_inode *);
 extern void xfs_qm_dqrele(struct xfs_dquot *);
 extern void xfs_qm_statvfs(struct xfs_inode *, struct kstatfs *);
-extern int xfs_qm_sync(struct xfs_mount *, int);
 extern int xfs_qm_newmount(struct xfs_mount *, uint *, uint *);
 extern void xfs_qm_mount_quotas(struct xfs_mount *);
 extern void xfs_qm_unmount(struct xfs_mount *);
@@ -366,10 +362,6 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
 #define xfs_qm_dqdetach(ip)
 #define xfs_qm_dqrele(d)
 #define xfs_qm_statvfs(ip, s)
-static inline int xfs_qm_sync(struct xfs_mount *mp, int flags)
-{
-       return 0;
-}
 #define xfs_qm_newmount(mp, a, b)                                      (0)
 #define xfs_qm_mount_quotas(mp)
 #define xfs_qm_unmount(mp)
index 7b7669507ee38f5e64db218bad4769635286325e..281961c1d81a73df18ab8dcf31c39e6be3d94588 100644 (file)
@@ -199,7 +199,6 @@ xfs_parseargs(
        mp->m_flags |= XFS_MOUNT_BARRIER;
        mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
        mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
-       mp->m_flags |= XFS_MOUNT_DELAYLOG;
 
        /*
         * These can be overridden by the mount option parsing.
@@ -353,11 +352,11 @@ xfs_parseargs(
                        mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
                        mp->m_qflags &= ~XFS_OQUOTA_ENFD;
                } else if (!strcmp(this_char, MNTOPT_DELAYLOG)) {
-                       mp->m_flags |= XFS_MOUNT_DELAYLOG;
+                       xfs_warn(mp,
+       "delaylog is the default now, option is deprecated.");
                } else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
-                       mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
                        xfs_warn(mp,
-       "nodelaylog is deprecated and will be removed in Linux 3.3");
+       "nodelaylog support has been removed, option is deprecated.");
                } else if (!strcmp(this_char, MNTOPT_DISCARD)) {
                        mp->m_flags |= XFS_MOUNT_DISCARD;
                } else if (!strcmp(this_char, MNTOPT_NODISCARD)) {
@@ -395,13 +394,6 @@ xfs_parseargs(
                return EINVAL;
        }
 
-       if ((mp->m_flags & XFS_MOUNT_DISCARD) &&
-           !(mp->m_flags & XFS_MOUNT_DELAYLOG)) {
-               xfs_warn(mp,
-       "the discard option is incompatible with the nodelaylog option");
-               return EINVAL;
-       }
-
 #ifndef CONFIG_XFS_QUOTA
        if (XFS_IS_QUOTA_RUNNING(mp)) {
                xfs_warn(mp, "quota support not available in this kernel.");
@@ -501,7 +493,6 @@ xfs_showargs(
                { XFS_MOUNT_ATTR2,              "," MNTOPT_ATTR2 },
                { XFS_MOUNT_FILESTREAMS,        "," MNTOPT_FILESTREAM },
                { XFS_MOUNT_GRPID,              "," MNTOPT_GRPID },
-               { XFS_MOUNT_DELAYLOG,           "," MNTOPT_DELAYLOG },
                { XFS_MOUNT_DISCARD,            "," MNTOPT_DISCARD },
                { 0, NULL }
        };
@@ -1014,17 +1005,10 @@ xfs_fs_sync_fs(
        int                     error;
 
        /*
-        * Not much we can do for the first async pass.  Writing out the
-        * superblock would be counter-productive as we are going to redirty
-        * when writing out other data and metadata (and writing out a single
-        * block is quite fast anyway).
-        *
-        * Try to asynchronously kick off quota syncing at least.
+        * Doing anything during the async pass would be counterproductive.
         */
-       if (!wait) {
-               xfs_qm_sync(mp, SYNC_TRYLOCK);
+       if (!wait)
                return 0;
-       }
 
        error = xfs_quiesce_data(mp);
        if (error)
@@ -1621,12 +1605,12 @@ STATIC int __init
 xfs_init_workqueues(void)
 {
        /*
-        * max_active is set to 8 to give enough concurency to allow
-        * multiple work operations on each CPU to run. This allows multiple
-        * filesystems to be running sync work concurrently, and scales with
-        * the number of CPUs in the system.
+        * We never want to the same work item to run twice, reclaiming inodes
+        * or idling the log is not going to get any faster by multiple CPUs
+        * competing for ressources.  Use the default large max_active value
+        * so that even lots of filesystems can perform these task in parallel.
         */
-       xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);
+       xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0);
        if (!xfs_syncd_wq)
                return -ENOMEM;
        return 0;
index f0994aedcd158c2db3d6f9b2bf4d21a4f819bec6..72c01a1c16e7d16ca0a49e284addf7d884dbfea6 100644 (file)
@@ -395,10 +395,7 @@ xfs_quiesce_data(
         */
        xfs_inode_ag_iterator(mp, xfs_log_dirty_inode, 0);
 
-       xfs_qm_sync(mp, SYNC_TRYLOCK);
-       xfs_qm_sync(mp, SYNC_WAIT);
-
-       /* force out the newly dirtied log buffers */
+       /* force out the log */
        xfs_log_force(mp, XFS_LOG_SYNC);
 
        /* write superblock and hoover up shutdown errors */
@@ -506,7 +503,6 @@ xfs_sync_worker(
                        error = xfs_fs_log_dummy(mp);
                else
                        xfs_log_force(mp, 0);
-               error = xfs_qm_sync(mp, SYNC_TRYLOCK);
 
                /* start pushing all the metadata that is currently dirty */
                xfs_ail_push_all(mp->m_ail);
index 49403579887324b87c821bc7eb62b0114314ce20..a9d5b1e06efee95920e0bc0dd7b75c6f867b537b 100644 (file)
@@ -743,8 +743,6 @@ DEFINE_DQUOT_EVENT(xfs_dqtobp_read);
 DEFINE_DQUOT_EVENT(xfs_dqread);
 DEFINE_DQUOT_EVENT(xfs_dqread_fail);
 DEFINE_DQUOT_EVENT(xfs_dqlookup_found);
-DEFINE_DQUOT_EVENT(xfs_dqlookup_want);
-DEFINE_DQUOT_EVENT(xfs_dqlookup_freelist);
 DEFINE_DQUOT_EVENT(xfs_dqlookup_done);
 DEFINE_DQUOT_EVENT(xfs_dqget_hit);
 DEFINE_DQUOT_EVENT(xfs_dqget_miss);
index 1f35b2feca978a515cbdc318b93eb50e48f54127..329b06aba1c2c59ab1b973a3a956a3af23c68abf 100644 (file)
@@ -1158,7 +1158,6 @@ xfs_trans_add_item(
 
        lidp->lid_item = lip;
        lidp->lid_flags = 0;
-       lidp->lid_size = 0;
        list_add_tail(&lidp->lid_trans, &tp->t_items);
 
        lip->li_desc = lidp;
@@ -1210,219 +1209,6 @@ xfs_trans_free_items(
        }
 }
 
-/*
- * Unlock the items associated with a transaction.
- *
- * Items which were not logged should be freed.  Those which were logged must
- * still be tracked so they can be unpinned when the transaction commits.
- */
-STATIC void
-xfs_trans_unlock_items(
-       struct xfs_trans        *tp,
-       xfs_lsn_t               commit_lsn)
-{
-       struct xfs_log_item_desc *lidp, *next;
-
-       list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
-               struct xfs_log_item     *lip = lidp->lid_item;
-
-               lip->li_desc = NULL;
-
-               if (commit_lsn != NULLCOMMITLSN)
-                       IOP_COMMITTING(lip, commit_lsn);
-               IOP_UNLOCK(lip);
-
-               /*
-                * Free the descriptor if the item is not dirty
-                * within this transaction.
-                */
-               if (!(lidp->lid_flags & XFS_LID_DIRTY))
-                       xfs_trans_free_item_desc(lidp);
-       }
-}
-
-/*
- * Total up the number of log iovecs needed to commit this
- * transaction.  The transaction itself needs one for the
- * transaction header.  Ask each dirty item in turn how many
- * it needs to get the total.
- */
-static uint
-xfs_trans_count_vecs(
-       struct xfs_trans        *tp)
-{
-       int                     nvecs;
-       struct xfs_log_item_desc *lidp;
-
-       nvecs = 1;
-
-       /* In the non-debug case we need to start bailing out if we
-        * didn't find a log_item here, return zero and let trans_commit
-        * deal with it.
-        */
-       if (list_empty(&tp->t_items)) {
-               ASSERT(0);
-               return 0;
-       }
-
-       list_for_each_entry(lidp, &tp->t_items, lid_trans) {
-               /*
-                * Skip items which aren't dirty in this transaction.
-                */
-               if (!(lidp->lid_flags & XFS_LID_DIRTY))
-                       continue;
-               lidp->lid_size = IOP_SIZE(lidp->lid_item);
-               nvecs += lidp->lid_size;
-       }
-
-       return nvecs;
-}
-
-/*
- * Fill in the vector with pointers to data to be logged
- * by this transaction.  The transaction header takes
- * the first vector, and then each dirty item takes the
- * number of vectors it indicated it needed in xfs_trans_count_vecs().
- *
- * As each item fills in the entries it needs, also pin the item
- * so that it cannot be flushed out until the log write completes.
- */
-static void
-xfs_trans_fill_vecs(
-       struct xfs_trans        *tp,
-       struct xfs_log_iovec    *log_vector)
-{
-       struct xfs_log_item_desc *lidp;
-       struct xfs_log_iovec    *vecp;
-       uint                    nitems;
-
-       /*
-        * Skip over the entry for the transaction header, we'll
-        * fill that in at the end.
-        */
-       vecp = log_vector + 1;
-
-       nitems = 0;
-       ASSERT(!list_empty(&tp->t_items));
-       list_for_each_entry(lidp, &tp->t_items, lid_trans) {
-               /* Skip items which aren't dirty in this transaction. */
-               if (!(lidp->lid_flags & XFS_LID_DIRTY))
-                       continue;
-
-               /*
-                * The item may be marked dirty but not log anything.  This can
-                * be used to get called when a transaction is committed.
-                */
-               if (lidp->lid_size)
-                       nitems++;
-               IOP_FORMAT(lidp->lid_item, vecp);
-               vecp += lidp->lid_size;
-               IOP_PIN(lidp->lid_item);
-       }
-
-       /*
-        * Now that we've counted the number of items in this transaction, fill
-        * in the transaction header. Note that the transaction header does not
-        * have a log item.
-        */
-       tp->t_header.th_magic = XFS_TRANS_HEADER_MAGIC;
-       tp->t_header.th_type = tp->t_type;
-       tp->t_header.th_num_items = nitems;
-       log_vector->i_addr = (xfs_caddr_t)&tp->t_header;
-       log_vector->i_len = sizeof(xfs_trans_header_t);
-       log_vector->i_type = XLOG_REG_TYPE_TRANSHDR;
-}
-
-/*
- * The committed item processing consists of calling the committed routine of
- * each logged item, updating the item's position in the AIL if necessary, and
- * unpinning each item.  If the committed routine returns -1, then do nothing
- * further with the item because it may have been freed.
- *
- * Since items are unlocked when they are copied to the incore log, it is
- * possible for two transactions to be completing and manipulating the same
- * item simultaneously.  The AIL lock will protect the lsn field of each item.
- * The value of this field can never go backwards.
- *
- * We unpin the items after repositioning them in the AIL, because otherwise
- * they could be immediately flushed and we'd have to race with the flusher
- * trying to pull the item from the AIL as we add it.
- */
-static void
-xfs_trans_item_committed(
-       struct xfs_log_item     *lip,
-       xfs_lsn_t               commit_lsn,
-       int                     aborted)
-{
-       xfs_lsn_t               item_lsn;
-       struct xfs_ail          *ailp;
-
-       if (aborted)
-               lip->li_flags |= XFS_LI_ABORTED;
-       item_lsn = IOP_COMMITTED(lip, commit_lsn);
-
-       /* item_lsn of -1 means the item needs no further processing */
-       if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
-               return;
-
-       /*
-        * If the returned lsn is greater than what it contained before, update
-        * the location of the item in the AIL.  If it is not, then do nothing.
-        * Items can never move backwards in the AIL.
-        *
-        * While the new lsn should usually be greater, it is possible that a
-        * later transaction completing simultaneously with an earlier one
-        * using the same item could complete first with a higher lsn.  This
-        * would cause the earlier transaction to fail the test below.
-        */
-       ailp = lip->li_ailp;
-       spin_lock(&ailp->xa_lock);
-       if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0) {
-               /*
-                * This will set the item's lsn to item_lsn and update the
-                * position of the item in the AIL.
-                *
-                * xfs_trans_ail_update() drops the AIL lock.
-                */
-               xfs_trans_ail_update(ailp, lip, item_lsn);
-       } else {
-               spin_unlock(&ailp->xa_lock);
-       }
-
-       /*
-        * Now that we've repositioned the item in the AIL, unpin it so it can
-        * be flushed. Pass information about buffer stale state down from the
-        * log item flags, if anyone else stales the buffer we do not want to
-        * pay any attention to it.
-        */
-       IOP_UNPIN(lip, 0);
-}
-
-/*
- * This is typically called by the LM when a transaction has been fully
- * committed to disk.  It needs to unpin the items which have
- * been logged by the transaction and update their positions
- * in the AIL if necessary.
- *
- * This also gets called when the transactions didn't get written out
- * because of an I/O error. Abortflag & XFS_LI_ABORTED is set then.
- */
-STATIC void
-xfs_trans_committed(
-       void                    *arg,
-       int                     abortflag)
-{
-       struct xfs_trans        *tp = arg;
-       struct xfs_log_item_desc *lidp, *next;
-
-       list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) {
-               xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag);
-               xfs_trans_free_item_desc(lidp);
-       }
-
-       xfs_trans_free(tp);
-}
-
 static inline void
 xfs_log_item_batch_insert(
        struct xfs_ail          *ailp,
@@ -1537,258 +1323,6 @@ xfs_trans_committed_bulk(
        spin_unlock(&ailp->xa_lock);
 }
 
-/*
- * Called from the trans_commit code when we notice that the filesystem is in
- * the middle of a forced shutdown.
- *
- * When we are called here, we have already pinned all the items in the
- * transaction. However, neither IOP_COMMITTING or IOP_UNLOCK has been called
- * so we can simply walk the items in the transaction, unpin them with an abort
- * flag and then free the items. Note that unpinning the items can result in
- * them being freed immediately, so we need to use a safe list traversal method
- * here.
- */
-STATIC void
-xfs_trans_uncommit(
-       struct xfs_trans        *tp,
-       uint                    flags)
-{
-       struct xfs_log_item_desc *lidp, *n;
-
-       list_for_each_entry_safe(lidp, n, &tp->t_items, lid_trans) {
-               if (lidp->lid_flags & XFS_LID_DIRTY)
-                       IOP_UNPIN(lidp->lid_item, 1);
-       }
-
-       xfs_trans_unreserve_and_mod_sb(tp);
-       xfs_trans_unreserve_and_mod_dquots(tp);
-
-       xfs_trans_free_items(tp, NULLCOMMITLSN, flags);
-       xfs_trans_free(tp);
-}
-
-/*
- * Format the transaction direct to the iclog. This isolates the physical
- * transaction commit operation from the logical operation and hence allows
- * other methods to be introduced without affecting the existing commit path.
- */
-static int
-xfs_trans_commit_iclog(
-       struct xfs_mount        *mp,
-       struct xfs_trans        *tp,
-       xfs_lsn_t               *commit_lsn,
-       int                     flags)
-{
-       int                     shutdown;
-       int                     error;
-       int                     log_flags = 0;
-       struct xlog_in_core     *commit_iclog;
-#define XFS_TRANS_LOGVEC_COUNT  16
-       struct xfs_log_iovec    log_vector_fast[XFS_TRANS_LOGVEC_COUNT];
-       struct xfs_log_iovec    *log_vector;
-       uint                    nvec;
-
-
-       /*
-        * Ask each log item how many log_vector entries it will
-        * need so we can figure out how many to allocate.
-        * Try to avoid the kmem_alloc() call in the common case
-        * by using a vector from the stack when it fits.
-        */
-       nvec = xfs_trans_count_vecs(tp);
-       if (nvec == 0) {
-               return ENOMEM;  /* triggers a shutdown! */
-       } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
-               log_vector = log_vector_fast;
-       } else {
-               log_vector = (xfs_log_iovec_t *)kmem_alloc(nvec *
-                                                  sizeof(xfs_log_iovec_t),
-                                                  KM_SLEEP);
-       }
-
-       /*
-        * Fill in the log_vector and pin the logged items, and
-        * then write the transaction to the log.
-        */
-       xfs_trans_fill_vecs(tp, log_vector);
-
-       if (flags & XFS_TRANS_RELEASE_LOG_RES)
-               log_flags = XFS_LOG_REL_PERM_RESERV;
-
-       error = xfs_log_write(mp, log_vector, nvec, tp->t_ticket, &(tp->t_lsn));
-
-       /*
-        * The transaction is committed incore here, and can go out to disk
-        * at any time after this call.  However, all the items associated
-        * with the transaction are still locked and pinned in memory.
-        */
-       *commit_lsn = xfs_log_done(mp, tp->t_ticket, &commit_iclog, log_flags);
-
-       tp->t_commit_lsn = *commit_lsn;
-       trace_xfs_trans_commit_lsn(tp);
-
-       if (nvec > XFS_TRANS_LOGVEC_COUNT)
-               kmem_free(log_vector);
-
-       /*
-        * If we got a log write error. Unpin the logitems that we
-        * had pinned, clean up, free trans structure, and return error.
-        */
-       if (error || *commit_lsn == -1) {
-               current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
-               xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT);
-               return XFS_ERROR(EIO);
-       }
-
-       /*
-        * Once the transaction has committed, unused
-        * reservations need to be released and changes to
-        * the superblock need to be reflected in the in-core
-        * version.  Do that now.
-        */
-       xfs_trans_unreserve_and_mod_sb(tp);
-
-       /*
-        * Tell the LM to call the transaction completion routine
-        * when the log write with LSN commit_lsn completes (e.g.
-        * when the transaction commit really hits the on-disk log).
-        * After this call we cannot reference tp, because the call
-        * can happen at any time and the call will free the transaction
-        * structure pointed to by tp.  The only case where we call
-        * the completion routine (xfs_trans_committed) directly is
-        * if the log is turned off on a debug kernel or we're
-        * running in simulation mode (the log is explicitly turned
-        * off).
-        */
-       tp->t_logcb.cb_func = xfs_trans_committed;
-       tp->t_logcb.cb_arg = tp;
-
-       /*
-        * We need to pass the iclog buffer which was used for the
-        * transaction commit record into this function, and attach
-        * the callback to it. The callback must be attached before
-        * the items are unlocked to avoid racing with other threads
-        * waiting for an item to unlock.
-        */
-       shutdown = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
-
-       /*
-        * Mark this thread as no longer being in a transaction
-        */
-       current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
-
-       /*
-        * Once all the items of the transaction have been copied
-        * to the in core log and the callback is attached, the
-        * items can be unlocked.
-        *
-        * This will free descriptors pointing to items which were
-        * not logged since there is nothing more to do with them.
-        * For items which were logged, we will keep pointers to them
-        * so they can be unpinned after the transaction commits to disk.
-        * This will also stamp each modified meta-data item with
-        * the commit lsn of this transaction for dependency tracking
-        * purposes.
-        */
-       xfs_trans_unlock_items(tp, *commit_lsn);
-
-       /*
-        * If we detected a log error earlier, finish committing
-        * the transaction now (unpin log items, etc).
-        *
-        * Order is critical here, to avoid using the transaction
-        * pointer after its been freed (by xfs_trans_committed
-        * either here now, or as a callback).  We cannot do this
-        * step inside xfs_log_notify as was done earlier because
-        * of this issue.
-        */
-       if (shutdown)
-               xfs_trans_committed(tp, XFS_LI_ABORTED);
-
-       /*
-        * Now that the xfs_trans_committed callback has been attached,
-        * and the items are released we can finally allow the iclog to
-        * go to disk.
-        */
-       return xfs_log_release_iclog(mp, commit_iclog);
-}
-
-/*
- * Walk the log items and allocate log vector structures for
- * each item large enough to fit all the vectors they require.
- * Note that this format differs from the old log vector format in
- * that there is no transaction header in these log vectors.
- */
-STATIC struct xfs_log_vec *
-xfs_trans_alloc_log_vecs(
-       xfs_trans_t     *tp)
-{
-       struct xfs_log_item_desc *lidp;
-       struct xfs_log_vec      *lv = NULL;
-       struct xfs_log_vec      *ret_lv = NULL;
-
-
-       /* Bail out if we didn't find a log item.  */
-       if (list_empty(&tp->t_items)) {
-               ASSERT(0);
-               return NULL;
-       }
-
-       list_for_each_entry(lidp, &tp->t_items, lid_trans) {
-               struct xfs_log_vec *new_lv;
-
-               /* Skip items which aren't dirty in this transaction. */
-               if (!(lidp->lid_flags & XFS_LID_DIRTY))
-                       continue;
-
-               /* Skip items that do not have any vectors for writing */
-               lidp->lid_size = IOP_SIZE(lidp->lid_item);
-               if (!lidp->lid_size)
-                       continue;
-
-               new_lv = kmem_zalloc(sizeof(*new_lv) +
-                               lidp->lid_size * sizeof(struct xfs_log_iovec),
-                               KM_SLEEP);
-
-               /* The allocated iovec region lies beyond the log vector. */
-               new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
-               new_lv->lv_niovecs = lidp->lid_size;
-               new_lv->lv_item = lidp->lid_item;
-               if (!ret_lv)
-                       ret_lv = new_lv;
-               else
-                       lv->lv_next = new_lv;
-               lv = new_lv;
-       }
-
-       return ret_lv;
-}
-
-static int
-xfs_trans_commit_cil(
-       struct xfs_mount        *mp,
-       struct xfs_trans        *tp,
-       xfs_lsn_t               *commit_lsn,
-       int                     flags)
-{
-       struct xfs_log_vec      *log_vector;
-
-       /*
-        * Get each log item to allocate a vector structure for
-        * the log item to to pass to the log write code. The
-        * CIL commit code will format the vector and save it away.
-        */
-       log_vector = xfs_trans_alloc_log_vecs(tp);
-       if (!log_vector)
-               return ENOMEM;
-
-       xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags);
-
-       current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
-       xfs_trans_free(tp);
-       return 0;
-}
-
 /*
  * Commit the given transaction to the log.
  *
@@ -1845,17 +1379,16 @@ xfs_trans_commit(
                xfs_trans_apply_sb_deltas(tp);
        xfs_trans_apply_dquot_deltas(tp);
 
-       if (mp->m_flags & XFS_MOUNT_DELAYLOG)
-               error = xfs_trans_commit_cil(mp, tp, &commit_lsn, flags);
-       else
-               error = xfs_trans_commit_iclog(mp, tp, &commit_lsn, flags);
-
+       error = xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
        if (error == ENOMEM) {
                xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
                error = XFS_ERROR(EIO);
                goto out_unreserve;
        }
 
+       current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
+       xfs_trans_free(tp);
+
        /*
         * If the transaction needs to be synchronous, then force the
         * log out now and wait for it.
index 3ae713c0abd9a04b3964d3ff8a9305155cd3b97a..f6118703f20d0352ff4098837e354c36ffab94c3 100644 (file)
@@ -163,9 +163,8 @@ typedef struct xfs_trans_header {
  */
 struct xfs_log_item_desc {
        struct xfs_log_item     *lid_item;
-       ushort                  lid_size;
-       unsigned char           lid_flags;
        struct list_head        lid_trans;
+       unsigned char           lid_flags;
 };
 
 #define XFS_LID_DIRTY          0x1