Merge git://git.infradead.org/battery-2.6
[pandora-kernel.git] / fs / xfs / xfs_trans.c
index f6d956b..f80a067 100644 (file)
@@ -1350,7 +1350,7 @@ xfs_trans_fill_vecs(
  * 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.
  */
-void
+static void
 xfs_trans_item_committed(
        struct xfs_log_item     *lip,
        xfs_lsn_t               commit_lsn,
@@ -1425,6 +1425,83 @@ xfs_trans_committed(
        xfs_trans_free(tp);
 }
 
+static inline void
+xfs_log_item_batch_insert(
+       struct xfs_ail          *ailp,
+       struct xfs_log_item     **log_items,
+       int                     nr_items,
+       xfs_lsn_t               commit_lsn)
+{
+       int     i;
+
+       spin_lock(&ailp->xa_lock);
+       /* xfs_trans_ail_update_bulk drops ailp->xa_lock */
+       xfs_trans_ail_update_bulk(ailp, log_items, nr_items, commit_lsn);
+
+       for (i = 0; i < nr_items; i++)
+               IOP_UNPIN(log_items[i], 0);
+}
+
+/*
+ * Bulk operation version of xfs_trans_committed that takes a log vector of
+ * items to insert into the AIL. This uses bulk AIL insertion techniques to
+ * minimise lock traffic.
+ */
+void
+xfs_trans_committed_bulk(
+       struct xfs_ail          *ailp,
+       struct xfs_log_vec      *log_vector,
+       xfs_lsn_t               commit_lsn,
+       int                     aborted)
+{
+#define LOG_ITEM_BATCH_SIZE    32
+       struct xfs_log_item     *log_items[LOG_ITEM_BATCH_SIZE];
+       struct xfs_log_vec      *lv;
+       int                     i = 0;
+
+       /* unpin all the log items */
+       for (lv = log_vector; lv; lv = lv->lv_next ) {
+               struct xfs_log_item     *lip = lv->lv_item;
+               xfs_lsn_t               item_lsn;
+
+               if (aborted)
+                       lip->li_flags |= XFS_LI_ABORTED;
+               item_lsn = IOP_COMMITTED(lip, commit_lsn);
+
+               /* item_lsn of -1 means the item was freed */
+               if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0)
+                       continue;
+
+               if (item_lsn != commit_lsn) {
+
+                       /*
+                        * Not a bulk update option due to unusual item_lsn.
+                        * Push into AIL immediately, rechecking the lsn once
+                        * we have the ail lock. Then unpin the item.
+                        */
+                       spin_lock(&ailp->xa_lock);
+                       if (XFS_LSN_CMP(item_lsn, lip->li_lsn) > 0)
+                               xfs_trans_ail_update(ailp, lip, item_lsn);
+                       else
+                               spin_unlock(&ailp->xa_lock);
+                       IOP_UNPIN(lip, 0);
+                       continue;
+               }
+
+               /* Item is a candidate for bulk AIL insert.  */
+               log_items[i++] = lv->lv_item;
+               if (i >= LOG_ITEM_BATCH_SIZE) {
+                       xfs_log_item_batch_insert(ailp, log_items,
+                                       LOG_ITEM_BATCH_SIZE, commit_lsn);
+                       i = 0;
+               }
+       }
+
+       /* make sure we insert the remainder! */
+       if (i)
+               xfs_log_item_batch_insert(ailp, log_items, i, commit_lsn);
+}
+
 /*
  * Called from the trans_commit code when we notice that
  * the filesystem is in the middle of a forced shutdown.