These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / xfs / xfs_extfree_item.c
index cb7fe64..4aa0153 100644 (file)
@@ -46,28 +46,6 @@ xfs_efi_item_free(
                kmem_zone_free(xfs_efi_zone, efip);
 }
 
-/*
- * Freeing the efi requires that we remove it from the AIL if it has already
- * been placed there. However, the EFI may not yet have been placed in the AIL
- * when called by xfs_efi_release() from EFD processing due to the ordering of
- * committed vs unpin operations in bulk insert operations. Hence the reference
- * count to ensure only the last caller frees the EFI.
- */
-STATIC void
-__xfs_efi_release(
-       struct xfs_efi_log_item *efip)
-{
-       struct xfs_ail          *ailp = efip->efi_item.li_ailp;
-
-       if (atomic_dec_and_test(&efip->efi_refcount)) {
-               spin_lock(&ailp->xa_lock);
-               /* xfs_trans_ail_delete() drops the AIL lock. */
-               xfs_trans_ail_delete(ailp, &efip->efi_item,
-                                    SHUTDOWN_LOG_IO_ERROR);
-               xfs_efi_item_free(efip);
-       }
-}
-
 /*
  * This returns the number of iovecs needed to log the given efi item.
  * We only need 1 iovec for an efi item.  It just logs the efi_log_format
@@ -128,12 +106,12 @@ xfs_efi_item_pin(
 }
 
 /*
- * While EFIs cannot really be pinned, the unpin operation is the last place at
- * which the EFI is manipulated during a transaction.  If we are being asked to
- * remove the EFI it's because the transaction has been cancelled and by
- * definition that means the EFI cannot be in the AIL so remove it from the
- * transaction and free it.  Otherwise coordinate with xfs_efi_release()
- * to determine who gets to free the EFI.
+ * The unpin operation is the last place an EFI is manipulated in the log. It is
+ * either inserted in the AIL or aborted in the event of a log I/O error. In
+ * either case, the EFI transaction has been successfully committed to make it
+ * this far. Therefore, we expect whoever committed the EFI to either construct
+ * and commit the EFD or drop the EFD's reference in the event of error. Simply
+ * drop the log's EFI reference now that the log is done with it.
  */
 STATIC void
 xfs_efi_item_unpin(
@@ -141,15 +119,7 @@ xfs_efi_item_unpin(
        int                     remove)
 {
        struct xfs_efi_log_item *efip = EFI_ITEM(lip);
-
-       if (remove) {
-               ASSERT(!(lip->li_flags & XFS_LI_IN_AIL));
-               if (lip->li_desc)
-                       xfs_trans_del_item(lip);
-               xfs_efi_item_free(efip);
-               return;
-       }
-       __xfs_efi_release(efip);
+       xfs_efi_release(efip);
 }
 
 /*
@@ -167,6 +137,11 @@ xfs_efi_item_push(
        return XFS_ITEM_PINNED;
 }
 
+/*
+ * The EFI has been either committed or aborted if the transaction has been
+ * cancelled. If the transaction was cancelled, an EFD isn't going to be
+ * constructed and thus we free the EFI here directly.
+ */
 STATIC void
 xfs_efi_item_unlock(
        struct xfs_log_item     *lip)
@@ -239,7 +214,7 @@ xfs_efi_init(
 
        xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops);
        efip->efi_format.efi_nextents = nextents;
-       efip->efi_format.efi_id = (__psint_t)(void*)efip;
+       efip->efi_format.efi_id = (uintptr_t)(void *)efip;
        atomic_set(&efip->efi_next_extent, 0);
        atomic_set(&efip->efi_refcount, 2);
 
@@ -301,23 +276,19 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
 }
 
 /*
- * This is called by the efd item code below to release references to the given
- * efi item.  Each efd calls this with the number of extents that it has
- * logged, and when the sum of these reaches the total number of extents logged
- * by this efi item we can free the efi item.
+ * Freeing the efi requires that we remove it from the AIL if it has already
+ * been placed there. However, the EFI may not yet have been placed in the AIL
+ * when called by xfs_efi_release() from EFD processing due to the ordering of
+ * committed vs unpin operations in bulk insert operations. Hence the reference
+ * count to ensure only the last caller frees the EFI.
  */
 void
-xfs_efi_release(xfs_efi_log_item_t     *efip,
-               uint                    nextents)
+xfs_efi_release(
+       struct xfs_efi_log_item *efip)
 {
-       ASSERT(atomic_read(&efip->efi_next_extent) >= nextents);
-       if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) {
-               /* recovery needs us to drop the EFI reference, too */
-               if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags))
-                       __xfs_efi_release(efip);
-
-               __xfs_efi_release(efip);
-               /* efip may now have been freed, do not reference it again. */
+       if (atomic_dec_and_test(&efip->efi_refcount)) {
+               xfs_trans_ail_remove(&efip->efi_item, SHUTDOWN_LOG_IO_ERROR);
+               xfs_efi_item_free(efip);
        }
 }
 
@@ -415,20 +386,27 @@ xfs_efd_item_push(
        return XFS_ITEM_PINNED;
 }
 
+/*
+ * The EFD is either committed or aborted if the transaction is cancelled. If
+ * the transaction is cancelled, drop our reference to the EFI and free the EFD.
+ */
 STATIC void
 xfs_efd_item_unlock(
        struct xfs_log_item     *lip)
 {
-       if (lip->li_flags & XFS_LI_ABORTED)
-               xfs_efd_item_free(EFD_ITEM(lip));
+       struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
+
+       if (lip->li_flags & XFS_LI_ABORTED) {
+               xfs_efi_release(efdp->efd_efip);
+               xfs_efd_item_free(efdp);
+       }
 }
 
 /*
- * When the efd item is committed to disk, all we need to do
- * is delete our reference to our partner efi item and then
- * free ourselves.  Since we're freeing ourselves we must
- * return -1 to keep the transaction code from further referencing
- * this item.
+ * When the efd item is committed to disk, all we need to do is delete our
+ * reference to our partner efi item and then free ourselves. Since we're
+ * freeing ourselves we must return -1 to keep the transaction code from further
+ * referencing this item.
  */
 STATIC xfs_lsn_t
 xfs_efd_item_committed(
@@ -438,13 +416,14 @@ xfs_efd_item_committed(
        struct xfs_efd_log_item *efdp = EFD_ITEM(lip);
 
        /*
-        * If we got a log I/O error, it's always the case that the LR with the
-        * EFI got unpinned and freed before the EFD got aborted.
+        * Drop the EFI reference regardless of whether the EFD has been
+        * aborted. Once the EFD transaction is constructed, it is the sole
+        * responsibility of the EFD to release the EFI (even if the EFI is
+        * aborted due to log I/O error).
         */
-       if (!(lip->li_flags & XFS_LI_ABORTED))
-               xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
-
+       xfs_efi_release(efdp->efd_efip);
        xfs_efd_item_free(efdp);
+
        return (xfs_lsn_t)-1;
 }