Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetoot...
[cascardo/linux.git] / fs / xfs / libxfs / xfs_trans_resv.c
index 68cb1e7..b456cca 100644 (file)
@@ -63,6 +63,33 @@ xfs_calc_buf_res(
        return nbufs * (size + xfs_buf_log_overhead());
 }
 
+/*
+ * Per-extent log reservation for the btree changes involved in freeing or
+ * allocating an extent.  In classic XFS there were two trees that will be
+ * modified (bnobt + cntbt).  With rmap enabled, there are three trees
+ * (rmapbt).  With reflink, there are four trees (refcountbt).  The number of
+ * blocks reserved is based on the formula:
+ *
+ * num trees * ((2 blocks/level * max depth) - 1)
+ *
+ * Keep in mind that max depth is calculated separately for each type of tree.
+ */
+uint
+xfs_allocfree_log_count(
+       struct xfs_mount *mp,
+       uint            num_ops)
+{
+       uint            blocks;
+
+       blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1);
+       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+               blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1);
+       if (xfs_sb_version_hasreflink(&mp->m_sb))
+               blocks += num_ops * (2 * mp->m_refc_maxlevels - 1);
+
+       return blocks;
+}
+
 /*
  * Logging inodes is really tricksy. They are logged in memory format,
  * which means that what we write into the log doesn't directly translate into
@@ -126,7 +153,7 @@ xfs_calc_inode_res(
  */
 STATIC uint
 xfs_calc_finobt_res(
-       struct xfs_mount        *mp,
+       struct xfs_mount        *mp,
        int                     alloc,
        int                     modify)
 {
@@ -137,7 +164,7 @@ xfs_calc_finobt_res(
 
        res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1));
        if (alloc)
-               res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), 
+               res += xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                        XFS_FSB_TO_B(mp, 1));
        if (modify)
                res += (uint)XFS_FSB_TO_B(mp, 1);
@@ -153,9 +180,9 @@ xfs_calc_finobt_res(
  * item logged to try to account for the overhead of the transaction mechanism.
  *
  * Note:  Most of the reservations underestimate the number of allocation
- * groups into which they could free extents in the xfs_bmap_finish() call.
+ * groups into which they could free extents in the xfs_defer_finish() call.
  * This is because the number in the worst case is quite high and quite
- * unusual.  In order to fix this we need to change xfs_bmap_finish() to free
+ * unusual.  In order to fix this we need to change xfs_defer_finish() to free
  * extents in only a single AG at a time.  This will require changes to the
  * EFI code as well, however, so that the EFI for the extents not freed is
  * logged again in each transaction.  See SGI PV #261917.
@@ -188,10 +215,10 @@ xfs_calc_write_reservation(
                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
                                      XFS_FSB_TO_B(mp, 1)) +
                     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -217,10 +244,10 @@ xfs_calc_itruncate_reservation(
                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
                                      XFS_FSB_TO_B(mp, 1)) +
                    xfs_calc_buf_res(5, 0) +
-                   xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+                   xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                     XFS_FSB_TO_B(mp, 1)) +
                    xfs_calc_buf_res(2 + mp->m_ialloc_blks +
                                     mp->m_in_maxlevels, 0)));
@@ -247,7 +274,7 @@ xfs_calc_rename_reservation(
                     xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 3),
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -286,7 +313,7 @@ xfs_calc_link_reservation(
                     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -324,7 +351,7 @@ xfs_calc_remove_reservation(
                     xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
                                      XFS_FSB_TO_B(mp, 1))),
                    (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -371,7 +398,7 @@ xfs_calc_create_resv_alloc(
                mp->m_sb.sb_sectsize +
                xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1));
 }
 
@@ -399,7 +426,7 @@ xfs_calc_icreate_resv_alloc(
        return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) +
                mp->m_sb.sb_sectsize +
                xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_finobt_res(mp, 0, 0);
 }
@@ -483,7 +510,7 @@ xfs_calc_ifree_reservation(
                xfs_calc_buf_res(1, 0) +
                xfs_calc_buf_res(2 + mp->m_ialloc_blks +
                                 mp->m_in_maxlevels, 0) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_finobt_res(mp, 0, 1);
 }
@@ -513,7 +540,7 @@ xfs_calc_growdata_reservation(
        struct xfs_mount        *mp)
 {
        return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1));
 }
 
@@ -535,7 +562,7 @@ xfs_calc_growrtalloc_reservation(
                xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
                                 XFS_FSB_TO_B(mp, 1)) +
                xfs_calc_inode_res(mp, 1) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1));
 }
 
@@ -611,7 +638,7 @@ xfs_calc_addafork_reservation(
                xfs_calc_buf_res(1, mp->m_dir_geo->blksize) +
                xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1,
                                 XFS_FSB_TO_B(mp, 1)) +
-               xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1),
+               xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1),
                                 XFS_FSB_TO_B(mp, 1));
 }
 
@@ -634,7 +661,7 @@ xfs_calc_attrinval_reservation(
                    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
                                     XFS_FSB_TO_B(mp, 1))),
                   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
-                   xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4),
+                   xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
                                     XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -701,7 +728,7 @@ xfs_calc_attrrm_reservation(
                                        XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) +
                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)),
                    (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2),
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
                                      XFS_FSB_TO_B(mp, 1))));
 }
 
@@ -785,11 +812,18 @@ xfs_trans_resv_calc(
         * require a permanent reservation on space.
         */
        resp->tr_write.tr_logres = xfs_calc_write_reservation(mp);
-       resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
+       if (xfs_sb_version_hasreflink(&mp->m_sb))
+               resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
+       else
+               resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT;
        resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
        resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp);
-       resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
+       if (xfs_sb_version_hasreflink(&mp->m_sb))
+               resp->tr_itruncate.tr_logcount =
+                               XFS_ITRUNCATE_LOG_COUNT_REFLINK;
+       else
+               resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT;
        resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
        resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp);
@@ -846,7 +880,10 @@ xfs_trans_resv_calc(
        resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
        resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp);
-       resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
+       if (xfs_sb_version_hasreflink(&mp->m_sb))
+               resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK;
+       else
+               resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT;
        resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES;
 
        /*