Merge tag 'xfs-6.7-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[sfrench/cifs-2.6.git] / fs / xfs / xfs_bmap_util.c
index 40e0a1f1f7530cba2193655b0be5ff661bfb107e..731260a5af6db43d06849d32a7384a90188f4031 100644 (file)
@@ -28,6 +28,7 @@
 #include "xfs_icache.h"
 #include "xfs_iomap.h"
 #include "xfs_reflink.h"
+#include "xfs_rtbitmap.h"
 
 /* Kernel only BMAP related definitions and functions */
 
@@ -75,28 +76,28 @@ xfs_bmap_rtalloc(
 {
        struct xfs_mount        *mp = ap->ip->i_mount;
        xfs_fileoff_t           orig_offset = ap->offset;
-       xfs_rtblock_t           rtb;
-       xfs_extlen_t            prod = 0;  /* product factor for allocators */
+       xfs_rtxnum_t            rtx;
+       xfs_rtxlen_t            prod = 0;  /* product factor for allocators */
        xfs_extlen_t            mod = 0;   /* product factor for allocators */
-       xfs_extlen_t            ralen = 0; /* realtime allocation length */
+       xfs_rtxlen_t            ralen = 0; /* realtime allocation length */
        xfs_extlen_t            align;     /* minimum allocation alignment */
        xfs_extlen_t            orig_length = ap->length;
        xfs_extlen_t            minlen = mp->m_sb.sb_rextsize;
-       xfs_extlen_t            raminlen;
+       xfs_rtxlen_t            raminlen;
        bool                    rtlocked = false;
        bool                    ignore_locality = false;
        int                     error;
 
        align = xfs_get_extsz_hint(ap->ip);
 retry:
-       prod = align / mp->m_sb.sb_rextsize;
+       prod = xfs_extlen_to_rtxlen(mp, align);
        error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
                                        align, 1, ap->eof, 0,
                                        ap->conv, &ap->offset, &ap->length);
        if (error)
                return error;
        ASSERT(ap->length);
-       ASSERT(ap->length % mp->m_sb.sb_rextsize == 0);
+       ASSERT(xfs_extlen_to_rtxmod(mp, ap->length) == 0);
 
        /*
         * If we shifted the file offset downward to satisfy an extent size
@@ -116,17 +117,14 @@ retry:
                prod = 1;
        /*
         * Set ralen to be the actual requested length in rtextents.
-        */
-       ralen = ap->length / mp->m_sb.sb_rextsize;
-       /*
+        *
         * If the old value was close enough to XFS_BMBT_MAX_EXTLEN that
         * we rounded up to it, cut it back so it's valid again.
         * Note that if it's a really large request (bigger than
         * XFS_BMBT_MAX_EXTLEN), we don't hear about that number, and can't
         * adjust the starting point to match it.
         */
-       if (ralen * mp->m_sb.sb_rextsize >= XFS_MAX_BMBT_EXTLEN)
-               ralen = XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize;
+       ralen = xfs_extlen_to_rtxlen(mp, min(ap->length, XFS_MAX_BMBT_EXTLEN));
 
        /*
         * Lock out modifications to both the RT bitmap and summary inodes
@@ -144,12 +142,10 @@ retry:
         * pick an extent that will space things out in the rt area.
         */
        if (ap->eof && ap->offset == 0) {
-               xfs_rtblock_t rtx; /* realtime extent no */
-
                error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
                if (error)
                        return error;
-               ap->blkno = rtx * mp->m_sb.sb_rextsize;
+               ap->blkno = xfs_rtx_to_rtb(mp, rtx);
        } else {
                ap->blkno = 0;
        }
@@ -160,20 +156,18 @@ retry:
         * Realtime allocation, done through xfs_rtallocate_extent.
         */
        if (ignore_locality)
-               ap->blkno = 0;
+               rtx = 0;
        else
-               do_div(ap->blkno, mp->m_sb.sb_rextsize);
-       rtb = ap->blkno;
-       ap->length = ralen;
-       raminlen = max_t(xfs_extlen_t, 1, minlen / mp->m_sb.sb_rextsize);
-       error = xfs_rtallocate_extent(ap->tp, ap->blkno, raminlen, ap->length,
-                       &ralen, ap->wasdel, prod, &rtb);
+               rtx = xfs_rtb_to_rtx(mp, ap->blkno);
+       raminlen = max_t(xfs_rtxlen_t, 1, xfs_extlen_to_rtxlen(mp, minlen));
+       error = xfs_rtallocate_extent(ap->tp, rtx, raminlen, ralen, &ralen,
+                       ap->wasdel, prod, &rtx);
        if (error)
                return error;
 
-       if (rtb != NULLRTBLOCK) {
-               ap->blkno = rtb * mp->m_sb.sb_rextsize;
-               ap->length = ralen * mp->m_sb.sb_rextsize;
+       if (rtx != NULLRTEXTNO) {
+               ap->blkno = xfs_rtx_to_rtb(mp, rtx);
+               ap->length = xfs_rtxlen_to_extlen(mp, ralen);
                ap->ip->i_nblocks += ap->length;
                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
                if (ap->wasdel)
@@ -690,7 +684,7 @@ xfs_can_free_eofblocks(
         */
        end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip));
        if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1)
-               end_fsb = roundup_64(end_fsb, mp->m_sb.sb_rextsize);
+               end_fsb = xfs_rtb_roundup_rtx(mp, end_fsb);
        last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
        if (last_fsb <= end_fsb)
                return false;
@@ -780,12 +774,10 @@ xfs_alloc_file_space(
 {
        xfs_mount_t             *mp = ip->i_mount;
        xfs_off_t               count;
-       xfs_filblks_t           allocated_fsb;
        xfs_filblks_t           allocatesize_fsb;
        xfs_extlen_t            extsz, temp;
        xfs_fileoff_t           startoffset_fsb;
        xfs_fileoff_t           endoffset_fsb;
-       int                     nimaps;
        int                     rt;
        xfs_trans_t             *tp;
        xfs_bmbt_irec_t         imaps[1], *imapp;
@@ -808,7 +800,6 @@ xfs_alloc_file_space(
 
        count = len;
        imapp = &imaps[0];
-       nimaps = 1;
        startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
        endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
        allocatesize_fsb = endoffset_fsb - startoffset_fsb;
@@ -819,6 +810,7 @@ xfs_alloc_file_space(
        while (allocatesize_fsb && !error) {
                xfs_fileoff_t   s, e;
                unsigned int    dblocks, rblocks, resblks;
+               int             nimaps = 1;
 
                /*
                 * Determine space reservations for data/realtime.
@@ -884,15 +876,19 @@ xfs_alloc_file_space(
                if (error)
                        break;
 
-               allocated_fsb = imapp->br_blockcount;
-
-               if (nimaps == 0) {
-                       error = -ENOSPC;
-                       break;
+               /*
+                * If the allocator cannot find a single free extent large
+                * enough to cover the start block of the requested range,
+                * xfs_bmapi_write will return 0 but leave *nimaps set to 0.
+                *
+                * In that case we simply need to keep looping with the same
+                * startoffset_fsb so that one of the following allocations
+                * will eventually reach the requested range.
+                */
+               if (nimaps) {
+                       startoffset_fsb += imapp->br_blockcount;
+                       allocatesize_fsb -= imapp->br_blockcount;
                }
-
-               startoffset_fsb += allocated_fsb;
-               allocatesize_fsb -= allocated_fsb;
        }
 
        return error;
@@ -989,10 +985,8 @@ xfs_free_file_space(
 
        /* We can only free complete realtime extents. */
        if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
-               startoffset_fsb = roundup_64(startoffset_fsb,
-                                            mp->m_sb.sb_rextsize);
-               endoffset_fsb = rounddown_64(endoffset_fsb,
-                                            mp->m_sb.sb_rextsize);
+               startoffset_fsb = xfs_rtb_roundup_rtx(mp, startoffset_fsb);
+               endoffset_fsb = xfs_rtb_rounddown_rtx(mp, endoffset_fsb);
        }
 
        /*