]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/xfs/xfs_rtalloc.c
Merge tag 'dmaengine-fix-5.1-rc3' of git://git.infradead.org/users/vkoul/slave-dma
[linux.git] / fs / xfs / xfs_rtalloc.c
index 926ed314ffba1d78b88cbf80d2d9cdeef3cc0fe3..ac0fcdad0c4edee1f3085aef91641f2f0a2030ca 100644 (file)
@@ -64,8 +64,12 @@ xfs_rtany_summary(
        int             log;            /* loop counter, log2 of ext. size */
        xfs_suminfo_t   sum;            /* summary data */
 
+       /* There are no extents at levels < m_rsum_cache[bbno]. */
+       if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno])
+               low = mp->m_rsum_cache[bbno];
+
        /*
-        * Loop over logs of extent sizes.  Order is irrelevant.
+        * Loop over logs of extent sizes.
         */
        for (log = low; log <= high; log++) {
                /*
@@ -80,13 +84,17 @@ xfs_rtany_summary(
                 */
                if (sum) {
                        *stat = 1;
-                       return 0;
+                       goto out;
                }
        }
        /*
         * Found nothing, return failure.
         */
        *stat = 0;
+out:
+       /* There were no extents at levels < log. */
+       if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno])
+               mp->m_rsum_cache[bbno] = log;
        return 0;
 }
 
@@ -853,6 +861,21 @@ xfs_growfs_rt_alloc(
        return error;
 }
 
+static void
+xfs_alloc_rsum_cache(
+       xfs_mount_t     *mp,            /* file system mount structure */
+       xfs_extlen_t    rbmblocks)      /* number of rt bitmap blocks */
+{
+       /*
+        * The rsum cache is initialized to all zeroes, which is trivially a
+        * lower bound on the minimum level with any free extents. We can
+        * continue without the cache if it couldn't be allocated.
+        */
+       mp->m_rsum_cache = kmem_zalloc_large(rbmblocks, KM_SLEEP);
+       if (!mp->m_rsum_cache)
+               xfs_warn(mp, "could not allocate realtime summary cache");
+}
+
 /*
  * Visible (exported) functions.
  */
@@ -881,6 +904,7 @@ xfs_growfs_rt(
        xfs_extlen_t    rsumblocks;     /* current number of rt summary blks */
        xfs_sb_t        *sbp;           /* old superblock */
        xfs_fsblock_t   sumbno;         /* summary block number */
+       uint8_t         *rsum_cache;    /* old summary cache */
 
        sbp = &mp->m_sb;
        /*
@@ -937,6 +961,11 @@ xfs_growfs_rt(
        error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
        if (error)
                return error;
+
+       rsum_cache = mp->m_rsum_cache;
+       if (nrbmblocks != sbp->sb_rbmblocks)
+               xfs_alloc_rsum_cache(mp, nrbmblocks);
+
        /*
         * Allocate a new (fake) mount/sb.
         */
@@ -1062,6 +1091,20 @@ xfs_growfs_rt(
         */
        kmem_free(nmp);
 
+       /*
+        * If we had to allocate a new rsum_cache, we either need to free the
+        * old one (if we succeeded) or free the new one and restore the old one
+        * (if there was an error).
+        */
+       if (rsum_cache != mp->m_rsum_cache) {
+               if (error) {
+                       kmem_free(mp->m_rsum_cache);
+                       mp->m_rsum_cache = rsum_cache;
+               } else {
+                       kmem_free(rsum_cache);
+               }
+       }
+
        return error;
 }
 
@@ -1187,8 +1230,8 @@ xfs_rtmount_init(
 }
 
 /*
- * Get the bitmap and summary inodes into the mount structure
- * at mount time.
+ * Get the bitmap and summary inodes and the summary cache into the mount
+ * structure at mount time.
  */
 int                                    /* error */
 xfs_rtmount_inodes(
@@ -1198,19 +1241,18 @@ xfs_rtmount_inodes(
        xfs_sb_t        *sbp;
 
        sbp = &mp->m_sb;
-       if (sbp->sb_rbmino == NULLFSINO)
-               return 0;
        error = xfs_iget(mp, NULL, sbp->sb_rbmino, 0, 0, &mp->m_rbmip);
        if (error)
                return error;
        ASSERT(mp->m_rbmip != NULL);
-       ASSERT(sbp->sb_rsumino != NULLFSINO);
+
        error = xfs_iget(mp, NULL, sbp->sb_rsumino, 0, 0, &mp->m_rsumip);
        if (error) {
                xfs_irele(mp->m_rbmip);
                return error;
        }
        ASSERT(mp->m_rsumip != NULL);
+       xfs_alloc_rsum_cache(mp, sbp->sb_rbmblocks);
        return 0;
 }
 
@@ -1218,6 +1260,7 @@ void
 xfs_rtunmount_inodes(
        struct xfs_mount        *mp)
 {
+       kmem_free(mp->m_rsum_cache);
        if (mp->m_rbmip)
                xfs_irele(mp->m_rbmip);
        if (mp->m_rsumip)