Commit 34f76326 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-6.7-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs updates from Chandan Babu:

 - Realtime device subsystem:
    - Cleanup usage of xfs_rtblock_t and xfs_fsblock_t data types
    - Replace open coded conversions between rt blocks and rt extents
      with calls to static inline helpers
    - Replace open coded realtime geometry compuation and macros with
      helper functions
    - CPU usage optimizations for realtime allocator
    - Misc bug fixes associated with Realtime device

 - Allow read operations to execute while an FICLONE ioctl is being
   serviced

 - Misc bug fixes:
    - Alert user when xfs_droplink() encounters an inode with a link
      count of zero
    - Handle the case where the allocator could return zero extents when
      servicing an fallocate request

* tag 'xfs-6.7-merge-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: (40 commits)
  xfs: allow read IO and FICLONE to run concurrently
  xfs: handle nimaps=0 from xfs_bmapi_write in xfs_alloc_file_space
  xfs: introduce protection for drop nlink
  xfs: don't look for end of extent further than necessary in xfs_rtallocate_extent_near()
  xfs: don't try redundant allocations in xfs_rtallocate_extent_near()
  xfs: limit maxlen based on available space in xfs_rtallocate_extent_near()
  xfs: return maximum free size from xfs_rtany_summary()
  xfs: invert the realtime summary cache
  xfs: simplify rt bitmap/summary block accessor functions
  xfs: simplify xfs_rtbuf_get calling conventions
  xfs: cache last bitmap block in realtime allocator
  xfs: use accessor functions for summary info words
  xfs: consolidate realtime allocation arguments
  xfs: create helpers for rtsummary block/wordcount computations
  xfs: use accessor functions for bitmap words
  xfs: create helpers for rtbitmap block/wordcount computations
  xfs: create a helper to handle logging parts of rt bitmap/summary blocks
  xfs: convert rt summary macros to helpers
  xfs: convert open-coded xfs_rtword_t pointer accesses to helper
  xfs: remove XFS_BLOCKWSIZE and XFS_BLOCKWMASK macros
  ...
parents 6d795e2a 14a53798
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_bmap_btree.h" #include "xfs_bmap_btree.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_errortag.h" #include "xfs_errortag.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_quota.h" #include "xfs_quota.h"
...@@ -2989,7 +2989,7 @@ xfs_bmap_extsize_align( ...@@ -2989,7 +2989,7 @@ xfs_bmap_extsize_align(
* If realtime, and the result isn't a multiple of the realtime * If realtime, and the result isn't a multiple of the realtime
* extent size we need to remove blocks until it is. * extent size we need to remove blocks until it is.
*/ */
if (rt && (temp = (align_alen % mp->m_sb.sb_rextsize))) { if (rt && (temp = xfs_extlen_to_rtxmod(mp, align_alen))) {
/* /*
* We're not covering the original request, or * We're not covering the original request, or
* we won't be able to once we fix the length. * we won't be able to once we fix the length.
...@@ -3016,7 +3016,7 @@ xfs_bmap_extsize_align( ...@@ -3016,7 +3016,7 @@ xfs_bmap_extsize_align(
else { else {
align_alen -= orig_off - align_off; align_alen -= orig_off - align_off;
align_off = orig_off; align_off = orig_off;
align_alen -= align_alen % mp->m_sb.sb_rextsize; align_alen -= xfs_extlen_to_rtxmod(mp, align_alen);
} }
/* /*
* Result doesn't cover the request, fail it. * Result doesn't cover the request, fail it.
...@@ -4826,12 +4826,8 @@ xfs_bmap_del_extent_delay( ...@@ -4826,12 +4826,8 @@ xfs_bmap_del_extent_delay(
ASSERT(got->br_startoff <= del->br_startoff); ASSERT(got->br_startoff <= del->br_startoff);
ASSERT(got_endoff >= del_endoff); ASSERT(got_endoff >= del_endoff);
if (isrt) { if (isrt)
uint64_t rtexts = XFS_FSB_TO_B(mp, del->br_blockcount); xfs_mod_frextents(mp, xfs_rtb_to_rtx(mp, del->br_blockcount));
do_div(rtexts, mp->m_sb.sb_rextsize);
xfs_mod_frextents(mp, rtexts);
}
/* /*
* Update the inode delalloc counter now and wait to update the * Update the inode delalloc counter now and wait to update the
...@@ -5057,33 +5053,20 @@ xfs_bmap_del_extent_real( ...@@ -5057,33 +5053,20 @@ xfs_bmap_del_extent_real(
flags = XFS_ILOG_CORE; flags = XFS_ILOG_CORE;
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) { if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
xfs_filblks_t len;
xfs_extlen_t mod;
len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
&mod);
ASSERT(mod == 0);
if (!(bflags & XFS_BMAPI_REMAP)) { if (!(bflags & XFS_BMAPI_REMAP)) {
xfs_fsblock_t bno; error = xfs_rtfree_blocks(tp, del->br_startblock,
del->br_blockcount);
bno = div_u64_rem(del->br_startblock,
mp->m_sb.sb_rextsize, &mod);
ASSERT(mod == 0);
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
if (error) if (error)
goto done; goto done;
} }
do_fx = 0; do_fx = 0;
nblks = len * mp->m_sb.sb_rextsize;
qfield = XFS_TRANS_DQ_RTBCOUNT; qfield = XFS_TRANS_DQ_RTBCOUNT;
} else { } else {
do_fx = 1; do_fx = 1;
nblks = del->br_blockcount;
qfield = XFS_TRANS_DQ_BCOUNT; qfield = XFS_TRANS_DQ_BCOUNT;
} }
nblks = del->br_blockcount;
del_endblock = del->br_startblock + del->br_blockcount; del_endblock = del->br_startblock + del->br_blockcount;
if (cur) { if (cur) {
...@@ -5289,7 +5272,6 @@ __xfs_bunmapi( ...@@ -5289,7 +5272,6 @@ __xfs_bunmapi(
int tmp_logflags; /* partial logging flags */ int tmp_logflags; /* partial logging flags */
int wasdel; /* was a delayed alloc extent */ int wasdel; /* was a delayed alloc extent */
int whichfork; /* data or attribute fork */ int whichfork; /* data or attribute fork */
xfs_fsblock_t sum;
xfs_filblks_t len = *rlen; /* length to unmap in file */ xfs_filblks_t len = *rlen; /* length to unmap in file */
xfs_fileoff_t end; xfs_fileoff_t end;
struct xfs_iext_cursor icur; struct xfs_iext_cursor icur;
...@@ -5384,8 +5366,8 @@ __xfs_bunmapi( ...@@ -5384,8 +5366,8 @@ __xfs_bunmapi(
if (!isrt) if (!isrt)
goto delete; goto delete;
sum = del.br_startblock + del.br_blockcount; mod = xfs_rtb_to_rtxoff(mp,
div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod); del.br_startblock + del.br_blockcount);
if (mod) { if (mod) {
/* /*
* Realtime extent not lined up at the end. * Realtime extent not lined up at the end.
...@@ -5432,7 +5414,8 @@ __xfs_bunmapi( ...@@ -5432,7 +5414,8 @@ __xfs_bunmapi(
goto error0; goto error0;
goto nodelete; goto nodelete;
} }
div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
mod = xfs_rtb_to_rtxoff(mp, del.br_startblock);
if (mod) { if (mod) {
xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; xfs_extlen_t off = mp->m_sb.sb_rextsize - mod;
...@@ -6209,7 +6192,7 @@ xfs_bmap_validate_extent( ...@@ -6209,7 +6192,7 @@ xfs_bmap_validate_extent(
return __this_address; return __this_address;
if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) { if (XFS_IS_REALTIME_INODE(ip) && whichfork == XFS_DATA_FORK) {
if (!xfs_verify_rtext(mp, irec->br_startblock, if (!xfs_verify_rtbext(mp, irec->br_startblock,
irec->br_blockcount)) irec->br_blockcount))
return __this_address; return __this_address;
} else { } else {
......
...@@ -98,7 +98,7 @@ typedef struct xfs_sb { ...@@ -98,7 +98,7 @@ typedef struct xfs_sb {
uint32_t sb_blocksize; /* logical block size, bytes */ uint32_t sb_blocksize; /* logical block size, bytes */
xfs_rfsblock_t sb_dblocks; /* number of data blocks */ xfs_rfsblock_t sb_dblocks; /* number of data blocks */
xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */
xfs_rtblock_t sb_rextents; /* number of realtime extents */ xfs_rtbxlen_t sb_rextents; /* number of realtime extents */
uuid_t sb_uuid; /* user-visible file system unique id */ uuid_t sb_uuid; /* user-visible file system unique id */
xfs_fsblock_t sb_logstart; /* starting block of log if internal */ xfs_fsblock_t sb_logstart; /* starting block of log if internal */
xfs_ino_t sb_rootino; /* root inode number */ xfs_ino_t sb_rootino; /* root inode number */
...@@ -690,6 +690,22 @@ struct xfs_agfl { ...@@ -690,6 +690,22 @@ struct xfs_agfl {
ASSERT(xfs_daddr_to_agno(mp, d) == \ ASSERT(xfs_daddr_to_agno(mp, d) == \
xfs_daddr_to_agno(mp, (d) + (len) - 1))) xfs_daddr_to_agno(mp, (d) + (len) - 1)))
/*
* Realtime bitmap information is accessed by the word, which is currently
* stored in host-endian format.
*/
union xfs_rtword_raw {
__u32 old;
};
/*
* Realtime summary counts are accessed by the word, which is currently
* stored in host-endian format.
*/
union xfs_suminfo_raw {
__u32 old;
};
/* /*
* XFS Timestamps * XFS Timestamps
* ============== * ==============
...@@ -1142,24 +1158,10 @@ static inline bool xfs_dinode_has_large_extent_counts( ...@@ -1142,24 +1158,10 @@ static inline bool xfs_dinode_has_large_extent_counts(
#define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize) #define XFS_BLOCKSIZE(mp) ((mp)->m_sb.sb_blocksize)
#define XFS_BLOCKMASK(mp) ((mp)->m_blockmask) #define XFS_BLOCKMASK(mp) ((mp)->m_blockmask)
#define XFS_BLOCKWSIZE(mp) ((mp)->m_blockwsize)
#define XFS_BLOCKWMASK(mp) ((mp)->m_blockwmask)
/* /*
* RT Summary and bit manipulation macros. * RT bit manipulation macros.
*/ */
#define XFS_SUMOFFS(mp,ls,bb) ((int)((ls) * (mp)->m_sb.sb_rbmblocks + (bb)))
#define XFS_SUMOFFSTOBLOCK(mp,s) \
(((s) * (uint)sizeof(xfs_suminfo_t)) >> (mp)->m_sb.sb_blocklog)
#define XFS_SUMPTR(mp,bp,so) \
((xfs_suminfo_t *)((bp)->b_addr + \
(((so) * (uint)sizeof(xfs_suminfo_t)) & XFS_BLOCKMASK(mp))))
#define XFS_BITTOBLOCK(mp,bi) ((bi) >> (mp)->m_blkbit_log)
#define XFS_BLOCKTOBIT(mp,bb) ((bb) << (mp)->m_blkbit_log)
#define XFS_BITTOWORD(mp,bi) \
((int)(((bi) >> XFS_NBWORDLOG) & XFS_BLOCKWMASK(mp)))
#define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b)) #define XFS_RTMIN(a,b) ((a) < (b) ? (a) : (b))
#define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b)) #define XFS_RTMAX(a,b) ((a) > (b) ? (a) : (b))
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rtalloc.h" #include "xfs_rtalloc.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_rtbitmap.h"
/* /*
* Realtime allocator bitmap functions shared with userspace. * Realtime allocator bitmap functions shared with userspace.
...@@ -46,25 +47,69 @@ const struct xfs_buf_ops xfs_rtbuf_ops = { ...@@ -46,25 +47,69 @@ const struct xfs_buf_ops xfs_rtbuf_ops = {
.verify_write = xfs_rtbuf_verify_write, .verify_write = xfs_rtbuf_verify_write,
}; };
/* Release cached rt bitmap and summary buffers. */
void
xfs_rtbuf_cache_relse(
struct xfs_rtalloc_args *args)
{
if (args->rbmbp) {
xfs_trans_brelse(args->tp, args->rbmbp);
args->rbmbp = NULL;
args->rbmoff = NULLFILEOFF;
}
if (args->sumbp) {
xfs_trans_brelse(args->tp, args->sumbp);
args->sumbp = NULL;
args->sumoff = NULLFILEOFF;
}
}
/* /*
* Get a buffer for the bitmap or summary file block specified. * Get a buffer for the bitmap or summary file block specified.
* The buffer is returned read and locked. * The buffer is returned read and locked.
*/ */
int int
xfs_rtbuf_get( xfs_rtbuf_get(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_fileoff_t block, /* block number in bitmap or summary */
xfs_rtblock_t block, /* block number in bitmap or summary */ int issum) /* is summary not bitmap */
int issum, /* is summary not bitmap */
struct xfs_buf **bpp) /* output: buffer for the block */
{ {
struct xfs_mount *mp = args->mp;
struct xfs_buf **cbpp; /* cached block buffer */
xfs_fileoff_t *coffp; /* cached block number */
struct xfs_buf *bp; /* block buffer, result */ struct xfs_buf *bp; /* block buffer, result */
xfs_inode_t *ip; /* bitmap or summary inode */ struct xfs_inode *ip; /* bitmap or summary inode */
xfs_bmbt_irec_t map; struct xfs_bmbt_irec map;
enum xfs_blft type;
int nmap = 1; int nmap = 1;
int error; /* error value */ int error;
ip = issum ? mp->m_rsumip : mp->m_rbmip; if (issum) {
cbpp = &args->sumbp;
coffp = &args->sumoff;
ip = mp->m_rsumip;
type = XFS_BLFT_RTSUMMARY_BUF;
} else {
cbpp = &args->rbmbp;
coffp = &args->rbmoff;
ip = mp->m_rbmip;
type = XFS_BLFT_RTBITMAP_BUF;
}
/*
* If we have a cached buffer, and the block number matches, use that.
*/
if (*cbpp && *coffp == block)
return 0;
/*
* Otherwise we have to have to get the buffer. If there was an old
* one, get rid of it first.
*/
if (*cbpp) {
xfs_trans_brelse(args->tp, *cbpp);
*cbpp = NULL;
}
error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0); error = xfs_bmapi_read(ip, block, 1, &map, &nmap, 0);
if (error) if (error)
...@@ -74,15 +119,15 @@ xfs_rtbuf_get( ...@@ -74,15 +119,15 @@ xfs_rtbuf_get(
return -EFSCORRUPTED; return -EFSCORRUPTED;
ASSERT(map.br_startblock != NULLFSBLOCK); ASSERT(map.br_startblock != NULLFSBLOCK);
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, error = xfs_trans_read_buf(mp, args->tp, mp->m_ddev_targp,
XFS_FSB_TO_DADDR(mp, map.br_startblock), XFS_FSB_TO_DADDR(mp, map.br_startblock),
mp->m_bsize, 0, &bp, &xfs_rtbuf_ops); mp->m_bsize, 0, &bp, &xfs_rtbuf_ops);
if (error) if (error)
return error; return error;
xfs_trans_buf_set_type(tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF xfs_trans_buf_set_type(args->tp, bp, type);
: XFS_BLFT_RTBITMAP_BUF); *cbpp = bp;
*bpp = bp; *coffp = block;
return 0; return 0;
} }
...@@ -92,47 +137,44 @@ xfs_rtbuf_get( ...@@ -92,47 +137,44 @@ xfs_rtbuf_get(
*/ */
int int
xfs_rtfind_back( xfs_rtfind_back(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to look at */
xfs_rtblock_t start, /* starting block to look at */ xfs_rtxnum_t limit, /* last rtext to look at */
xfs_rtblock_t limit, /* last block to look at */ xfs_rtxnum_t *rtx) /* out: start rtext found */
xfs_rtblock_t *rtblock) /* out: start block found */
{ {
xfs_rtword_t *b; /* current word in buffer */ struct xfs_mount *mp = args->mp;
int bit; /* bit number in the word */ int bit; /* bit number in the word */
xfs_rtblock_t block; /* bitmap block number */ xfs_fileoff_t block; /* bitmap block number */
struct xfs_buf *bp; /* buf for the block */
xfs_rtword_t *bufp; /* starting word in buffer */
int error; /* error value */ int error; /* error value */
xfs_rtblock_t firstbit; /* first useful bit in the word */ xfs_rtxnum_t firstbit; /* first useful bit in the word */
xfs_rtblock_t i; /* current bit number rel. to start */ xfs_rtxnum_t i; /* current bit number rel. to start */
xfs_rtblock_t len; /* length of inspected area */ xfs_rtxnum_t len; /* length of inspected area */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t want; /* mask for "good" values */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
int word; /* word number in the buffer */ xfs_rtword_t incore;
unsigned int word; /* word number in the buffer */
/* /*
* Compute and read in starting bitmap block for starting block. * Compute and read in starting bitmap block for starting block.
*/ */
block = XFS_BITTOBLOCK(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
bufp = bp->b_addr;
/* /*
* Get the first word's index & point to it. * Get the first word's index & point to it.
*/ */
word = XFS_BITTOWORD(mp, start); word = xfs_rtx_to_rbmword(mp, start);
b = &bufp[word];
bit = (int)(start & (XFS_NBWORD - 1)); bit = (int)(start & (XFS_NBWORD - 1));
len = start - limit + 1; len = start - limit + 1;
/* /*
* Compute match value, based on the bit at start: if 1 (free) * Compute match value, based on the bit at start: if 1 (free)
* then all-ones, else all-zeroes. * then all-ones, else all-zeroes.
*/ */
want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; incore = xfs_rtbitmap_getword(args, word);
want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
/* /*
* If the starting position is not word-aligned, deal with the * If the starting position is not word-aligned, deal with the
* partial word. * partial word.
...@@ -149,13 +191,12 @@ xfs_rtfind_back( ...@@ -149,13 +191,12 @@ xfs_rtfind_back(
* Calculate the difference between the value there * Calculate the difference between the value there
* and what we're looking for. * and what we're looking for.
*/ */
if ((wdiff = (*b ^ want) & mask)) { if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different. Mark where we are and return. * Different. Mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i = bit - XFS_RTHIBIT(wdiff); i = bit - XFS_RTHIBIT(wdiff);
*rtblock = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
} }
i = bit - firstbit + 1; i = bit - firstbit + 1;
...@@ -167,19 +208,11 @@ xfs_rtfind_back( ...@@ -167,19 +208,11 @@ xfs_rtfind_back(
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, --block);
error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error)
if (error) {
return error; return error;
}
bufp = bp->b_addr; word = mp->m_blockwsize - 1;
word = XFS_BLOCKWMASK(mp);
b = &bufp[word];
} else {
/*
* Go on to the previous word in the buffer.
*/
b--;
} }
} else { } else {
/* /*
...@@ -195,13 +228,13 @@ xfs_rtfind_back( ...@@ -195,13 +228,13 @@ xfs_rtfind_back(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = *b ^ want)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ want)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtblock = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
} }
i += XFS_NBWORD; i += XFS_NBWORD;
...@@ -213,19 +246,11 @@ xfs_rtfind_back( ...@@ -213,19 +246,11 @@ xfs_rtfind_back(
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, --block);
error = xfs_rtbuf_get(mp, tp, --block, 0, &bp); if (error)
if (error) {
return error; return error;
}
bufp = bp->b_addr; word = mp->m_blockwsize - 1;
word = XFS_BLOCKWMASK(mp);
b = &bufp[word];
} else {
/*
* Go on to the previous word in the buffer.
*/
b--;
} }
} }
/* /*
...@@ -242,13 +267,13 @@ xfs_rtfind_back( ...@@ -242,13 +267,13 @@ xfs_rtfind_back(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = (*b ^ want) & mask)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff); i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtblock = start - i + 1; *rtx = start - i + 1;
return 0; return 0;
} else } else
i = len; i = len;
...@@ -256,8 +281,7 @@ xfs_rtfind_back( ...@@ -256,8 +281,7 @@ xfs_rtfind_back(
/* /*
* No match, return that we scanned the whole area. * No match, return that we scanned the whole area.
*/ */
xfs_trans_brelse(tp, bp); *rtx = start - i + 1;
*rtblock = start - i + 1;
return 0; return 0;
} }
...@@ -267,47 +291,44 @@ xfs_rtfind_back( ...@@ -267,47 +291,44 @@ xfs_rtfind_back(
*/ */
int int
xfs_rtfind_forw( xfs_rtfind_forw(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to look at */
xfs_rtblock_t start, /* starting block to look at */ xfs_rtxnum_t limit, /* last rtext to look at */
xfs_rtblock_t limit, /* last block to look at */ xfs_rtxnum_t *rtx) /* out: start rtext found */
xfs_rtblock_t *rtblock) /* out: start block found */
{ {
xfs_rtword_t *b; /* current word in buffer */ struct xfs_mount *mp = args->mp;
int bit; /* bit number in the word */ int bit; /* bit number in the word */
xfs_rtblock_t block; /* bitmap block number */ xfs_fileoff_t block; /* bitmap block number */
struct xfs_buf *bp; /* buf for the block */ int error;
xfs_rtword_t *bufp; /* starting word in buffer */ xfs_rtxnum_t i; /* current bit number rel. to start */
int error; /* error value */ xfs_rtxnum_t lastbit;/* last useful bit in the word */
xfs_rtblock_t i; /* current bit number rel. to start */ xfs_rtxnum_t len; /* length of inspected area */
xfs_rtblock_t lastbit; /* last useful bit in the word */
xfs_rtblock_t len; /* length of inspected area */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t want; /* mask for "good" values */ xfs_rtword_t want; /* mask for "good" values */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
int word; /* word number in the buffer */ xfs_rtword_t incore;
unsigned int word; /* word number in the buffer */
/* /*
* Compute and read in starting bitmap block for starting block. * Compute and read in starting bitmap block for starting block.
*/ */
block = XFS_BITTOBLOCK(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
bufp = bp->b_addr;
/* /*
* Get the first word's index & point to it. * Get the first word's index & point to it.
*/ */
word = XFS_BITTOWORD(mp, start); word = xfs_rtx_to_rbmword(mp, start);
b = &bufp[word];
bit = (int)(start & (XFS_NBWORD - 1)); bit = (int)(start & (XFS_NBWORD - 1));
len = limit - start + 1; len = limit - start + 1;
/* /*
* Compute match value, based on the bit at start: if 1 (free) * Compute match value, based on the bit at start: if 1 (free)
* then all-ones, else all-zeroes. * then all-ones, else all-zeroes.
*/ */
want = (*b & ((xfs_rtword_t)1 << bit)) ? -1 : 0; incore = xfs_rtbitmap_getword(args, word);
want = (incore & ((xfs_rtword_t)1 << bit)) ? -1 : 0;
/* /*
* If the starting position is not word-aligned, deal with the * If the starting position is not word-aligned, deal with the
* partial word. * partial word.
...@@ -323,13 +344,12 @@ xfs_rtfind_forw( ...@@ -323,13 +344,12 @@ xfs_rtfind_forw(
* Calculate the difference between the value there * Calculate the difference between the value there
* and what we're looking for. * and what we're looking for.
*/ */
if ((wdiff = (*b ^ want) & mask)) { if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different. Mark where we are and return. * Different. Mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i = XFS_RTLOBIT(wdiff) - bit; i = XFS_RTLOBIT(wdiff) - bit;
*rtblock = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
} }
i = lastbit - bit; i = lastbit - bit;
...@@ -337,22 +357,15 @@ xfs_rtfind_forw( ...@@ -337,22 +357,15 @@ xfs_rtfind_forw(
* Go on to next block if that's where the next word is * Go on to next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* If done with this block, get the previous one. * If done with this block, get the previous one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
b = bufp = bp->b_addr;
word = 0; word = 0;
} else {
/*
* Go on to the previous word in the buffer.
*/
b++;
} }
} else { } else {
/* /*
...@@ -368,13 +381,13 @@ xfs_rtfind_forw( ...@@ -368,13 +381,13 @@ xfs_rtfind_forw(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = *b ^ want)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ want)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*rtblock = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
} }
i += XFS_NBWORD; i += XFS_NBWORD;
...@@ -382,22 +395,15 @@ xfs_rtfind_forw( ...@@ -382,22 +395,15 @@ xfs_rtfind_forw(
* Go on to next block if that's where the next word is * Go on to next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
b = bufp = bp->b_addr;
word = 0; word = 0;
} else {
/*
* Go on to the next word in the buffer.
*/
b++;
} }
} }
/* /*
...@@ -412,13 +418,13 @@ xfs_rtfind_forw( ...@@ -412,13 +418,13 @@ xfs_rtfind_forw(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = (*b ^ want) & mask)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ want) & mask)) {
/* /*
* Different, mark where we are and return. * Different, mark where we are and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*rtblock = start + i - 1; *rtx = start + i - 1;
return 0; return 0;
} else } else
i = len; i = len;
...@@ -426,11 +432,25 @@ xfs_rtfind_forw( ...@@ -426,11 +432,25 @@ xfs_rtfind_forw(
/* /*
* No match, return that we scanned the whole area. * No match, return that we scanned the whole area.
*/ */
xfs_trans_brelse(tp, bp); *rtx = start + i - 1;
*rtblock = start + i - 1;
return 0; return 0;
} }
/* Log rtsummary counter at @infoword. */
static inline void
xfs_trans_log_rtsummary(
struct xfs_rtalloc_args *args,
unsigned int infoword)
{
struct xfs_buf *bp = args->sumbp;
size_t first, last;
first = (void *)xfs_rsumblock_infoptr(args, infoword) - bp->b_addr;
last = first + sizeof(xfs_suminfo_t) - 1;
xfs_trans_log_buf(args->tp, bp, first, last);
}
/* /*
* Read and/or modify the summary information for a given extent size, * Read and/or modify the summary information for a given extent size,
* bitmap block combination. * bitmap block combination.
...@@ -442,86 +462,77 @@ xfs_rtfind_forw( ...@@ -442,86 +462,77 @@ xfs_rtfind_forw(
*/ */
int int
xfs_rtmodify_summary_int( xfs_rtmodify_summary_int(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */
int log, /* log2 of extent size */ int log, /* log2 of extent size */
xfs_rtblock_t bbno, /* bitmap block number */ xfs_fileoff_t bbno, /* bitmap block number */
int delta, /* change to make to summary info */ int delta, /* change to make to summary info */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_suminfo_t *sum) /* out: summary info for this block */ xfs_suminfo_t *sum) /* out: summary info for this block */
{ {
struct xfs_buf *bp; /* buffer for the summary block */ struct xfs_mount *mp = args->mp;
int error; /* error value */ int error;
xfs_fsblock_t sb; /* summary fsblock */ xfs_fileoff_t sb; /* summary fsblock */
int so; /* index into the summary file */ xfs_rtsumoff_t so; /* index into the summary file */
xfs_suminfo_t *sp; /* pointer to returned data */ unsigned int infoword;
/* /*
* Compute entry number in the summary file. * Compute entry number in the summary file.
*/ */
so = XFS_SUMOFFS(mp, log, bbno); so = xfs_rtsumoffs(mp, log, bbno);
/* /*
* Compute the block number in the summary file. * Compute the block number in the summary file.
*/ */
sb = XFS_SUMOFFSTOBLOCK(mp, so); sb = xfs_rtsumoffs_to_block(mp, so);
/*
* If we have an old buffer, and the block number matches, use that. error = xfs_rtsummary_read_buf(args, sb);
*/ if (error)
if (*rbpp && *rsb == sb)
bp = *rbpp;
/*
* Otherwise we have to get the buffer.
*/
else {
/*
* If there was an old one, get rid of it first.
*/
if (*rbpp)
xfs_trans_brelse(tp, *rbpp);
error = xfs_rtbuf_get(mp, tp, sb, 1, &bp);
if (error) {
return error; return error;
}
/*
* Remember this buffer and block for the next call.
*/
*rbpp = bp;
*rsb = sb;
}
/* /*
* Point to the summary information, modify/log it, and/or copy it out. * Point to the summary information, modify/log it, and/or copy it out.
*/ */
sp = XFS_SUMPTR(mp, bp, so); infoword = xfs_rtsumoffs_to_infoword(mp, so);
if (delta) { if (delta) {
uint first = (uint)((char *)sp - (char *)bp->b_addr); xfs_suminfo_t val = xfs_suminfo_add(args, infoword, delta);
*sp += delta;
if (mp->m_rsum_cache) { if (mp->m_rsum_cache) {
if (*sp == 0 && log == mp->m_rsum_cache[bbno]) if (val == 0 && log + 1 == mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno]++;
if (*sp != 0 && log < mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log; mp->m_rsum_cache[bbno] = log;
if (val != 0 && log >= mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log + 1;
} }
xfs_trans_log_buf(tp, bp, first, first + sizeof(*sp) - 1); xfs_trans_log_rtsummary(args, infoword);
}
if (sum) if (sum)
*sum = *sp; *sum = val;
} else if (sum) {
*sum = xfs_suminfo_get(args, infoword);
}
return 0; return 0;
} }
int int
xfs_rtmodify_summary( xfs_rtmodify_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */
int log, /* log2 of extent size */ int log, /* log2 of extent size */
xfs_rtblock_t bbno, /* bitmap block number */ xfs_fileoff_t bbno, /* bitmap block number */
int delta, /* change to make to summary info */ int delta) /* in/out: summary block number */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ {
xfs_fsblock_t *rsb) /* in/out: summary block number */ return xfs_rtmodify_summary_int(args, log, bbno, delta, NULL);
}
/* Log rtbitmap block from the word @from to the byte before @next. */
static inline void
xfs_trans_log_rtbitmap(
struct xfs_rtalloc_args *args,
unsigned int from,
unsigned int next)
{ {
return xfs_rtmodify_summary_int(mp, tp, log, bbno, struct xfs_buf *bp = args->rbmbp;
delta, rbpp, rsb, NULL); size_t first, last;
first = (void *)xfs_rbmblock_wordptr(args, from) - bp->b_addr;
last = ((void *)xfs_rbmblock_wordptr(args, next) - 1) - bp->b_addr;
xfs_trans_log_buf(args->tp, bp, first, last);
} }
/* /*
...@@ -530,41 +541,37 @@ xfs_rtmodify_summary( ...@@ -530,41 +541,37 @@ xfs_rtmodify_summary(
*/ */
int int
xfs_rtmodify_range( xfs_rtmodify_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to modify */
xfs_rtblock_t start, /* starting block to modify */ xfs_rtxlen_t len, /* length of extent to modify */
xfs_extlen_t len, /* length of extent to modify */
int val) /* 1 for free, 0 for allocated */ int val) /* 1 for free, 0 for allocated */
{ {
xfs_rtword_t *b; /* current word in buffer */ struct xfs_mount *mp = args->mp;
int bit; /* bit number in the word */ int bit; /* bit number in the word */
xfs_rtblock_t block; /* bitmap block number */ xfs_fileoff_t block; /* bitmap block number */
struct xfs_buf *bp; /* buf for the block */ int error;
xfs_rtword_t *bufp; /* starting word in buffer */
int error; /* error value */
xfs_rtword_t *first; /* first used word in the buffer */
int i; /* current bit number rel. to start */ int i; /* current bit number rel. to start */
int lastbit; /* last useful bit in word */ int lastbit; /* last useful bit in word */
xfs_rtword_t mask; /* mask o frelevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
int word; /* word number in the buffer */ xfs_rtword_t incore;
unsigned int firstword; /* first word used in the buffer */
unsigned int word; /* word number in the buffer */
/* /*
* Compute starting bitmap block number. * Compute starting bitmap block number.
*/ */
block = XFS_BITTOBLOCK(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
/* /*
* Read the bitmap block, and point to its data. * Read the bitmap block, and point to its data.
*/ */
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
bufp = bp->b_addr;
/* /*
* Compute the starting word's address, and starting bit. * Compute the starting word's address, and starting bit.
*/ */
word = XFS_BITTOWORD(mp, start); firstword = word = xfs_rtx_to_rbmword(mp, start);
first = b = &bufp[word];
bit = (int)(start & (XFS_NBWORD - 1)); bit = (int)(start & (XFS_NBWORD - 1));
/* /*
* 0 (allocated) => all zeroes; 1 (free) => all ones. * 0 (allocated) => all zeroes; 1 (free) => all ones.
...@@ -583,34 +590,28 @@ xfs_rtmodify_range( ...@@ -583,34 +590,28 @@ xfs_rtmodify_range(
/* /*
* Set/clear the active bits. * Set/clear the active bits.
*/ */
incore = xfs_rtbitmap_getword(args, word);
if (val) if (val)
*b |= mask; incore |= mask;
else else
*b &= ~mask; incore &= ~mask;
xfs_rtbitmap_setword(args, word, incore);
i = lastbit - bit; i = lastbit - bit;
/* /*
* Go on to the next block if that's where the next word is * Go on to the next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* Log the changed part of this block. * Log the changed part of this block.
* Get the next one. * Get the next one.
*/ */
xfs_trans_log_buf(tp, bp, xfs_trans_log_rtbitmap(args, firstword, word);
(uint)((char *)first - (char *)bufp), error = xfs_rtbitmap_read_buf(args, ++block);
(uint)((char *)b - (char *)bufp)); if (error)
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
if (error) {
return error; return error;
}
first = b = bufp = bp->b_addr; firstword = word = 0;
word = 0;
} else {
/*
* Go on to the next word in the buffer
*/
b++;
} }
} else { } else {
/* /*
...@@ -626,31 +627,23 @@ xfs_rtmodify_range( ...@@ -626,31 +627,23 @@ xfs_rtmodify_range(
/* /*
* Set the word value correctly. * Set the word value correctly.
*/ */
*b = val; xfs_rtbitmap_setword(args, word, val);
i += XFS_NBWORD; i += XFS_NBWORD;
/* /*
* Go on to the next block if that's where the next word is * Go on to the next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* Log the changed part of this block. * Log the changed part of this block.
* Get the next one. * Get the next one.
*/ */
xfs_trans_log_buf(tp, bp, xfs_trans_log_rtbitmap(args, firstword, word);
(uint)((char *)first - (char *)bufp), error = xfs_rtbitmap_read_buf(args, ++block);
(uint)((char *)b - (char *)bufp)); if (error)
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp);
if (error) {
return error; return error;
}
first = b = bufp = bp->b_addr; firstword = word = 0;
word = 0;
} else {
/*
* Go on to the next word in the buffer
*/
b++;
} }
} }
/* /*
...@@ -665,18 +658,19 @@ xfs_rtmodify_range( ...@@ -665,18 +658,19 @@ xfs_rtmodify_range(
/* /*
* Set/clear the active bits. * Set/clear the active bits.
*/ */
incore = xfs_rtbitmap_getword(args, word);
if (val) if (val)
*b |= mask; incore |= mask;
else else
*b &= ~mask; incore &= ~mask;
b++; xfs_rtbitmap_setword(args, word, incore);
word++;
} }
/* /*
* Log any remaining changed bytes. * Log any remaining changed bytes.
*/ */
if (b > first) if (word > firstword)
xfs_trans_log_buf(tp, bp, (uint)((char *)first - (char *)bufp), xfs_trans_log_rtbitmap(args, firstword, word);
(uint)((char *)b - (char *)bufp - 1));
return 0; return 0;
} }
...@@ -686,23 +680,21 @@ xfs_rtmodify_range( ...@@ -686,23 +680,21 @@ xfs_rtmodify_range(
*/ */
int int
xfs_rtfree_range( xfs_rtfree_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext to free */
xfs_rtblock_t start, /* starting block to free */ xfs_rtxlen_t len) /* in/out: summary block number */
xfs_extlen_t len, /* length to free */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fsblock_t *rsb) /* in/out: summary block number */
{ {
xfs_rtblock_t end; /* end of the freed extent */ struct xfs_mount *mp = args->mp;
xfs_rtxnum_t end; /* end of the freed extent */
int error; /* error value */ int error; /* error value */
xfs_rtblock_t postblock; /* first block freed > end */ xfs_rtxnum_t postblock; /* first rtext freed > end */
xfs_rtblock_t preblock; /* first block freed < start */ xfs_rtxnum_t preblock; /* first rtext freed < start */
end = start + len - 1; end = start + len - 1;
/* /*
* Modify the bitmap to mark this extent freed. * Modify the bitmap to mark this extent freed.
*/ */
error = xfs_rtmodify_range(mp, tp, start, len, 1); error = xfs_rtmodify_range(args, start, len, 1);
if (error) { if (error) {
return error; return error;
} }
...@@ -711,14 +703,14 @@ xfs_rtfree_range( ...@@ -711,14 +703,14 @@ xfs_rtfree_range(
* We need to find the beginning and end of the extent so we can * We need to find the beginning and end of the extent so we can
* properly update the summary. * properly update the summary.
*/ */
error = xfs_rtfind_back(mp, tp, start, 0, &preblock); error = xfs_rtfind_back(args, start, 0, &preblock);
if (error) { if (error) {
return error; return error;
} }
/* /*
* Find the next allocated block (end of allocated extent). * Find the next allocated block (end of allocated extent).
*/ */
error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, error = xfs_rtfind_forw(args, end, mp->m_sb.sb_rextents - 1,
&postblock); &postblock);
if (error) if (error)
return error; return error;
...@@ -727,9 +719,9 @@ xfs_rtfree_range( ...@@ -727,9 +719,9 @@ xfs_rtfree_range(
* old extent, add summary data for them to be allocated. * old extent, add summary data for them to be allocated.
*/ */
if (preblock < start) { if (preblock < start) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(start - preblock), XFS_RTBLOCKLOG(start - preblock),
XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -739,9 +731,9 @@ xfs_rtfree_range( ...@@ -739,9 +731,9 @@ xfs_rtfree_range(
* old extent, add summary data for them to be allocated. * old extent, add summary data for them to be allocated.
*/ */
if (postblock > end) { if (postblock > end) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock - end), XFS_RTBLOCKLOG(postblock - end),
XFS_BITTOBLOCK(mp, end + 1), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, end + 1), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -750,10 +742,9 @@ xfs_rtfree_range( ...@@ -750,10 +742,9 @@ xfs_rtfree_range(
* Increment the summary information corresponding to the entire * Increment the summary information corresponding to the entire
* (new) free extent. * (new) free extent.
*/ */
error = xfs_rtmodify_summary(mp, tp, return xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_RTBLOCKLOG(postblock + 1 - preblock),
XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), 1);
return error;
} }
/* /*
...@@ -762,43 +753,39 @@ xfs_rtfree_range( ...@@ -762,43 +753,39 @@ xfs_rtfree_range(
*/ */
int int
xfs_rtcheck_range( xfs_rtcheck_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number of extent */
xfs_rtblock_t start, /* starting block number of extent */ xfs_rtxlen_t len, /* length of extent */
xfs_extlen_t len, /* length of extent */
int val, /* 1 for free, 0 for allocated */ int val, /* 1 for free, 0 for allocated */
xfs_rtblock_t *new, /* out: first block not matching */ xfs_rtxnum_t *new, /* out: first rtext not matching */
int *stat) /* out: 1 for matches, 0 for not */ int *stat) /* out: 1 for matches, 0 for not */
{ {
xfs_rtword_t *b; /* current word in buffer */ struct xfs_mount *mp = args->mp;
int bit; /* bit number in the word */ int bit; /* bit number in the word */
xfs_rtblock_t block; /* bitmap block number */ xfs_fileoff_t block; /* bitmap block number */
struct xfs_buf *bp; /* buf for the block */ int error;
xfs_rtword_t *bufp; /* starting word in buffer */ xfs_rtxnum_t i; /* current bit number rel. to start */
int error; /* error value */ xfs_rtxnum_t lastbit; /* last useful bit in word */
xfs_rtblock_t i; /* current bit number rel. to start */
xfs_rtblock_t lastbit; /* last useful bit in word */
xfs_rtword_t mask; /* mask of relevant bits for value */ xfs_rtword_t mask; /* mask of relevant bits for value */
xfs_rtword_t wdiff; /* difference from wanted value */ xfs_rtword_t wdiff; /* difference from wanted value */
int word; /* word number in the buffer */ xfs_rtword_t incore;
unsigned int word; /* word number in the buffer */
/* /*
* Compute starting bitmap block number * Compute starting bitmap block number
*/ */
block = XFS_BITTOBLOCK(mp, start); block = xfs_rtx_to_rbmblock(mp, start);
/* /*
* Read the bitmap block. * Read the bitmap block.
*/ */
error = xfs_rtbuf_get(mp, tp, block, 0, &bp); error = xfs_rtbitmap_read_buf(args, block);
if (error) { if (error)
return error; return error;
}
bufp = bp->b_addr;
/* /*
* Compute the starting word's address, and starting bit. * Compute the starting word's address, and starting bit.
*/ */
word = XFS_BITTOWORD(mp, start); word = xfs_rtx_to_rbmword(mp, start);
b = &bufp[word];
bit = (int)(start & (XFS_NBWORD - 1)); bit = (int)(start & (XFS_NBWORD - 1));
/* /*
* 0 (allocated) => all zero's; 1 (free) => all one's. * 0 (allocated) => all zero's; 1 (free) => all one's.
...@@ -820,11 +807,11 @@ xfs_rtcheck_range( ...@@ -820,11 +807,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = (*b ^ val) & mask)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ val) & mask)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i = XFS_RTLOBIT(wdiff) - bit; i = XFS_RTLOBIT(wdiff) - bit;
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -835,22 +822,15 @@ xfs_rtcheck_range( ...@@ -835,22 +822,15 @@ xfs_rtcheck_range(
* Go on to next block if that's where the next word is * Go on to next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
b = bufp = bp->b_addr;
word = 0; word = 0;
} else {
/*
* Go on to the next word in the buffer.
*/
b++;
} }
} else { } else {
/* /*
...@@ -866,11 +846,11 @@ xfs_rtcheck_range( ...@@ -866,11 +846,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = *b ^ val)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = incore ^ val)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -881,22 +861,15 @@ xfs_rtcheck_range( ...@@ -881,22 +861,15 @@ xfs_rtcheck_range(
* Go on to next block if that's where the next word is * Go on to next block if that's where the next word is
* and we need the next word. * and we need the next word.
*/ */
if (++word == XFS_BLOCKWSIZE(mp) && i < len) { if (++word == mp->m_blockwsize && i < len) {
/* /*
* If done with this block, get the next one. * If done with this block, get the next one.
*/ */
xfs_trans_brelse(tp, bp); error = xfs_rtbitmap_read_buf(args, ++block);
error = xfs_rtbuf_get(mp, tp, ++block, 0, &bp); if (error)
if (error) {
return error; return error;
}
b = bufp = bp->b_addr;
word = 0; word = 0;
} else {
/*
* Go on to the next word in the buffer.
*/
b++;
} }
} }
/* /*
...@@ -911,11 +884,11 @@ xfs_rtcheck_range( ...@@ -911,11 +884,11 @@ xfs_rtcheck_range(
/* /*
* Compute difference between actual and desired value. * Compute difference between actual and desired value.
*/ */
if ((wdiff = (*b ^ val) & mask)) { incore = xfs_rtbitmap_getword(args, word);
if ((wdiff = (incore ^ val) & mask)) {
/* /*
* Different, compute first wrong bit and return. * Different, compute first wrong bit and return.
*/ */
xfs_trans_brelse(tp, bp);
i += XFS_RTLOBIT(wdiff); i += XFS_RTLOBIT(wdiff);
*new = start + i; *new = start + i;
*stat = 0; *stat = 0;
...@@ -926,7 +899,6 @@ xfs_rtcheck_range( ...@@ -926,7 +899,6 @@ xfs_rtcheck_range(
/* /*
* Successful, return. * Successful, return.
*/ */
xfs_trans_brelse(tp, bp);
*new = start + i; *new = start + i;
*stat = 1; *stat = 1;
return 0; return 0;
...@@ -936,58 +908,57 @@ xfs_rtcheck_range( ...@@ -936,58 +908,57 @@ xfs_rtcheck_range(
/* /*
* Check that the given extent (block range) is allocated already. * Check that the given extent (block range) is allocated already.
*/ */
STATIC int /* error */ STATIC int
xfs_rtcheck_alloc_range( xfs_rtcheck_alloc_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number of extent */
xfs_rtblock_t bno, /* starting block number of extent */ xfs_rtxlen_t len) /* length of extent */
xfs_extlen_t len) /* length of extent */
{ {
xfs_rtblock_t new; /* dummy for xfs_rtcheck_range */ xfs_rtxnum_t new; /* dummy for xfs_rtcheck_range */
int stat; int stat;
int error; int error;
error = xfs_rtcheck_range(mp, tp, bno, len, 0, &new, &stat); error = xfs_rtcheck_range(args, start, len, 0, &new, &stat);
if (error) if (error)
return error; return error;
ASSERT(stat); ASSERT(stat);
return 0; return 0;
} }
#else #else
#define xfs_rtcheck_alloc_range(m,t,b,l) (0) #define xfs_rtcheck_alloc_range(a,b,l) (0)
#endif #endif
/* /*
* Free an extent in the realtime subvolume. Length is expressed in * Free an extent in the realtime subvolume. Length is expressed in
* realtime extents, as is the block number. * realtime extents, as is the block number.
*/ */
int /* error */ int
xfs_rtfree_extent( xfs_rtfree_extent(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_rtblock_t bno, /* starting block number to free */ xfs_rtxnum_t start, /* starting rtext number to free */
xfs_extlen_t len) /* length of extent freed */ xfs_rtxlen_t len) /* length of extent freed */
{ {
int error; /* error value */ struct xfs_mount *mp = tp->t_mountp;
xfs_mount_t *mp; /* file system mount structure */ struct xfs_rtalloc_args args = {
xfs_fsblock_t sb; /* summary file block number */ .mp = mp,
struct xfs_buf *sumbp = NULL; /* summary file block buffer */ .tp = tp,
};
int error;
struct timespec64 atime; struct timespec64 atime;
mp = tp->t_mountp;
ASSERT(mp->m_rbmip->i_itemp != NULL); ASSERT(mp->m_rbmip->i_itemp != NULL);
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
error = xfs_rtcheck_alloc_range(mp, tp, bno, len); error = xfs_rtcheck_alloc_range(&args, start, len);
if (error) if (error)
return error; return error;
/* /*
* Free the range of realtime blocks. * Free the range of realtime blocks.
*/ */
error = xfs_rtfree_range(mp, tp, bno, len, &sumbp, &sb); error = xfs_rtfree_range(&args, start, len);
if (error) { if (error)
return error; goto out;
}
/* /*
* Mark more blocks free in the superblock. * Mark more blocks free in the superblock.
*/ */
...@@ -1002,11 +973,47 @@ xfs_rtfree_extent( ...@@ -1002,11 +973,47 @@ xfs_rtfree_extent(
mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
atime = inode_get_atime(VFS_I(mp->m_rbmip)); atime = inode_get_atime(VFS_I(mp->m_rbmip));
*((uint64_t *)&atime) = 0; atime.tv_sec = 0;
inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime); inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime);
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
} }
return 0; error = 0;
out:
xfs_rtbuf_cache_relse(&args);
return error;
}
/*
* Free some blocks in the realtime subvolume. rtbno and rtlen are in units of
* rt blocks, not rt extents; must be aligned to the rt extent size; and rtlen
* cannot exceed XFS_MAX_BMBT_EXTLEN.
*/
int
xfs_rtfree_blocks(
struct xfs_trans *tp,
xfs_fsblock_t rtbno,
xfs_filblks_t rtlen)
{
struct xfs_mount *mp = tp->t_mountp;
xfs_rtxnum_t start;
xfs_filblks_t len;
xfs_extlen_t mod;
ASSERT(rtlen <= XFS_MAX_BMBT_EXTLEN);
len = xfs_rtb_to_rtxrem(mp, rtlen, &mod);
if (mod) {
ASSERT(mod == 0);
return -EIO;
}
start = xfs_rtb_to_rtxrem(mp, rtbno, &mod);
if (mod) {
ASSERT(mod == 0);
return -EIO;
}
return xfs_rtfree_extent(tp, start, len);
} }
/* Find all the free records within a given range. */ /* Find all the free records within a given range. */
...@@ -1019,10 +1026,14 @@ xfs_rtalloc_query_range( ...@@ -1019,10 +1026,14 @@ xfs_rtalloc_query_range(
xfs_rtalloc_query_range_fn fn, xfs_rtalloc_query_range_fn fn,
void *priv) void *priv)
{ {
struct xfs_rtalloc_args args = {
.mp = mp,
.tp = tp,
};
struct xfs_rtalloc_rec rec; struct xfs_rtalloc_rec rec;
xfs_rtblock_t rtstart; xfs_rtxnum_t rtstart;
xfs_rtblock_t rtend; xfs_rtxnum_t rtend;
xfs_rtblock_t high_key; xfs_rtxnum_t high_key;
int is_free; int is_free;
int error = 0; int error = 0;
...@@ -1038,13 +1049,13 @@ xfs_rtalloc_query_range( ...@@ -1038,13 +1049,13 @@ xfs_rtalloc_query_range(
rtstart = low_rec->ar_startext; rtstart = low_rec->ar_startext;
while (rtstart <= high_key) { while (rtstart <= high_key) {
/* Is the first block free? */ /* Is the first block free? */
error = xfs_rtcheck_range(mp, tp, rtstart, 1, 1, &rtend, error = xfs_rtcheck_range(&args, rtstart, 1, 1, &rtend,
&is_free); &is_free);
if (error) if (error)
break; break;
/* How long does the extent go for? */ /* How long does the extent go for? */
error = xfs_rtfind_forw(mp, tp, rtstart, high_key, &rtend); error = xfs_rtfind_forw(&args, rtstart, high_key, &rtend);
if (error) if (error)
break; break;
...@@ -1060,6 +1071,7 @@ xfs_rtalloc_query_range( ...@@ -1060,6 +1071,7 @@ xfs_rtalloc_query_range(
rtstart = rtend + 1; rtstart = rtend + 1;
} }
xfs_rtbuf_cache_relse(&args);
return error; return error;
} }
...@@ -1085,18 +1097,79 @@ int ...@@ -1085,18 +1097,79 @@ int
xfs_rtalloc_extent_is_free( xfs_rtalloc_extent_is_free(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_rtxnum_t start,
xfs_extlen_t len, xfs_rtxlen_t len,
bool *is_free) bool *is_free)
{ {
xfs_rtblock_t end; struct xfs_rtalloc_args args = {
.mp = mp,
.tp = tp,
};
xfs_rtxnum_t end;
int matches; int matches;
int error; int error;
error = xfs_rtcheck_range(mp, tp, start, len, 1, &end, &matches); error = xfs_rtcheck_range(&args, start, len, 1, &end, &matches);
xfs_rtbuf_cache_relse(&args);
if (error) if (error)
return error; return error;
*is_free = matches; *is_free = matches;
return 0; return 0;
} }
/*
* Compute the number of rtbitmap blocks needed to track the given number of rt
* extents.
*/
xfs_filblks_t
xfs_rtbitmap_blockcount(
struct xfs_mount *mp,
xfs_rtbxlen_t rtextents)
{
return howmany_64(rtextents, NBBY * mp->m_sb.sb_blocksize);
}
/*
* Compute the number of rtbitmap words needed to populate every block of a
* bitmap that is large enough to track the given number of rt extents.
*/
unsigned long long
xfs_rtbitmap_wordcount(
struct xfs_mount *mp,
xfs_rtbxlen_t rtextents)
{
xfs_filblks_t blocks;
blocks = xfs_rtbitmap_blockcount(mp, rtextents);
return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
}
/* Compute the number of rtsummary blocks needed to track the given rt space. */
xfs_filblks_t
xfs_rtsummary_blockcount(
struct xfs_mount *mp,
unsigned int rsumlevels,
xfs_extlen_t rbmblocks)
{
unsigned long long rsumwords;
rsumwords = (unsigned long long)rsumlevels * rbmblocks;
return XFS_B_TO_FSB(mp, rsumwords << XFS_WORDLOG);
}
/*
* Compute the number of rtsummary info words needed to populate every block of
* a summary file that is large enough to track the given rt space.
*/
unsigned long long
xfs_rtsummary_wordcount(
struct xfs_mount *mp,
unsigned int rsumlevels,
xfs_extlen_t rbmblocks)
{
xfs_filblks_t blocks;
blocks = xfs_rtsummary_blockcount(mp, rsumlevels, rbmblocks);
return XFS_FSB_TO_B(mp, blocks) >> XFS_WORDLOG;
}
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*/
#ifndef __XFS_RTBITMAP_H__
#define __XFS_RTBITMAP_H__
struct xfs_rtalloc_args {
struct xfs_mount *mp;
struct xfs_trans *tp;
struct xfs_buf *rbmbp; /* bitmap block buffer */
struct xfs_buf *sumbp; /* summary block buffer */
xfs_fileoff_t rbmoff; /* bitmap block number */
xfs_fileoff_t sumoff; /* summary block number */
};
static inline xfs_rtblock_t
xfs_rtx_to_rtb(
struct xfs_mount *mp,
xfs_rtxnum_t rtx)
{
if (mp->m_rtxblklog >= 0)
return rtx << mp->m_rtxblklog;
return rtx * mp->m_sb.sb_rextsize;
}
static inline xfs_extlen_t
xfs_rtxlen_to_extlen(
struct xfs_mount *mp,
xfs_rtxlen_t rtxlen)
{
if (mp->m_rtxblklog >= 0)
return rtxlen << mp->m_rtxblklog;
return rtxlen * mp->m_sb.sb_rextsize;
}
/* Compute the misalignment between an extent length and a realtime extent .*/
static inline unsigned int
xfs_extlen_to_rtxmod(
struct xfs_mount *mp,
xfs_extlen_t len)
{
if (mp->m_rtxblklog >= 0)
return len & mp->m_rtxblkmask;
return len % mp->m_sb.sb_rextsize;
}
static inline xfs_rtxlen_t
xfs_extlen_to_rtxlen(
struct xfs_mount *mp,
xfs_extlen_t len)
{
if (mp->m_rtxblklog >= 0)
return len >> mp->m_rtxblklog;
return len / mp->m_sb.sb_rextsize;
}
/* Convert an rt block number into an rt extent number. */
static inline xfs_rtxnum_t
xfs_rtb_to_rtx(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
if (likely(mp->m_rtxblklog >= 0))
return rtbno >> mp->m_rtxblklog;
return div_u64(rtbno, mp->m_sb.sb_rextsize);
}
/* Return the offset of an rt block number within an rt extent. */
static inline xfs_extlen_t
xfs_rtb_to_rtxoff(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
if (likely(mp->m_rtxblklog >= 0))
return rtbno & mp->m_rtxblkmask;
return do_div(rtbno, mp->m_sb.sb_rextsize);
}
/*
* Crack an rt block number into an rt extent number and an offset within that
* rt extent. Returns the rt extent number directly and the offset in @off.
*/
static inline xfs_rtxnum_t
xfs_rtb_to_rtxrem(
struct xfs_mount *mp,
xfs_rtblock_t rtbno,
xfs_extlen_t *off)
{
if (likely(mp->m_rtxblklog >= 0)) {
*off = rtbno & mp->m_rtxblkmask;
return rtbno >> mp->m_rtxblklog;
}
return div_u64_rem(rtbno, mp->m_sb.sb_rextsize, off);
}
/*
* Convert an rt block number into an rt extent number, rounding up to the next
* rt extent if the rt block is not aligned to an rt extent boundary.
*/
static inline xfs_rtxnum_t
xfs_rtb_to_rtxup(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
if (likely(mp->m_rtxblklog >= 0)) {
if (rtbno & mp->m_rtxblkmask)
return (rtbno >> mp->m_rtxblklog) + 1;
return rtbno >> mp->m_rtxblklog;
}
if (do_div(rtbno, mp->m_sb.sb_rextsize))
rtbno++;
return rtbno;
}
/* Round this rtblock up to the nearest rt extent size. */
static inline xfs_rtblock_t
xfs_rtb_roundup_rtx(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
return roundup_64(rtbno, mp->m_sb.sb_rextsize);
}
/* Round this rtblock down to the nearest rt extent size. */
static inline xfs_rtblock_t
xfs_rtb_rounddown_rtx(
struct xfs_mount *mp,
xfs_rtblock_t rtbno)
{
return rounddown_64(rtbno, mp->m_sb.sb_rextsize);
}
/* Convert an rt extent number to a file block offset in the rt bitmap file. */
static inline xfs_fileoff_t
xfs_rtx_to_rbmblock(
struct xfs_mount *mp,
xfs_rtxnum_t rtx)
{
return rtx >> mp->m_blkbit_log;
}
/* Convert an rt extent number to a word offset within an rt bitmap block. */
static inline unsigned int
xfs_rtx_to_rbmword(
struct xfs_mount *mp,
xfs_rtxnum_t rtx)
{
return (rtx >> XFS_NBWORDLOG) & (mp->m_blockwsize - 1);
}
/* Convert a file block offset in the rt bitmap file to an rt extent number. */
static inline xfs_rtxnum_t
xfs_rbmblock_to_rtx(
struct xfs_mount *mp,
xfs_fileoff_t rbmoff)
{
return rbmoff << mp->m_blkbit_log;
}
/* Return a pointer to a bitmap word within a rt bitmap block. */
static inline union xfs_rtword_raw *
xfs_rbmblock_wordptr(
struct xfs_rtalloc_args *args,
unsigned int index)
{
union xfs_rtword_raw *words = args->rbmbp->b_addr;
return words + index;
}
/* Convert an ondisk bitmap word to its incore representation. */
static inline xfs_rtword_t
xfs_rtbitmap_getword(
struct xfs_rtalloc_args *args,
unsigned int index)
{
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
return word->old;
}
/* Set an ondisk bitmap word from an incore representation. */
static inline void
xfs_rtbitmap_setword(
struct xfs_rtalloc_args *args,
unsigned int index,
xfs_rtword_t value)
{
union xfs_rtword_raw *word = xfs_rbmblock_wordptr(args, index);
word->old = value;
}
/*
* Convert a rt extent length and rt bitmap block number to a xfs_suminfo_t
* offset within the rt summary file.
*/
static inline xfs_rtsumoff_t
xfs_rtsumoffs(
struct xfs_mount *mp,
int log2_len,
xfs_fileoff_t rbmoff)
{
return log2_len * mp->m_sb.sb_rbmblocks + rbmoff;
}
/*
* Convert an xfs_suminfo_t offset to a file block offset within the rt summary
* file.
*/
static inline xfs_fileoff_t
xfs_rtsumoffs_to_block(
struct xfs_mount *mp,
xfs_rtsumoff_t rsumoff)
{
return XFS_B_TO_FSBT(mp, rsumoff * sizeof(xfs_suminfo_t));
}
/*
* Convert an xfs_suminfo_t offset to an info word offset within an rt summary
* block.
*/
static inline unsigned int
xfs_rtsumoffs_to_infoword(
struct xfs_mount *mp,
xfs_rtsumoff_t rsumoff)
{
unsigned int mask = mp->m_blockmask >> XFS_SUMINFOLOG;
return rsumoff & mask;
}
/* Return a pointer to a summary info word within a rt summary block. */
static inline union xfs_suminfo_raw *
xfs_rsumblock_infoptr(
struct xfs_rtalloc_args *args,
unsigned int index)
{
union xfs_suminfo_raw *info = args->sumbp->b_addr;
return info + index;
}
/* Get the current value of a summary counter. */
static inline xfs_suminfo_t
xfs_suminfo_get(
struct xfs_rtalloc_args *args,
unsigned int index)
{
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
return info->old;
}
/* Add to the current value of a summary counter and return the new value. */
static inline xfs_suminfo_t
xfs_suminfo_add(
struct xfs_rtalloc_args *args,
unsigned int index,
int delta)
{
union xfs_suminfo_raw *info = xfs_rsumblock_infoptr(args, index);
info->old += delta;
return info->old;
}
/*
* Functions for walking free space rtextents in the realtime bitmap.
*/
struct xfs_rtalloc_rec {
xfs_rtxnum_t ar_startext;
xfs_rtbxlen_t ar_extcount;
};
typedef int (*xfs_rtalloc_query_range_fn)(
struct xfs_mount *mp,
struct xfs_trans *tp,
const struct xfs_rtalloc_rec *rec,
void *priv);
#ifdef CONFIG_XFS_RT
void xfs_rtbuf_cache_relse(struct xfs_rtalloc_args *args);
int xfs_rtbuf_get(struct xfs_rtalloc_args *args, xfs_fileoff_t block,
int issum);
static inline int
xfs_rtbitmap_read_buf(
struct xfs_rtalloc_args *args,
xfs_fileoff_t block)
{
return xfs_rtbuf_get(args, block, 0);
}
static inline int
xfs_rtsummary_read_buf(
struct xfs_rtalloc_args *args,
xfs_fileoff_t block)
{
return xfs_rtbuf_get(args, block, 1);
}
int xfs_rtcheck_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxlen_t len, int val, xfs_rtxnum_t *new, int *stat);
int xfs_rtfind_back(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
int xfs_rtfind_forw(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxnum_t limit, xfs_rtxnum_t *rtblock);
int xfs_rtmodify_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxlen_t len, int val);
int xfs_rtmodify_summary_int(struct xfs_rtalloc_args *args, int log,
xfs_fileoff_t bbno, int delta, xfs_suminfo_t *sum);
int xfs_rtmodify_summary(struct xfs_rtalloc_args *args, int log,
xfs_fileoff_t bbno, int delta);
int xfs_rtfree_range(struct xfs_rtalloc_args *args, xfs_rtxnum_t start,
xfs_rtxlen_t len);
int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp,
const struct xfs_rtalloc_rec *low_rec,
const struct xfs_rtalloc_rec *high_rec,
xfs_rtalloc_query_range_fn fn, void *priv);
int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtalloc_query_range_fn fn,
void *priv);
int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtxnum_t start, xfs_rtxlen_t len,
bool *is_free);
/*
* Free an extent in the realtime subvolume. Length is expressed in
* realtime extents, as is the block number.
*/
int /* error */
xfs_rtfree_extent(
struct xfs_trans *tp, /* transaction pointer */
xfs_rtxnum_t start, /* starting rtext number to free */
xfs_rtxlen_t len); /* length of extent freed */
/* Same as above, but in units of rt blocks. */
int xfs_rtfree_blocks(struct xfs_trans *tp, xfs_fsblock_t rtbno,
xfs_filblks_t rtlen);
xfs_filblks_t xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t
rtextents);
unsigned long long xfs_rtbitmap_wordcount(struct xfs_mount *mp,
xfs_rtbxlen_t rtextents);
xfs_filblks_t xfs_rtsummary_blockcount(struct xfs_mount *mp,
unsigned int rsumlevels, xfs_extlen_t rbmblocks);
unsigned long long xfs_rtsummary_wordcount(struct xfs_mount *mp,
unsigned int rsumlevels, xfs_extlen_t rbmblocks);
#else /* CONFIG_XFS_RT */
# define xfs_rtfree_extent(t,b,l) (-ENOSYS)
# define xfs_rtfree_blocks(t,rb,rl) (-ENOSYS)
# define xfs_rtalloc_query_range(m,t,l,h,f,p) (-ENOSYS)
# define xfs_rtalloc_query_all(m,t,f,p) (-ENOSYS)
# define xfs_rtbitmap_read_buf(a,b) (-ENOSYS)
# define xfs_rtsummary_read_buf(a,b) (-ENOSYS)
# define xfs_rtbuf_cache_relse(a) (0)
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (-ENOSYS)
static inline xfs_filblks_t
xfs_rtbitmap_blockcount(struct xfs_mount *mp, xfs_rtbxlen_t rtextents)
{
/* shut up gcc */
return 0;
}
# define xfs_rtbitmap_wordcount(mp, r) (0)
# define xfs_rtsummary_blockcount(mp, l, b) (0)
# define xfs_rtsummary_wordcount(mp, l, b) (0)
#endif /* CONFIG_XFS_RT */
#endif /* __XFS_RTBITMAP_H__ */
...@@ -975,6 +975,8 @@ xfs_sb_mount_common( ...@@ -975,6 +975,8 @@ xfs_sb_mount_common(
mp->m_blockmask = sbp->sb_blocksize - 1; mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1; mp->m_blockwmask = mp->m_blockwsize - 1;
mp->m_rtxblklog = log2_if_power2(sbp->sb_rextsize);
mp->m_rtxblkmask = mask64_if_power2(sbp->sb_rextsize);
mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
......
...@@ -25,7 +25,7 @@ extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp); ...@@ -25,7 +25,7 @@ extern uint64_t xfs_sb_version_to_features(struct xfs_sb *sbp);
extern int xfs_update_secondary_sbs(struct xfs_mount *mp); extern int xfs_update_secondary_sbs(struct xfs_mount *mp);
#define XFS_FS_GEOM_MAX_STRUCT_VER (4) #define XFS_FS_GEOM_MAX_STRUCT_VER (5)
extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo, extern void xfs_fs_geometry(struct xfs_mount *mp, struct xfs_fsop_geom *geo,
int struct_version); int struct_version);
extern int xfs_sb_read_secondary(struct xfs_mount *mp, extern int xfs_sb_read_secondary(struct xfs_mount *mp,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_qm.h" #include "xfs_qm.h"
#include "xfs_trans_space.h" #include "xfs_trans_space.h"
#include "xfs_rtbitmap.h"
#define _ALLOC true #define _ALLOC true
#define _FREE false #define _FREE false
...@@ -217,11 +218,12 @@ xfs_rtalloc_block_count( ...@@ -217,11 +218,12 @@ xfs_rtalloc_block_count(
struct xfs_mount *mp, struct xfs_mount *mp,
unsigned int num_ops) unsigned int num_ops)
{ {
unsigned int blksz = XFS_FSB_TO_B(mp, 1); unsigned int rtbmp_blocks;
unsigned int rtbmp_bytes; xfs_rtxlen_t rtxlen;
rtbmp_bytes = (XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize) / NBBY; rtxlen = xfs_extlen_to_rtxlen(mp, XFS_MAX_BMBT_EXTLEN);
return (howmany(rtbmp_bytes, blksz) + 1) * num_ops; rtbmp_blocks = xfs_rtbitmap_blockcount(mp, rtxlen);
return (rtbmp_blocks + 1) * num_ops;
} }
/* /*
......
...@@ -148,10 +148,10 @@ xfs_verify_rtbno( ...@@ -148,10 +148,10 @@ xfs_verify_rtbno(
/* Verify that a realtime device extent is fully contained inside the volume. */ /* Verify that a realtime device extent is fully contained inside the volume. */
bool bool
xfs_verify_rtext( xfs_verify_rtbext(
struct xfs_mount *mp, struct xfs_mount *mp,
xfs_rtblock_t rtbno, xfs_rtblock_t rtbno,
xfs_rtblock_t len) xfs_filblks_t len)
{ {
if (rtbno + len <= rtbno) if (rtbno + len <= rtbno)
return false; return false;
......
...@@ -11,6 +11,7 @@ typedef uint32_t prid_t; /* project ID */ ...@@ -11,6 +11,7 @@ typedef uint32_t prid_t; /* project ID */
typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */ typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */
typedef uint32_t xfs_agino_t; /* inode # within allocation grp */ typedef uint32_t xfs_agino_t; /* inode # within allocation grp */
typedef uint32_t xfs_extlen_t; /* extent length in blocks */ typedef uint32_t xfs_extlen_t; /* extent length in blocks */
typedef uint32_t xfs_rtxlen_t; /* file extent length in rtextents */
typedef uint32_t xfs_agnumber_t; /* allocation group number */ typedef uint32_t xfs_agnumber_t; /* allocation group number */
typedef uint64_t xfs_extnum_t; /* # of extents in a file */ typedef uint64_t xfs_extnum_t; /* # of extents in a file */
typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */ typedef uint32_t xfs_aextnum_t; /* # extents in an attribute fork */
...@@ -18,6 +19,7 @@ typedef int64_t xfs_fsize_t; /* bytes in a file */ ...@@ -18,6 +19,7 @@ typedef int64_t xfs_fsize_t; /* bytes in a file */
typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */ typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */
typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */ typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */
typedef uint32_t xfs_rtsumoff_t; /* offset of an rtsummary info word */
typedef uint32_t xfs_rtword_t; /* word type for bitmap manipulations */ typedef uint32_t xfs_rtword_t; /* word type for bitmap manipulations */
typedef int64_t xfs_lsn_t; /* log sequence number */ typedef int64_t xfs_lsn_t; /* log sequence number */
...@@ -31,6 +33,8 @@ typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ ...@@ -31,6 +33,8 @@ typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */
typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */ typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */
typedef uint64_t xfs_fileoff_t; /* block number in a file */ typedef uint64_t xfs_fileoff_t; /* block number in a file */
typedef uint64_t xfs_filblks_t; /* number of blocks in a file */ typedef uint64_t xfs_filblks_t; /* number of blocks in a file */
typedef uint64_t xfs_rtxnum_t; /* rtextent number */
typedef uint64_t xfs_rtbxlen_t; /* rtbitmap extent length in rtextents */
typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */ typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */
...@@ -47,6 +51,7 @@ typedef void * xfs_failaddr_t; ...@@ -47,6 +51,7 @@ typedef void * xfs_failaddr_t;
#define NULLRFSBLOCK ((xfs_rfsblock_t)-1) #define NULLRFSBLOCK ((xfs_rfsblock_t)-1)
#define NULLRTBLOCK ((xfs_rtblock_t)-1) #define NULLRTBLOCK ((xfs_rtblock_t)-1)
#define NULLFILEOFF ((xfs_fileoff_t)-1) #define NULLFILEOFF ((xfs_fileoff_t)-1)
#define NULLRTEXTNO ((xfs_rtxnum_t)-1)
#define NULLAGBLOCK ((xfs_agblock_t)-1) #define NULLAGBLOCK ((xfs_agblock_t)-1)
#define NULLAGNUMBER ((xfs_agnumber_t)-1) #define NULLAGNUMBER ((xfs_agnumber_t)-1)
...@@ -145,6 +150,7 @@ typedef uint32_t xfs_dqid_t; ...@@ -145,6 +150,7 @@ typedef uint32_t xfs_dqid_t;
*/ */
#define XFS_NBBYLOG 3 /* log2(NBBY) */ #define XFS_NBBYLOG 3 /* log2(NBBY) */
#define XFS_WORDLOG 2 /* log2(sizeof(xfs_rtword_t)) */ #define XFS_WORDLOG 2 /* log2(sizeof(xfs_rtword_t)) */
#define XFS_SUMINFOLOG 2 /* log2(sizeof(xfs_suminfo_t)) */
#define XFS_NBWORDLOG (XFS_NBBYLOG + XFS_WORDLOG) #define XFS_NBWORDLOG (XFS_NBBYLOG + XFS_WORDLOG)
#define XFS_NBWORD (1 << XFS_NBWORDLOG) #define XFS_NBWORD (1 << XFS_NBWORDLOG)
#define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1) #define XFS_WORDMASK ((1 << XFS_WORDLOG) - 1)
...@@ -229,8 +235,8 @@ bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino); ...@@ -229,8 +235,8 @@ bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino); bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno); bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
bool xfs_verify_rtext(struct xfs_mount *mp, xfs_rtblock_t rtbno, bool xfs_verify_rtbext(struct xfs_mount *mp, xfs_rtblock_t rtbno,
xfs_rtblock_t len); xfs_filblks_t len);
bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount); bool xfs_verify_icount(struct xfs_mount *mp, unsigned long long icount);
bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off); bool xfs_verify_dablk(struct xfs_mount *mp, xfs_fileoff_t off);
void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min, void xfs_icount_range(struct xfs_mount *mp, unsigned long long *min,
......
...@@ -410,7 +410,7 @@ xchk_bmap_iextent( ...@@ -410,7 +410,7 @@ xchk_bmap_iextent(
/* Make sure the extent points to a valid place. */ /* Make sure the extent points to a valid place. */
if (info->is_rt && if (info->is_rt &&
!xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount)) !xfs_verify_rtbext(mp, irec->br_startblock, irec->br_blockcount))
xchk_fblock_set_corrupt(info->sc, info->whichfork, xchk_fblock_set_corrupt(info->sc, info->whichfork,
irec->br_startoff); irec->br_startoff);
if (!info->is_rt && if (!info->is_rt &&
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include "xfs_health.h" #include "xfs_health.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_rmap.h" #include "xfs_rmap.h"
#include "xfs_bmap_util.h" #include "xfs_bmap_util.h"
#include "xfs_rtbitmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
#include "scrub/common.h" #include "scrub/common.h"
#include "scrub/btree.h" #include "scrub/btree.h"
...@@ -225,7 +226,7 @@ xchk_inode_extsize( ...@@ -225,7 +226,7 @@ xchk_inode_extsize(
*/ */
if ((flags & XFS_DIFLAG_RTINHERIT) && if ((flags & XFS_DIFLAG_RTINHERIT) &&
(flags & XFS_DIFLAG_EXTSZINHERIT) && (flags & XFS_DIFLAG_EXTSZINHERIT) &&
value % sc->mp->m_sb.sb_rextsize > 0) xfs_extlen_to_rtxmod(sc->mp, value) > 0)
xchk_ino_set_warning(sc, ino); xchk_ino_set_warning(sc, ino);
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
...@@ -48,12 +48,12 @@ xchk_rtbitmap_rec( ...@@ -48,12 +48,12 @@ xchk_rtbitmap_rec(
{ {
struct xfs_scrub *sc = priv; struct xfs_scrub *sc = priv;
xfs_rtblock_t startblock; xfs_rtblock_t startblock;
xfs_rtblock_t blockcount; xfs_filblks_t blockcount;
startblock = rec->ar_startext * mp->m_sb.sb_rextsize; startblock = xfs_rtx_to_rtb(mp, rec->ar_startext);
blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize; blockcount = xfs_rtx_to_rtb(mp, rec->ar_extcount);
if (!xfs_verify_rtext(mp, startblock, blockcount)) if (!xfs_verify_rtbext(mp, startblock, blockcount))
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
return 0; return 0;
} }
...@@ -128,26 +128,22 @@ xchk_rtbitmap( ...@@ -128,26 +128,22 @@ xchk_rtbitmap(
void void
xchk_xref_is_used_rt_space( xchk_xref_is_used_rt_space(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xfs_rtblock_t fsbno, xfs_rtblock_t rtbno,
xfs_extlen_t len) xfs_extlen_t len)
{ {
xfs_rtblock_t startext; xfs_rtxnum_t startext;
xfs_rtblock_t endext; xfs_rtxnum_t endext;
xfs_rtblock_t extcount;
bool is_free; bool is_free;
int error; int error;
if (xchk_skip_xref(sc->sm)) if (xchk_skip_xref(sc->sm))
return; return;
startext = fsbno; startext = xfs_rtb_to_rtx(sc->mp, rtbno);
endext = fsbno + len - 1; endext = xfs_rtb_to_rtx(sc->mp, rtbno + len - 1);
do_div(startext, sc->mp->m_sb.sb_rextsize);
do_div(endext, sc->mp->m_sb.sb_rextsize);
extcount = endext - startext + 1;
xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP); xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext, extcount, error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext,
&is_free); endext - startext + 1, &is_free);
if (!xchk_should_check_xref(sc, &error, NULL)) if (!xchk_should_check_xref(sc, &error, NULL))
goto out_unlock; goto out_unlock;
if (is_free) if (is_free)
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_trans.h" #include "xfs_trans.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_bit.h" #include "xfs_bit.h"
#include "xfs_bmap.h" #include "xfs_bmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
...@@ -81,34 +81,45 @@ typedef unsigned int xchk_rtsumoff_t; ...@@ -81,34 +81,45 @@ typedef unsigned int xchk_rtsumoff_t;
static inline int static inline int
xfsum_load( xfsum_load(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
xfs_suminfo_t *info) union xfs_suminfo_raw *rawinfo)
{ {
return xfile_obj_load(sc->xfile, info, sizeof(xfs_suminfo_t), return xfile_obj_load(sc->xfile, rawinfo,
sizeof(union xfs_suminfo_raw),
sumoff << XFS_WORDLOG); sumoff << XFS_WORDLOG);
} }
static inline int static inline int
xfsum_store( xfsum_store(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
const xfs_suminfo_t info) const union xfs_suminfo_raw rawinfo)
{ {
return xfile_obj_store(sc->xfile, &info, sizeof(xfs_suminfo_t), return xfile_obj_store(sc->xfile, &rawinfo,
sizeof(union xfs_suminfo_raw),
sumoff << XFS_WORDLOG); sumoff << XFS_WORDLOG);
} }
static inline int static inline int
xfsum_copyout( xfsum_copyout(
struct xfs_scrub *sc, struct xfs_scrub *sc,
xchk_rtsumoff_t sumoff, xfs_rtsumoff_t sumoff,
xfs_suminfo_t *info, union xfs_suminfo_raw *rawinfo,
unsigned int nr_words) unsigned int nr_words)
{ {
return xfile_obj_load(sc->xfile, info, nr_words << XFS_WORDLOG, return xfile_obj_load(sc->xfile, rawinfo, nr_words << XFS_WORDLOG,
sumoff << XFS_WORDLOG); sumoff << XFS_WORDLOG);
} }
static inline xfs_suminfo_t
xchk_rtsum_inc(
struct xfs_mount *mp,
union xfs_suminfo_raw *v)
{
v->old += 1;
return v->old;
}
/* Update the summary file to reflect the free extent that we've accumulated. */ /* Update the summary file to reflect the free extent that we've accumulated. */
STATIC int STATIC int
xchk_rtsum_record_free( xchk_rtsum_record_free(
...@@ -121,23 +132,24 @@ xchk_rtsum_record_free( ...@@ -121,23 +132,24 @@ xchk_rtsum_record_free(
xfs_fileoff_t rbmoff; xfs_fileoff_t rbmoff;
xfs_rtblock_t rtbno; xfs_rtblock_t rtbno;
xfs_filblks_t rtlen; xfs_filblks_t rtlen;
xchk_rtsumoff_t offs; xfs_rtsumoff_t offs;
unsigned int lenlog; unsigned int lenlog;
xfs_suminfo_t v = 0; union xfs_suminfo_raw v;
xfs_suminfo_t value;
int error = 0; int error = 0;
if (xchk_should_terminate(sc, &error)) if (xchk_should_terminate(sc, &error))
return error; return error;
/* Compute the relevant location in the rtsum file. */ /* Compute the relevant location in the rtsum file. */
rbmoff = XFS_BITTOBLOCK(mp, rec->ar_startext); rbmoff = xfs_rtx_to_rbmblock(mp, rec->ar_startext);
lenlog = XFS_RTBLOCKLOG(rec->ar_extcount); lenlog = XFS_RTBLOCKLOG(rec->ar_extcount);
offs = XFS_SUMOFFS(mp, lenlog, rbmoff); offs = xfs_rtsumoffs(mp, lenlog, rbmoff);
rtbno = rec->ar_startext * mp->m_sb.sb_rextsize; rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
rtlen = rec->ar_extcount * mp->m_sb.sb_rextsize; rtlen = xfs_rtx_to_rtb(mp, rec->ar_extcount);
if (!xfs_verify_rtext(mp, rtbno, rtlen)) { if (!xfs_verify_rtbext(mp, rtbno, rtlen)) {
xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino); xchk_ino_xref_set_corrupt(sc, mp->m_rbmip->i_ino);
return -EFSCORRUPTED; return -EFSCORRUPTED;
} }
...@@ -147,9 +159,9 @@ xchk_rtsum_record_free( ...@@ -147,9 +159,9 @@ xchk_rtsum_record_free(
if (error) if (error)
return error; return error;
v++; value = xchk_rtsum_inc(sc->mp, &v);
trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount, trace_xchk_rtsum_record_free(mp, rec->ar_startext, rec->ar_extcount,
lenlog, offs, v); lenlog, offs, value);
return xfsum_store(sc, offs, v); return xfsum_store(sc, offs, v);
} }
...@@ -160,12 +172,11 @@ xchk_rtsum_compute( ...@@ -160,12 +172,11 @@ xchk_rtsum_compute(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
unsigned long long rtbmp_bytes; unsigned long long rtbmp_blocks;
/* If the bitmap size doesn't match the computed size, bail. */ /* If the bitmap size doesn't match the computed size, bail. */
rtbmp_bytes = howmany_64(mp->m_sb.sb_rextents, NBBY); rtbmp_blocks = xfs_rtbitmap_blockcount(mp, mp->m_sb.sb_rextents);
if (roundup_64(rtbmp_bytes, mp->m_sb.sb_blocksize) != if (XFS_FSB_TO_B(mp, rtbmp_blocks) != mp->m_rbmip->i_disk_size)
mp->m_rbmip->i_disk_size)
return -EFSCORRUPTED; return -EFSCORRUPTED;
return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free, return xfs_rtalloc_query_all(sc->mp, sc->tp, xchk_rtsum_record_free,
...@@ -177,14 +188,18 @@ STATIC int ...@@ -177,14 +188,18 @@ STATIC int
xchk_rtsum_compare( xchk_rtsum_compare(
struct xfs_scrub *sc) struct xfs_scrub *sc)
{ {
struct xfs_rtalloc_args args = {
.mp = sc->mp,
.tp = sc->tp,
};
struct xfs_mount *mp = sc->mp; struct xfs_mount *mp = sc->mp;
struct xfs_buf *bp;
struct xfs_bmbt_irec map; struct xfs_bmbt_irec map;
xfs_fileoff_t off; xfs_fileoff_t off;
xchk_rtsumoff_t sumoff = 0; xchk_rtsumoff_t sumoff = 0;
int nmap; int nmap;
for (off = 0; off < XFS_B_TO_FSB(mp, mp->m_rsumsize); off++) { for (off = 0; off < XFS_B_TO_FSB(mp, mp->m_rsumsize); off++) {
union xfs_suminfo_raw *ondisk_info;
int error = 0; int error = 0;
if (xchk_should_terminate(sc, &error)) if (xchk_should_terminate(sc, &error))
...@@ -205,22 +220,23 @@ xchk_rtsum_compare( ...@@ -205,22 +220,23 @@ xchk_rtsum_compare(
} }
/* Read a block's worth of ondisk rtsummary file. */ /* Read a block's worth of ondisk rtsummary file. */
error = xfs_rtbuf_get(mp, sc->tp, off, 1, &bp); error = xfs_rtsummary_read_buf(&args, off);
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error)) if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
return error; return error;
/* Read a block's worth of computed rtsummary file. */ /* Read a block's worth of computed rtsummary file. */
error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize); error = xfsum_copyout(sc, sumoff, sc->buf, mp->m_blockwsize);
if (error) { if (error) {
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
return error; return error;
} }
if (memcmp(bp->b_addr, sc->buf, ondisk_info = xfs_rsumblock_infoptr(&args, 0);
if (memcmp(ondisk_info, sc->buf,
mp->m_blockwsize << XFS_WORDLOG) != 0) mp->m_blockwsize << XFS_WORDLOG) != 0)
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off); xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
xfs_trans_brelse(sc->tp, bp); xfs_rtbuf_cache_relse(&args);
sumoff += mp->m_blockwsize; sumoff += mp->m_blockwsize;
} }
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "xfs_inode.h" #include "xfs_inode.h"
#include "xfs_btree.h" #include "xfs_btree.h"
#include "xfs_ag.h" #include "xfs_ag.h"
#include "xfs_rtbitmap.h"
#include "scrub/scrub.h" #include "scrub/scrub.h"
#include "scrub/xfile.h" #include "scrub/xfile.h"
#include "scrub/xfarray.h" #include "scrub/xfarray.h"
......
...@@ -1036,17 +1036,18 @@ TRACE_EVENT(xfarray_sort_stats, ...@@ -1036,17 +1036,18 @@ TRACE_EVENT(xfarray_sort_stats,
#ifdef CONFIG_XFS_RT #ifdef CONFIG_XFS_RT
TRACE_EVENT(xchk_rtsum_record_free, TRACE_EVENT(xchk_rtsum_record_free,
TP_PROTO(struct xfs_mount *mp, xfs_rtblock_t start, TP_PROTO(struct xfs_mount *mp, xfs_rtxnum_t start,
uint64_t len, unsigned int log, loff_t pos, xfs_suminfo_t v), xfs_rtbxlen_t len, unsigned int log, loff_t pos,
TP_ARGS(mp, start, len, log, pos, v), xfs_suminfo_t value),
TP_ARGS(mp, start, len, log, pos, value),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(dev_t, dev) __field(dev_t, dev)
__field(dev_t, rtdev) __field(dev_t, rtdev)
__field(xfs_rtblock_t, start) __field(xfs_rtxnum_t, start)
__field(unsigned long long, len) __field(unsigned long long, len)
__field(unsigned int, log) __field(unsigned int, log)
__field(loff_t, pos) __field(loff_t, pos)
__field(xfs_suminfo_t, v) __field(xfs_suminfo_t, value)
), ),
TP_fast_assign( TP_fast_assign(
__entry->dev = mp->m_super->s_dev; __entry->dev = mp->m_super->s_dev;
...@@ -1055,7 +1056,7 @@ TRACE_EVENT(xchk_rtsum_record_free, ...@@ -1055,7 +1056,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
__entry->len = len; __entry->len = len;
__entry->log = log; __entry->log = log;
__entry->pos = pos; __entry->pos = pos;
__entry->v = v; __entry->value = value;
), ),
TP_printk("dev %d:%d rtdev %d:%d rtx 0x%llx rtxcount 0x%llx log %u rsumpos 0x%llx sumcount %u", TP_printk("dev %d:%d rtdev %d:%d rtx 0x%llx rtxcount 0x%llx log %u rsumpos 0x%llx sumcount %u",
MAJOR(__entry->dev), MINOR(__entry->dev), MAJOR(__entry->dev), MINOR(__entry->dev),
...@@ -1064,7 +1065,7 @@ TRACE_EVENT(xchk_rtsum_record_free, ...@@ -1064,7 +1065,7 @@ TRACE_EVENT(xchk_rtsum_record_free,
__entry->len, __entry->len,
__entry->log, __entry->log,
__entry->pos, __entry->pos,
__entry->v) __entry->value)
); );
#endif /* CONFIG_XFS_RT */ #endif /* CONFIG_XFS_RT */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_iomap.h" #include "xfs_iomap.h"
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_rtbitmap.h"
/* Kernel only BMAP related definitions and functions */ /* Kernel only BMAP related definitions and functions */
...@@ -75,28 +76,28 @@ xfs_bmap_rtalloc( ...@@ -75,28 +76,28 @@ xfs_bmap_rtalloc(
{ {
struct xfs_mount *mp = ap->ip->i_mount; struct xfs_mount *mp = ap->ip->i_mount;
xfs_fileoff_t orig_offset = ap->offset; xfs_fileoff_t orig_offset = ap->offset;
xfs_rtblock_t rtb; xfs_rtxnum_t rtx;
xfs_extlen_t prod = 0; /* product factor for allocators */ xfs_rtxlen_t prod = 0; /* product factor for allocators */
xfs_extlen_t mod = 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 align; /* minimum allocation alignment */
xfs_extlen_t orig_length = ap->length; xfs_extlen_t orig_length = ap->length;
xfs_extlen_t minlen = mp->m_sb.sb_rextsize; xfs_extlen_t minlen = mp->m_sb.sb_rextsize;
xfs_extlen_t raminlen; xfs_rtxlen_t raminlen;
bool rtlocked = false; bool rtlocked = false;
bool ignore_locality = false; bool ignore_locality = false;
int error; int error;
align = xfs_get_extsz_hint(ap->ip); align = xfs_get_extsz_hint(ap->ip);
retry: 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, error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
align, 1, ap->eof, 0, align, 1, ap->eof, 0,
ap->conv, &ap->offset, &ap->length); ap->conv, &ap->offset, &ap->length);
if (error) if (error)
return error; return error;
ASSERT(ap->length); 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 * If we shifted the file offset downward to satisfy an extent size
...@@ -116,17 +117,14 @@ xfs_bmap_rtalloc( ...@@ -116,17 +117,14 @@ xfs_bmap_rtalloc(
prod = 1; prod = 1;
/* /*
* Set ralen to be the actual requested length in rtextents. * 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 * 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. * we rounded up to it, cut it back so it's valid again.
* Note that if it's a really large request (bigger than * 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 * XFS_BMBT_MAX_EXTLEN), we don't hear about that number, and can't
* adjust the starting point to match it. * adjust the starting point to match it.
*/ */
if (ralen * mp->m_sb.sb_rextsize >= XFS_MAX_BMBT_EXTLEN) ralen = xfs_extlen_to_rtxlen(mp, min(ap->length, XFS_MAX_BMBT_EXTLEN));
ralen = XFS_MAX_BMBT_EXTLEN / mp->m_sb.sb_rextsize;
/* /*
* Lock out modifications to both the RT bitmap and summary inodes * Lock out modifications to both the RT bitmap and summary inodes
...@@ -144,12 +142,10 @@ xfs_bmap_rtalloc( ...@@ -144,12 +142,10 @@ xfs_bmap_rtalloc(
* pick an extent that will space things out in the rt area. * pick an extent that will space things out in the rt area.
*/ */
if (ap->eof && ap->offset == 0) { if (ap->eof && ap->offset == 0) {
xfs_rtblock_t rtx; /* realtime extent no */
error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx);
if (error) if (error)
return error; return error;
ap->blkno = rtx * mp->m_sb.sb_rextsize; ap->blkno = xfs_rtx_to_rtb(mp, rtx);
} else { } else {
ap->blkno = 0; ap->blkno = 0;
} }
...@@ -160,20 +156,18 @@ xfs_bmap_rtalloc( ...@@ -160,20 +156,18 @@ xfs_bmap_rtalloc(
* Realtime allocation, done through xfs_rtallocate_extent. * Realtime allocation, done through xfs_rtallocate_extent.
*/ */
if (ignore_locality) if (ignore_locality)
ap->blkno = 0; rtx = 0;
else else
do_div(ap->blkno, mp->m_sb.sb_rextsize); rtx = xfs_rtb_to_rtx(mp, ap->blkno);
rtb = ap->blkno; raminlen = max_t(xfs_rtxlen_t, 1, xfs_extlen_to_rtxlen(mp, minlen));
ap->length = ralen; error = xfs_rtallocate_extent(ap->tp, rtx, raminlen, ralen, &ralen,
raminlen = max_t(xfs_extlen_t, 1, minlen / mp->m_sb.sb_rextsize); ap->wasdel, prod, &rtx);
error = xfs_rtallocate_extent(ap->tp, ap->blkno, raminlen, ap->length,
&ralen, ap->wasdel, prod, &rtb);
if (error) if (error)
return error; return error;
if (rtb != NULLRTBLOCK) { if (rtx != NULLRTEXTNO) {
ap->blkno = rtb * mp->m_sb.sb_rextsize; ap->blkno = xfs_rtx_to_rtb(mp, rtx);
ap->length = ralen * mp->m_sb.sb_rextsize; ap->length = xfs_rtxlen_to_extlen(mp, ralen);
ap->ip->i_nblocks += ap->length; ap->ip->i_nblocks += ap->length;
xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
if (ap->wasdel) if (ap->wasdel)
...@@ -690,7 +684,7 @@ xfs_can_free_eofblocks( ...@@ -690,7 +684,7 @@ xfs_can_free_eofblocks(
*/ */
end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_ISIZE(ip)); 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) 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); last_fsb = XFS_B_TO_FSB(mp, mp->m_super->s_maxbytes);
if (last_fsb <= end_fsb) if (last_fsb <= end_fsb)
return false; return false;
...@@ -780,12 +774,10 @@ xfs_alloc_file_space( ...@@ -780,12 +774,10 @@ xfs_alloc_file_space(
{ {
xfs_mount_t *mp = ip->i_mount; xfs_mount_t *mp = ip->i_mount;
xfs_off_t count; xfs_off_t count;
xfs_filblks_t allocated_fsb;
xfs_filblks_t allocatesize_fsb; xfs_filblks_t allocatesize_fsb;
xfs_extlen_t extsz, temp; xfs_extlen_t extsz, temp;
xfs_fileoff_t startoffset_fsb; xfs_fileoff_t startoffset_fsb;
xfs_fileoff_t endoffset_fsb; xfs_fileoff_t endoffset_fsb;
int nimaps;
int rt; int rt;
xfs_trans_t *tp; xfs_trans_t *tp;
xfs_bmbt_irec_t imaps[1], *imapp; xfs_bmbt_irec_t imaps[1], *imapp;
...@@ -808,7 +800,6 @@ xfs_alloc_file_space( ...@@ -808,7 +800,6 @@ xfs_alloc_file_space(
count = len; count = len;
imapp = &imaps[0]; imapp = &imaps[0];
nimaps = 1;
startoffset_fsb = XFS_B_TO_FSBT(mp, offset); startoffset_fsb = XFS_B_TO_FSBT(mp, offset);
endoffset_fsb = XFS_B_TO_FSB(mp, offset + count); endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
allocatesize_fsb = endoffset_fsb - startoffset_fsb; allocatesize_fsb = endoffset_fsb - startoffset_fsb;
...@@ -819,6 +810,7 @@ xfs_alloc_file_space( ...@@ -819,6 +810,7 @@ xfs_alloc_file_space(
while (allocatesize_fsb && !error) { while (allocatesize_fsb && !error) {
xfs_fileoff_t s, e; xfs_fileoff_t s, e;
unsigned int dblocks, rblocks, resblks; unsigned int dblocks, rblocks, resblks;
int nimaps = 1;
/* /*
* Determine space reservations for data/realtime. * Determine space reservations for data/realtime.
...@@ -884,15 +876,19 @@ xfs_alloc_file_space( ...@@ -884,15 +876,19 @@ xfs_alloc_file_space(
if (error) if (error)
break; break;
allocated_fsb = imapp->br_blockcount; /*
* If the allocator cannot find a single free extent large
if (nimaps == 0) { * enough to cover the start block of the requested range,
error = -ENOSPC; * xfs_bmapi_write will return 0 but leave *nimaps set to 0.
break; *
* 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; return error;
...@@ -989,10 +985,8 @@ xfs_free_file_space( ...@@ -989,10 +985,8 @@ xfs_free_file_space(
/* We can only free complete realtime extents. */ /* We can only free complete realtime extents. */
if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) { if (XFS_IS_REALTIME_INODE(ip) && mp->m_sb.sb_rextsize > 1) {
startoffset_fsb = roundup_64(startoffset_fsb, startoffset_fsb = xfs_rtb_roundup_rtx(mp, startoffset_fsb);
mp->m_sb.sb_rextsize); endoffset_fsb = xfs_rtb_rounddown_rtx(mp, endoffset_fsb);
endoffset_fsb = rounddown_64(endoffset_fsb,
mp->m_sb.sb_rextsize);
} }
/* /*
......
...@@ -214,6 +214,43 @@ xfs_ilock_iocb( ...@@ -214,6 +214,43 @@ xfs_ilock_iocb(
return 0; return 0;
} }
static int
xfs_ilock_iocb_for_write(
struct kiocb *iocb,
unsigned int *lock_mode)
{
ssize_t ret;
struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp));
ret = xfs_ilock_iocb(iocb, *lock_mode);
if (ret)
return ret;
if (*lock_mode == XFS_IOLOCK_EXCL)
return 0;
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
return 0;
xfs_iunlock(ip, *lock_mode);
*lock_mode = XFS_IOLOCK_EXCL;
return xfs_ilock_iocb(iocb, *lock_mode);
}
static unsigned int
xfs_ilock_for_write_fault(
struct xfs_inode *ip)
{
/* get a shared lock if no remapping in progress */
xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
if (!xfs_iflags_test(ip, XFS_IREMAPPING))
return XFS_MMAPLOCK_SHARED;
/* wait for remapping to complete */
xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
return XFS_MMAPLOCK_EXCL;
}
STATIC ssize_t STATIC ssize_t
xfs_file_dio_read( xfs_file_dio_read(
struct kiocb *iocb, struct kiocb *iocb,
...@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned( ...@@ -551,7 +588,7 @@ xfs_file_dio_write_aligned(
unsigned int iolock = XFS_IOLOCK_SHARED; unsigned int iolock = XFS_IOLOCK_SHARED;
ssize_t ret; ssize_t ret;
ret = xfs_ilock_iocb(iocb, iolock); ret = xfs_ilock_iocb_for_write(iocb, &iolock);
if (ret) if (ret)
return ret; return ret;
ret = xfs_file_write_checks(iocb, from, &iolock); ret = xfs_file_write_checks(iocb, from, &iolock);
...@@ -618,7 +655,7 @@ xfs_file_dio_write_unaligned( ...@@ -618,7 +655,7 @@ xfs_file_dio_write_unaligned(
flags = IOMAP_DIO_FORCE_WAIT; flags = IOMAP_DIO_FORCE_WAIT;
} }
ret = xfs_ilock_iocb(iocb, iolock); ret = xfs_ilock_iocb_for_write(iocb, &iolock);
if (ret) if (ret)
return ret; return ret;
...@@ -1180,7 +1217,7 @@ xfs_file_remap_range( ...@@ -1180,7 +1217,7 @@ xfs_file_remap_range(
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out)) if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
xfs_log_force_inode(dest); xfs_log_force_inode(dest);
out_unlock: out_unlock:
xfs_iunlock2_io_mmap(src, dest); xfs_iunlock2_remapping(src, dest);
if (ret) if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
return remapped > 0 ? remapped : ret; return remapped > 0 ? remapped : ret;
...@@ -1328,6 +1365,7 @@ __xfs_filemap_fault( ...@@ -1328,6 +1365,7 @@ __xfs_filemap_fault(
struct inode *inode = file_inode(vmf->vma->vm_file); struct inode *inode = file_inode(vmf->vma->vm_file);
struct xfs_inode *ip = XFS_I(inode); struct xfs_inode *ip = XFS_I(inode);
vm_fault_t ret; vm_fault_t ret;
unsigned int lock_mode = 0;
trace_xfs_filemap_fault(ip, order, write_fault); trace_xfs_filemap_fault(ip, order, write_fault);
...@@ -1336,24 +1374,23 @@ __xfs_filemap_fault( ...@@ -1336,24 +1374,23 @@ __xfs_filemap_fault(
file_update_time(vmf->vma->vm_file); file_update_time(vmf->vma->vm_file);
} }
if (IS_DAX(inode) || write_fault)
lock_mode = xfs_ilock_for_write_fault(XFS_I(inode));
if (IS_DAX(inode)) { if (IS_DAX(inode)) {
pfn_t pfn; pfn_t pfn;
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
ret = xfs_dax_fault(vmf, order, write_fault, &pfn); ret = xfs_dax_fault(vmf, order, write_fault, &pfn);
if (ret & VM_FAULT_NEEDDSYNC) if (ret & VM_FAULT_NEEDDSYNC)
ret = dax_finish_sync_fault(vmf, order, pfn); ret = dax_finish_sync_fault(vmf, order, pfn);
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); } else if (write_fault) {
} else { ret = iomap_page_mkwrite(vmf, &xfs_page_mkwrite_iomap_ops);
if (write_fault) {
xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
ret = iomap_page_mkwrite(vmf,
&xfs_page_mkwrite_iomap_ops);
xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
} else { } else {
ret = filemap_fault(vmf); ret = filemap_fault(vmf);
} }
}
if (lock_mode)
xfs_iunlock(XFS_I(inode), lock_mode);
if (write_fault) if (write_fault)
sb_end_pagefault(inode->i_sb); sb_end_pagefault(inode->i_sb);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "xfs_refcount.h" #include "xfs_refcount.h"
#include "xfs_refcount_btree.h" #include "xfs_refcount_btree.h"
#include "xfs_alloc_btree.h" #include "xfs_alloc_btree.h"
#include "xfs_rtalloc.h" #include "xfs_rtbitmap.h"
#include "xfs_ag.h" #include "xfs_ag.h"
/* Convert an xfs_fsmap to an fsmap. */ /* Convert an xfs_fsmap to an fsmap. */
...@@ -483,11 +483,11 @@ xfs_getfsmap_rtdev_rtbitmap_helper( ...@@ -483,11 +483,11 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
xfs_rtblock_t rtbno; xfs_rtblock_t rtbno;
xfs_daddr_t rec_daddr, len_daddr; xfs_daddr_t rec_daddr, len_daddr;
rtbno = rec->ar_startext * mp->m_sb.sb_rextsize; rtbno = xfs_rtx_to_rtb(mp, rec->ar_startext);
rec_daddr = XFS_FSB_TO_BB(mp, rtbno); rec_daddr = XFS_FSB_TO_BB(mp, rtbno);
irec.rm_startblock = rtbno; irec.rm_startblock = rtbno;
rtbno = rec->ar_extcount * mp->m_sb.sb_rextsize; rtbno = xfs_rtx_to_rtb(mp, rec->ar_extcount);
len_daddr = XFS_FSB_TO_BB(mp, rtbno); len_daddr = XFS_FSB_TO_BB(mp, rtbno);
irec.rm_blockcount = rtbno; irec.rm_blockcount = rtbno;
...@@ -514,7 +514,7 @@ xfs_getfsmap_rtdev_rtbitmap( ...@@ -514,7 +514,7 @@ xfs_getfsmap_rtdev_rtbitmap(
uint64_t eofs; uint64_t eofs;
int error; int error;
eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rextents * mp->m_sb.sb_rextsize); eofs = XFS_FSB_TO_BB(mp, xfs_rtx_to_rtb(mp, mp->m_sb.sb_rextents));
if (keys[0].fmr_physical >= eofs) if (keys[0].fmr_physical >= eofs)
return 0; return 0;
start_rtb = XFS_BB_TO_FSBT(mp, start_rtb = XFS_BB_TO_FSBT(mp,
...@@ -539,11 +539,8 @@ xfs_getfsmap_rtdev_rtbitmap( ...@@ -539,11 +539,8 @@ xfs_getfsmap_rtdev_rtbitmap(
* Set up query parameters to return free rtextents covering the range * Set up query parameters to return free rtextents covering the range
* we want. * we want.
*/ */
alow.ar_startext = start_rtb; alow.ar_startext = xfs_rtb_to_rtx(mp, start_rtb);
ahigh.ar_startext = end_rtb; ahigh.ar_startext = xfs_rtb_to_rtxup(mp, end_rtb);
do_div(alow.ar_startext, mp->m_sb.sb_rextsize);
if (do_div(ahigh.ar_startext, mp->m_sb.sb_rextsize))
ahigh.ar_startext++;
error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh, error = xfs_rtalloc_query_range(mp, tp, &alow, &ahigh,
xfs_getfsmap_rtdev_rtbitmap_helper, info); xfs_getfsmap_rtdev_rtbitmap_helper, info);
if (error) if (error)
......
...@@ -918,6 +918,13 @@ xfs_droplink( ...@@ -918,6 +918,13 @@ xfs_droplink(
xfs_trans_t *tp, xfs_trans_t *tp,
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
if (VFS_I(ip)->i_nlink == 0) {
xfs_alert(ip->i_mount,
"%s: Attempt to drop inode (%llu) with nlink zero.",
__func__, ip->i_ino);
return -EFSCORRUPTED;
}
xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
drop_nlink(VFS_I(ip)); drop_nlink(VFS_I(ip));
...@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap( ...@@ -3621,6 +3628,23 @@ xfs_iunlock2_io_mmap(
inode_unlock(VFS_I(ip1)); inode_unlock(VFS_I(ip1));
} }
/* Drop the MMAPLOCK and the IOLOCK after a remap completes. */
void
xfs_iunlock2_remapping(
struct xfs_inode *ip1,
struct xfs_inode *ip2)
{
xfs_iflags_clear(ip1, XFS_IREMAPPING);
if (ip1 != ip2)
xfs_iunlock(ip1, XFS_MMAPLOCK_SHARED);
xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
if (ip1 != ip2)
inode_unlock_shared(VFS_I(ip1));
inode_unlock(VFS_I(ip2));
}
/* /*
* Reload the incore inode list for this inode. Caller should ensure that * Reload the incore inode list for this inode. Caller should ensure that
* the link count cannot change, either by taking ILOCK_SHARED or otherwise * the link count cannot change, either by taking ILOCK_SHARED or otherwise
......
...@@ -347,6 +347,14 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip) ...@@ -347,6 +347,14 @@ static inline bool xfs_inode_has_large_extent_counts(struct xfs_inode *ip)
/* Quotacheck is running but inode has not been added to quota counts. */ /* Quotacheck is running but inode has not been added to quota counts. */
#define XFS_IQUOTAUNCHECKED (1 << 14) #define XFS_IQUOTAUNCHECKED (1 << 14)
/*
* Remap in progress. Callers that wish to update file data while
* holding a shared IOLOCK or MMAPLOCK must drop the lock and retake
* the lock in exclusive mode. Relocking the file will block until
* IREMAPPING is cleared.
*/
#define XFS_IREMAPPING (1U << 15)
/* All inode state flags related to inode reclaim. */ /* All inode state flags related to inode reclaim. */
#define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \ #define XFS_ALL_IRECLAIM_FLAGS (XFS_IRECLAIMABLE | \
XFS_IRECLAIM | \ XFS_IRECLAIM | \
...@@ -595,6 +603,7 @@ void xfs_end_io(struct work_struct *work); ...@@ -595,6 +603,7 @@ void xfs_end_io(struct work_struct *work);
int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); int xfs_ilock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2); void xfs_iunlock2_io_mmap(struct xfs_inode *ip1, struct xfs_inode *ip2);
void xfs_iunlock2_remapping(struct xfs_inode *ip1, struct xfs_inode *ip2);
static inline bool static inline bool
xfs_inode_unlinked_incomplete( xfs_inode_unlinked_incomplete(
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_log.h" #include "xfs_log.h"
#include "xfs_log_priv.h" #include "xfs_log_priv.h"
#include "xfs_error.h" #include "xfs_error.h"
#include "xfs_rtbitmap.h"
#include <linux/iversion.h> #include <linux/iversion.h>
...@@ -107,7 +108,7 @@ xfs_inode_item_precommit( ...@@ -107,7 +108,7 @@ xfs_inode_item_precommit(
*/ */
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
(ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) && (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
(ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) { xfs_extlen_to_rtxmod(ip->i_mount, ip->i_extsize) > 0) {
ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE | ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
XFS_DIFLAG_EXTSZINHERIT); XFS_DIFLAG_EXTSZINHERIT);
ip->i_extsize = 0; ip->i_extsize = 0;
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "xfs_reflink.h" #include "xfs_reflink.h"
#include "xfs_ioctl.h" #include "xfs_ioctl.h"
#include "xfs_xattr.h" #include "xfs_xattr.h"
#include "xfs_rtbitmap.h"
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/namei.h> #include <linux/namei.h>
...@@ -1004,7 +1005,7 @@ xfs_fill_fsxattr( ...@@ -1004,7 +1005,7 @@ xfs_fill_fsxattr(
* later. * later.
*/ */
if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) && if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
ip->i_extsize % mp->m_sb.sb_rextsize > 0) { xfs_extlen_to_rtxmod(mp, ip->i_extsize) > 0) {
fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE | fa->fsx_xflags &= ~(FS_XFLAG_EXTSIZE |
FS_XFLAG_EXTSZINHERIT); FS_XFLAG_EXTSZINHERIT);
fa->fsx_extsize = 0; fa->fsx_extsize = 0;
...@@ -1130,7 +1131,7 @@ xfs_ioctl_setattr_xflags( ...@@ -1130,7 +1131,7 @@ xfs_ioctl_setattr_xflags(
/* If realtime flag is set then must have realtime device */ /* If realtime flag is set then must have realtime device */
if (fa->fsx_xflags & FS_XFLAG_REALTIME) { if (fa->fsx_xflags & FS_XFLAG_REALTIME) {
if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 || if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 ||
(ip->i_extsize % mp->m_sb.sb_rextsize)) xfs_extlen_to_rtxmod(mp, ip->i_extsize))
return -EINVAL; return -EINVAL;
} }
......
...@@ -198,6 +198,18 @@ static inline uint64_t howmany_64(uint64_t x, uint32_t y) ...@@ -198,6 +198,18 @@ static inline uint64_t howmany_64(uint64_t x, uint32_t y)
return x; return x;
} }
/* If @b is a power of 2, return log2(b). Else return -1. */
static inline int8_t log2_if_power2(unsigned long b)
{
return is_power_of_2(b) ? ilog2(b) : -1;
}
/* If @b is a power of 2, return a mask of the lower bits, else return zero. */
static inline unsigned long long mask64_if_power2(unsigned long b)
{
return is_power_of_2(b) ? b - 1 : 0;
}
int xfs_rw_bdev(struct block_device *bdev, sector_t sector, unsigned int count, int xfs_rw_bdev(struct block_device *bdev, sector_t sector, unsigned int count,
char *data, enum req_op op); char *data, enum req_op op);
......
...@@ -101,9 +101,9 @@ typedef struct xfs_mount { ...@@ -101,9 +101,9 @@ typedef struct xfs_mount {
/* /*
* Optional cache of rt summary level per bitmap block with the * Optional cache of rt summary level per bitmap block with the
* invariant that m_rsum_cache[bbno] <= the minimum i for which * invariant that m_rsum_cache[bbno] > the maximum i for which
* rsum[i][bbno] != 0. Reads and writes are serialized by the rsumip * rsum[i][bbno] != 0, or 0 if rsum[i][bbno] == 0 for all i.
* inode lock. * Reads and writes are serialized by the rsumip inode lock.
*/ */
uint8_t *m_rsum_cache; uint8_t *m_rsum_cache;
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
...@@ -119,6 +119,7 @@ typedef struct xfs_mount { ...@@ -119,6 +119,7 @@ typedef struct xfs_mount {
uint8_t m_blkbb_log; /* blocklog - BBSHIFT */ uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
uint8_t m_agno_log; /* log #ag's */ uint8_t m_agno_log; /* log #ag's */
uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ uint8_t m_sectbb_log; /* sectlog - BBSHIFT */
int8_t m_rtxblklog; /* log2 of rextsize, if possible */
uint m_blockmask; /* sb_blocksize-1 */ uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */ uint m_blockwsize; /* sb_blocksize in words */
uint m_blockwmask; /* blockwsize-1 */ uint m_blockwmask; /* blockwsize-1 */
...@@ -152,6 +153,7 @@ typedef struct xfs_mount { ...@@ -152,6 +153,7 @@ typedef struct xfs_mount {
uint64_t m_features; /* active filesystem features */ uint64_t m_features; /* active filesystem features */
uint64_t m_low_space[XFS_LOWSP_MAX]; uint64_t m_low_space[XFS_LOWSP_MAX];
uint64_t m_low_rtexts[XFS_LOWSP_MAX]; uint64_t m_low_rtexts[XFS_LOWSP_MAX];
uint64_t m_rtxblkmask; /* rt extent block mask */
struct xfs_ino_geometry m_ino_geo; /* inode geometry */ struct xfs_ino_geometry m_ino_geo; /* inode geometry */
struct xfs_trans_resv m_resv; /* precomputed res values */ struct xfs_trans_resv m_resv; /* precomputed res values */
/* low free space thresholds */ /* low free space thresholds */
......
...@@ -72,6 +72,10 @@ xfs_check_ondisk_structs(void) ...@@ -72,6 +72,10 @@ xfs_check_ondisk_structs(void)
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_map_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_map_t, 4);
XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_local_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_local_t, 4);
/* realtime structures */
XFS_CHECK_STRUCT_SIZE(union xfs_rtword_raw, 4);
XFS_CHECK_STRUCT_SIZE(union xfs_suminfo_raw, 4);
/* /*
* m68k has problems with xfs_attr_leaf_name_remote_t, but we pad it to * m68k has problems with xfs_attr_leaf_name_remote_t, but we pad it to
* 4 bytes anyway so it's not obviously a problem. Hence for the moment * 4 bytes anyway so it's not obviously a problem. Hence for the moment
......
...@@ -1540,6 +1540,10 @@ xfs_reflink_remap_prep( ...@@ -1540,6 +1540,10 @@ xfs_reflink_remap_prep(
if (ret) if (ret)
goto out_unlock; goto out_unlock;
xfs_iflags_set(src, XFS_IREMAPPING);
if (inode_in != inode_out)
xfs_ilock_demote(src, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL);
return 0; return 0;
out_unlock: out_unlock:
xfs_iunlock2_io_mmap(src, dest); xfs_iunlock2_io_mmap(src, dest);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_rtalloc.h" #include "xfs_rtalloc.h"
#include "xfs_sb.h" #include "xfs_sb.h"
#include "xfs_rtbitmap.h"
/* /*
* Read and return the summary information for a given extent size, * Read and return the summary information for a given extent size,
...@@ -28,48 +29,48 @@ ...@@ -28,48 +29,48 @@
*/ */
static int static int
xfs_rtget_summary( xfs_rtget_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */
int log, /* log2 of extent size */ int log, /* log2 of extent size */
xfs_rtblock_t bbno, /* bitmap block number */ xfs_fileoff_t bbno, /* bitmap block number */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_suminfo_t *sum) /* out: summary info for this block */ xfs_suminfo_t *sum) /* out: summary info for this block */
{ {
return xfs_rtmodify_summary_int(mp, tp, log, bbno, 0, rbpp, rsb, sum); return xfs_rtmodify_summary_int(args, log, bbno, 0, sum);
} }
/* /*
* Return whether there are any free extents in the size range given * Return whether there are any free extents in the size range given
* by low and high, for the bitmap block bbno. * by low and high, for the bitmap block bbno.
*/ */
STATIC int /* error */ STATIC int
xfs_rtany_summary( xfs_rtany_summary(
xfs_mount_t *mp, /* file system mount structure */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */
int low, /* low log2 extent size */ int low, /* low log2 extent size */
int high, /* high log2 extent size */ int high, /* high log2 extent size */
xfs_rtblock_t bbno, /* bitmap block number */ xfs_fileoff_t bbno, /* bitmap block number */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ int *maxlog) /* out: max log2 extent size free */
xfs_fsblock_t *rsb, /* in/out: summary block number */
int *stat) /* out: any good extents here? */
{ {
int error; /* error value */ struct xfs_mount *mp = args->mp;
int error;
int log; /* loop counter, log2 of ext. size */ int log; /* loop counter, log2 of ext. size */
xfs_suminfo_t sum; /* summary data */ xfs_suminfo_t sum; /* summary data */
/* There are no extents at levels < m_rsum_cache[bbno]. */ /* There are no extents at levels >= m_rsum_cache[bbno]. */
if (mp->m_rsum_cache && low < mp->m_rsum_cache[bbno]) if (mp->m_rsum_cache) {
low = mp->m_rsum_cache[bbno]; high = min(high, mp->m_rsum_cache[bbno] - 1);
if (low > high) {
*maxlog = -1;
return 0;
}
}
/* /*
* Loop over logs of extent sizes. * Loop over logs of extent sizes.
*/ */
for (log = low; log <= high; log++) { for (log = high; log >= low; log--) {
/* /*
* Get one summary datum. * Get one summary datum.
*/ */
error = xfs_rtget_summary(mp, tp, log, bbno, rbpp, rsb, &sum); error = xfs_rtget_summary(args, log, bbno, &sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -77,18 +78,18 @@ xfs_rtany_summary( ...@@ -77,18 +78,18 @@ xfs_rtany_summary(
* If there are any, return success. * If there are any, return success.
*/ */
if (sum) { if (sum) {
*stat = 1; *maxlog = log;
goto out; goto out;
} }
} }
/* /*
* Found nothing, return failure. * Found nothing, return failure.
*/ */
*stat = 0; *maxlog = -1;
out: out:
/* There were no extents at levels < log. */ /* There were no extents at levels > log. */
if (mp->m_rsum_cache && log > mp->m_rsum_cache[bbno]) if (mp->m_rsum_cache && log + 1 < mp->m_rsum_cache[bbno])
mp->m_rsum_cache[bbno] = log; mp->m_rsum_cache[bbno] = log + 1;
return 0; return 0;
} }
...@@ -97,60 +98,54 @@ xfs_rtany_summary( ...@@ -97,60 +98,54 @@ xfs_rtany_summary(
* Copy and transform the summary file, given the old and new * Copy and transform the summary file, given the old and new
* parameters in the mount structures. * parameters in the mount structures.
*/ */
STATIC int /* error */ STATIC int
xfs_rtcopy_summary( xfs_rtcopy_summary(
xfs_mount_t *omp, /* old file system mount point */ struct xfs_rtalloc_args *oargs,
xfs_mount_t *nmp, /* new file system mount point */ struct xfs_rtalloc_args *nargs)
xfs_trans_t *tp) /* transaction pointer */
{ {
xfs_rtblock_t bbno; /* bitmap block number */ xfs_fileoff_t bbno; /* bitmap block number */
struct xfs_buf *bp; /* summary buffer */ int error;
int error; /* error return value */
int log; /* summary level number (log length) */ int log; /* summary level number (log length) */
xfs_suminfo_t sum; /* summary data */ xfs_suminfo_t sum; /* summary data */
xfs_fsblock_t sumbno; /* summary block number */
bp = NULL; for (log = oargs->mp->m_rsumlevels - 1; log >= 0; log--) {
for (log = omp->m_rsumlevels - 1; log >= 0; log--) { for (bbno = oargs->mp->m_sb.sb_rbmblocks - 1;
for (bbno = omp->m_sb.sb_rbmblocks - 1;
(xfs_srtblock_t)bbno >= 0; (xfs_srtblock_t)bbno >= 0;
bbno--) { bbno--) {
error = xfs_rtget_summary(omp, tp, log, bbno, &bp, error = xfs_rtget_summary(oargs, log, bbno, &sum);
&sumbno, &sum);
if (error) if (error)
return error; goto out;
if (sum == 0) if (sum == 0)
continue; continue;
error = xfs_rtmodify_summary(omp, tp, log, bbno, -sum, error = xfs_rtmodify_summary(oargs, log, bbno, -sum);
&bp, &sumbno);
if (error) if (error)
return error; goto out;
error = xfs_rtmodify_summary(nmp, tp, log, bbno, sum, error = xfs_rtmodify_summary(nargs, log, bbno, sum);
&bp, &sumbno);
if (error) if (error)
return error; goto out;
ASSERT(sum > 0); ASSERT(sum > 0);
} }
} }
error = 0;
out:
xfs_rtbuf_cache_relse(oargs);
return 0; return 0;
} }
/* /*
* Mark an extent specified by start and len allocated. * Mark an extent specified by start and len allocated.
* Updates all the summary information as well as the bitmap. * Updates all the summary information as well as the bitmap.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_range( xfs_rtallocate_range(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* start rtext to allocate */
xfs_rtblock_t start, /* start block to allocate */ xfs_rtxlen_t len) /* in/out: summary block number */
xfs_extlen_t len, /* length to allocate */
struct xfs_buf **rbpp, /* in/out: summary block buffer */
xfs_fsblock_t *rsb) /* in/out: summary block number */
{ {
xfs_rtblock_t end; /* end of the allocated extent */ struct xfs_mount *mp = args->mp;
int error; /* error value */ xfs_rtxnum_t end; /* end of the allocated rtext */
xfs_rtblock_t postblock = 0; /* first block allocated > end */ int error;
xfs_rtblock_t preblock = 0; /* first block allocated < start */ xfs_rtxnum_t postblock = 0; /* first rtext allocated > end */
xfs_rtxnum_t preblock = 0; /* first rtext allocated < start */
end = start + len - 1; end = start + len - 1;
/* /*
...@@ -158,14 +153,14 @@ xfs_rtallocate_range( ...@@ -158,14 +153,14 @@ xfs_rtallocate_range(
* We need to find the beginning and end of the extent so we can * We need to find the beginning and end of the extent so we can
* properly update the summary. * properly update the summary.
*/ */
error = xfs_rtfind_back(mp, tp, start, 0, &preblock); error = xfs_rtfind_back(args, start, 0, &preblock);
if (error) { if (error) {
return error; return error;
} }
/* /*
* Find the next allocated block (end of free extent). * Find the next allocated block (end of free extent).
*/ */
error = xfs_rtfind_forw(mp, tp, end, mp->m_sb.sb_rextents - 1, error = xfs_rtfind_forw(args, end, mp->m_sb.sb_rextents - 1,
&postblock); &postblock);
if (error) { if (error) {
return error; return error;
...@@ -174,9 +169,9 @@ xfs_rtallocate_range( ...@@ -174,9 +169,9 @@ xfs_rtallocate_range(
* Decrement the summary information corresponding to the entire * Decrement the summary information corresponding to the entire
* (old) free extent. * (old) free extent.
*/ */
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock + 1 - preblock), XFS_RTBLOCKLOG(postblock + 1 - preblock),
XFS_BITTOBLOCK(mp, preblock), -1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), -1);
if (error) { if (error) {
return error; return error;
} }
...@@ -185,9 +180,9 @@ xfs_rtallocate_range( ...@@ -185,9 +180,9 @@ xfs_rtallocate_range(
* old extent, add summary data for them to be free. * old extent, add summary data for them to be free.
*/ */
if (preblock < start) { if (preblock < start) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(start - preblock), XFS_RTBLOCKLOG(start - preblock),
XFS_BITTOBLOCK(mp, preblock), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, preblock), 1);
if (error) { if (error) {
return error; return error;
} }
...@@ -197,9 +192,9 @@ xfs_rtallocate_range( ...@@ -197,9 +192,9 @@ xfs_rtallocate_range(
* old extent, add summary data for them to be free. * old extent, add summary data for them to be free.
*/ */
if (postblock > end) { if (postblock > end) {
error = xfs_rtmodify_summary(mp, tp, error = xfs_rtmodify_summary(args,
XFS_RTBLOCKLOG(postblock - end), XFS_RTBLOCKLOG(postblock - end),
XFS_BITTOBLOCK(mp, end + 1), 1, rbpp, rsb); xfs_rtx_to_rbmblock(mp, end + 1), 1);
if (error) { if (error) {
return error; return error;
} }
...@@ -207,54 +202,69 @@ xfs_rtallocate_range( ...@@ -207,54 +202,69 @@ xfs_rtallocate_range(
/* /*
* Modify the bitmap to mark this extent allocated. * Modify the bitmap to mark this extent allocated.
*/ */
error = xfs_rtmodify_range(mp, tp, start, len, 0); error = xfs_rtmodify_range(args, start, len, 0);
return error; return error;
} }
/*
* Make sure we don't run off the end of the rt volume. Be careful that
* adjusting maxlen downwards doesn't cause us to fail the alignment checks.
*/
static inline xfs_rtxlen_t
xfs_rtallocate_clamp_len(
struct xfs_mount *mp,
xfs_rtxnum_t startrtx,
xfs_rtxlen_t rtxlen,
xfs_rtxlen_t prod)
{
xfs_rtxlen_t ret;
ret = min(mp->m_sb.sb_rextents, startrtx + rtxlen) - startrtx;
return rounddown(ret, prod);
}
/* /*
* Attempt to allocate an extent minlen<=len<=maxlen starting from * Attempt to allocate an extent minlen<=len<=maxlen starting from
* bitmap block bbno. If we don't get maxlen then use prod to trim * bitmap block bbno. If we don't get maxlen then use prod to trim
* the length, if given. Returns error; returns starting block in *rtblock. * the length, if given. Returns error; returns starting block in *rtx.
* The lengths are all in rtextents. * The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_block( xfs_rtallocate_extent_block(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_fileoff_t bbno, /* bitmap block number */
xfs_rtblock_t bbno, /* bitmap block number */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxnum_t *nextp, /* out: next rtext to try */
xfs_rtblock_t *nextp, /* out: next block to try */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_extlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock) /* out: start block allocated */
{ {
xfs_rtblock_t besti; /* best rtblock found so far */ struct xfs_mount *mp = args->mp;
xfs_rtblock_t bestlen; /* best length found so far */ xfs_rtxnum_t besti; /* best rtext found so far */
xfs_rtblock_t end; /* last rtblock in chunk */ xfs_rtxnum_t bestlen;/* best length found so far */
int error; /* error value */ xfs_rtxnum_t end; /* last rtext in chunk */
xfs_rtblock_t i; /* current rtblock trying */ int error;
xfs_rtblock_t next; /* next rtblock to try */ xfs_rtxnum_t i; /* current rtext trying */
xfs_rtxnum_t next; /* next rtext to try */
int stat; /* status from internal calls */ int stat; /* status from internal calls */
/* /*
* Loop over all the extents starting in this bitmap block, * Loop over all the extents starting in this bitmap block,
* looking for one that's long enough. * looking for one that's long enough.
*/ */
for (i = XFS_BLOCKTOBIT(mp, bbno), besti = -1, bestlen = 0, for (i = xfs_rbmblock_to_rtx(mp, bbno), besti = -1, bestlen = 0,
end = XFS_BLOCKTOBIT(mp, bbno + 1) - 1; end = xfs_rbmblock_to_rtx(mp, bbno + 1) - 1;
i <= end; i <= end;
i++) { i++) {
/* Make sure we don't scan off the end of the rt volume. */ /* Make sure we don't scan off the end of the rt volume. */
maxlen = min(mp->m_sb.sb_rextents, i + maxlen) - i; maxlen = xfs_rtallocate_clamp_len(mp, i, maxlen, prod);
/* /*
* See if there's a free extent of maxlen starting at i. * See if there's a free extent of maxlen starting at i.
* If it's not so then next will contain the first non-free. * If it's not so then next will contain the first non-free.
*/ */
error = xfs_rtcheck_range(mp, tp, i, maxlen, 1, &next, &stat); error = xfs_rtcheck_range(args, i, maxlen, 1, &next, &stat);
if (error) { if (error) {
return error; return error;
} }
...@@ -262,13 +272,12 @@ xfs_rtallocate_extent_block( ...@@ -262,13 +272,12 @@ xfs_rtallocate_extent_block(
/* /*
* i for maxlen is all free, allocate and return that. * i for maxlen is all free, allocate and return that.
*/ */
error = xfs_rtallocate_range(mp, tp, i, maxlen, rbpp, error = xfs_rtallocate_range(args, i, maxlen);
rsb);
if (error) { if (error) {
return error; return error;
} }
*len = maxlen; *len = maxlen;
*rtblock = i; *rtx = i;
return 0; return 0;
} }
/* /*
...@@ -278,7 +287,7 @@ xfs_rtallocate_extent_block( ...@@ -278,7 +287,7 @@ xfs_rtallocate_extent_block(
* so far, remember it. * so far, remember it.
*/ */
if (minlen < maxlen) { if (minlen < maxlen) {
xfs_rtblock_t thislen; /* this extent size */ xfs_rtxnum_t thislen; /* this extent size */
thislen = next - i; thislen = next - i;
if (thislen >= minlen && thislen > bestlen) { if (thislen >= minlen && thislen > bestlen) {
...@@ -290,7 +299,7 @@ xfs_rtallocate_extent_block( ...@@ -290,7 +299,7 @@ xfs_rtallocate_extent_block(
* If not done yet, find the start of the next free space. * If not done yet, find the start of the next free space.
*/ */
if (next < end) { if (next < end) {
error = xfs_rtfind_forw(mp, tp, next, end, &i); error = xfs_rtfind_forw(args, next, end, &i);
if (error) { if (error) {
return error; return error;
} }
...@@ -301,7 +310,7 @@ xfs_rtallocate_extent_block( ...@@ -301,7 +310,7 @@ xfs_rtallocate_extent_block(
* Searched the whole thing & didn't find a maxlen free extent. * Searched the whole thing & didn't find a maxlen free extent.
*/ */
if (minlen < maxlen && besti != -1) { if (minlen < maxlen && besti != -1) {
xfs_extlen_t p; /* amount to trim length by */ xfs_rtxlen_t p; /* amount to trim length by */
/* /*
* If size should be a multiple of prod, make that so. * If size should be a multiple of prod, make that so.
...@@ -315,51 +324,49 @@ xfs_rtallocate_extent_block( ...@@ -315,51 +324,49 @@ xfs_rtallocate_extent_block(
/* /*
* Allocate besti for bestlen & return that. * Allocate besti for bestlen & return that.
*/ */
error = xfs_rtallocate_range(mp, tp, besti, bestlen, rbpp, rsb); error = xfs_rtallocate_range(args, besti, bestlen);
if (error) { if (error) {
return error; return error;
} }
*len = bestlen; *len = bestlen;
*rtblock = besti; *rtx = besti;
return 0; return 0;
} }
/* /*
* Allocation failed. Set *nextp to the next block to try. * Allocation failed. Set *nextp to the next block to try.
*/ */
*nextp = next; *nextp = next;
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
/* /*
* Allocate an extent of length minlen<=len<=maxlen, starting at block * Allocate an extent of length minlen<=len<=maxlen, starting at block
* bno. If we don't get maxlen then use prod to trim the length, if given. * bno. If we don't get maxlen then use prod to trim the length, if given.
* Returns error; returns starting block in *rtblock. * Returns error; returns starting block in *rtx.
* The lengths are all in rtextents. * The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_exact( xfs_rtallocate_extent_exact(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_rtblock_t bno, /* starting block number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_extlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock) /* out: start block allocated */
{ {
int error; /* error value */ int error;
xfs_extlen_t i; /* extent length trimmed due to prod */ xfs_rtxlen_t i; /* extent length trimmed due to prod */
int isfree; /* extent is free */ int isfree; /* extent is free */
xfs_rtblock_t next; /* next block to try (dummy) */ xfs_rtxnum_t next; /* next rtext to try (dummy) */
ASSERT(minlen % prod == 0 && maxlen % prod == 0); ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0);
/* /*
* Check if the range in question (for maxlen) is free. * Check if the range in question (for maxlen) is free.
*/ */
error = xfs_rtcheck_range(mp, tp, bno, maxlen, 1, &next, &isfree); error = xfs_rtcheck_range(args, start, maxlen, 1, &next, &isfree);
if (error) { if (error) {
return error; return error;
} }
...@@ -367,23 +374,23 @@ xfs_rtallocate_extent_exact( ...@@ -367,23 +374,23 @@ xfs_rtallocate_extent_exact(
/* /*
* If it is, allocate it and return success. * If it is, allocate it and return success.
*/ */
error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb); error = xfs_rtallocate_range(args, start, maxlen);
if (error) { if (error) {
return error; return error;
} }
*len = maxlen; *len = maxlen;
*rtblock = bno; *rtx = start;
return 0; return 0;
} }
/* /*
* If not, allocate what there is, if it's at least minlen. * If not, allocate what there is, if it's at least minlen.
*/ */
maxlen = next - bno; maxlen = next - start;
if (maxlen < minlen) { if (maxlen < minlen) {
/* /*
* Failed, return failure status. * Failed, return failure status.
*/ */
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
/* /*
...@@ -395,81 +402,82 @@ xfs_rtallocate_extent_exact( ...@@ -395,81 +402,82 @@ xfs_rtallocate_extent_exact(
/* /*
* Now we can't do it, return failure status. * Now we can't do it, return failure status.
*/ */
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
} }
/* /*
* Allocate what we can and return it. * Allocate what we can and return it.
*/ */
error = xfs_rtallocate_range(mp, tp, bno, maxlen, rbpp, rsb); error = xfs_rtallocate_range(args, start, maxlen);
if (error) { if (error) {
return error; return error;
} }
*len = maxlen; *len = maxlen;
*rtblock = bno; *rtx = start;
return 0; return 0;
} }
/* /*
* Allocate an extent of length minlen<=len<=maxlen, starting as near * Allocate an extent of length minlen<=len<=maxlen, starting as near
* to bno as possible. If we don't get maxlen then use prod to trim * to start as possible. If we don't get maxlen then use prod to trim
* the length, if given. The lengths are all in rtextents. * the length, if given. The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_near( xfs_rtallocate_extent_near(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_rtblock_t bno, /* starting block number to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_extlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock) /* out: start block allocated */
{ {
int any; /* any useful extents from summary */ struct xfs_mount *mp = args->mp;
xfs_rtblock_t bbno; /* bitmap block number */ int maxlog; /* max useful extent from summary */
int error; /* error value */ xfs_fileoff_t bbno; /* bitmap block number */
int error;
int i; /* bitmap block offset (loop control) */ int i; /* bitmap block offset (loop control) */
int j; /* secondary loop control */ int j; /* secondary loop control */
int log2len; /* log2 of minlen */ int log2len; /* log2 of minlen */
xfs_rtblock_t n; /* next block to try */ xfs_rtxnum_t n; /* next rtext to try */
xfs_rtblock_t r; /* result block */ xfs_rtxnum_t r; /* result rtext */
ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0);
ASSERT(minlen % prod == 0 && maxlen % prod == 0);
/* /*
* If the block number given is off the end, silently set it to * If the block number given is off the end, silently set it to
* the last block. * the last block.
*/ */
if (bno >= mp->m_sb.sb_rextents) if (start >= mp->m_sb.sb_rextents)
bno = mp->m_sb.sb_rextents - 1; start = mp->m_sb.sb_rextents - 1;
/* Make sure we don't run off the end of the rt volume. */ /* Make sure we don't run off the end of the rt volume. */
maxlen = min(mp->m_sb.sb_rextents, bno + maxlen) - bno; maxlen = xfs_rtallocate_clamp_len(mp, start, maxlen, prod);
if (maxlen < minlen) { if (maxlen < minlen) {
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
/* /*
* Try the exact allocation first. * Try the exact allocation first.
*/ */
error = xfs_rtallocate_extent_exact(mp, tp, bno, minlen, maxlen, len, error = xfs_rtallocate_extent_exact(args, start, minlen, maxlen, len,
rbpp, rsb, prod, &r); prod, &r);
if (error) { if (error) {
return error; return error;
} }
/* /*
* If the exact allocation worked, return that. * If the exact allocation worked, return that.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
*rtblock = r; *rtx = r;
return 0; return 0;
} }
bbno = XFS_BITTOBLOCK(mp, bno); bbno = xfs_rtx_to_rbmblock(mp, start);
i = 0; i = 0;
j = -1;
ASSERT(minlen != 0); ASSERT(minlen != 0);
log2len = xfs_highbit32(minlen); log2len = xfs_highbit32(minlen);
/* /*
...@@ -480,8 +488,8 @@ xfs_rtallocate_extent_near( ...@@ -480,8 +488,8 @@ xfs_rtallocate_extent_near(
* Get summary information of extents of all useful levels * Get summary information of extents of all useful levels
* starting in this bitmap block. * starting in this bitmap block.
*/ */
error = xfs_rtany_summary(mp, tp, log2len, mp->m_rsumlevels - 1, error = xfs_rtany_summary(args, log2len, mp->m_rsumlevels - 1,
bbno + i, rbpp, rsb, &any); bbno + i, &maxlog);
if (error) { if (error) {
return error; return error;
} }
...@@ -489,7 +497,10 @@ xfs_rtallocate_extent_near( ...@@ -489,7 +497,10 @@ xfs_rtallocate_extent_near(
* If there are any useful extents starting here, try * If there are any useful extents starting here, try
* allocating one. * allocating one.
*/ */
if (any) { if (maxlog >= 0) {
xfs_extlen_t maxavail =
min_t(xfs_rtblock_t, maxlen,
(1ULL << (maxlog + 1)) - 1);
/* /*
* On the positive side of the starting location. * On the positive side of the starting location.
*/ */
...@@ -498,17 +509,17 @@ xfs_rtallocate_extent_near( ...@@ -498,17 +509,17 @@ xfs_rtallocate_extent_near(
* Try to allocate an extent starting in * Try to allocate an extent starting in
* this block. * this block.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, error = xfs_rtallocate_extent_block(args,
bbno + i, minlen, maxlen, len, &n, rbpp, bbno + i, minlen, maxavail, len,
rsb, prod, &r); &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
/* /*
* If it worked, return it. * If it worked, return it.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
*rtblock = r; *rtx = r;
return 0; return 0;
} }
} }
...@@ -516,68 +527,46 @@ xfs_rtallocate_extent_near( ...@@ -516,68 +527,46 @@ xfs_rtallocate_extent_near(
* On the negative side of the starting location. * On the negative side of the starting location.
*/ */
else { /* i < 0 */ else { /* i < 0 */
int maxblocks;
/* /*
* Loop backwards through the bitmap blocks from * Loop backwards to find the end of the extent
* the starting point-1 up to where we are now. * we found in the realtime summary.
* There should be an extent which ends in this *
* bitmap block and is long enough. * maxblocks is the maximum possible number of
*/ * bitmap blocks from the start of the extent
for (j = -1; j > i; j--) { * to the end of the extent.
/*
* Grab the summary information for
* this bitmap block.
*/ */
error = xfs_rtany_summary(mp, tp, if (maxlog == 0)
log2len, mp->m_rsumlevels - 1, maxblocks = 0;
bbno + j, rbpp, rsb, &any); else if (maxlog < mp->m_blkbit_log)
if (error) { maxblocks = 1;
return error; else
} maxblocks = 2 << (maxlog - mp->m_blkbit_log);
/* /*
* If there's no extent given in the * We need to check bbno + i + maxblocks down to
* summary that means the extent we * bbno + i. We already checked bbno down to
* found must carry over from an * bbno + j + 1, so we don't need to check those
* earlier block. If there is an * again.
* extent given, we've already tried
* that allocation, don't do it again.
*/ */
if (any) j = min(i + maxblocks, j);
continue; for (; j >= i; j--) {
error = xfs_rtallocate_extent_block(mp, error = xfs_rtallocate_extent_block(args,
tp, bbno + j, minlen, maxlen, bbno + j, minlen,
len, &n, rbpp, rsb, prod, &r); maxavail, len, &n, prod,
&r);
if (error) { if (error) {
return error; return error;
} }
/* /*
* If it works, return the extent. * If it works, return the extent.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
*rtblock = r; *rtx = r;
return 0; return 0;
} }
} }
/*
* There weren't intervening bitmap blocks
* with a long enough extent, or the
* allocation didn't work for some reason
* (i.e. it's a little * too short).
* Try to allocate from the summary block
* that we found.
*/
error = xfs_rtallocate_extent_block(mp, tp,
bbno + i, minlen, maxlen, len, &n, rbpp,
rsb, prod, &r);
if (error) {
return error;
}
/*
* If it works, return the extent.
*/
if (r != NULLRTBLOCK) {
*rtblock = r;
return 0;
}
} }
} }
/* /*
...@@ -610,7 +599,7 @@ xfs_rtallocate_extent_near( ...@@ -610,7 +599,7 @@ xfs_rtallocate_extent_near(
else else
break; break;
} }
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
...@@ -619,26 +608,25 @@ xfs_rtallocate_extent_near( ...@@ -619,26 +608,25 @@ xfs_rtallocate_extent_near(
* specified. If we don't get maxlen then use prod to trim * specified. If we don't get maxlen then use prod to trim
* the length, if given. The lengths are all in rtextents. * the length, if given. The lengths are all in rtextents.
*/ */
STATIC int /* error */ STATIC int
xfs_rtallocate_extent_size( xfs_rtallocate_extent_size(
xfs_mount_t *mp, /* file system mount point */ struct xfs_rtalloc_args *args,
xfs_trans_t *tp, /* transaction pointer */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t *len, /* out: actual length allocated */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t prod, /* extent product factor */
struct xfs_buf **rbpp, /* in/out: summary block buffer */ xfs_rtxnum_t *rtx) /* out: start rtext allocated */
xfs_fsblock_t *rsb, /* in/out: summary block number */
xfs_extlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock) /* out: start block allocated */
{ {
int error; /* error value */ struct xfs_mount *mp = args->mp;
int i; /* bitmap block number */ int error;
xfs_fileoff_t i; /* bitmap block number */
int l; /* level number (loop control) */ int l; /* level number (loop control) */
xfs_rtblock_t n; /* next block to be tried */ xfs_rtxnum_t n; /* next rtext to be tried */
xfs_rtblock_t r; /* result block number */ xfs_rtxnum_t r; /* result rtext number */
xfs_suminfo_t sum; /* summary information for extents */ xfs_suminfo_t sum; /* summary information for extents */
ASSERT(minlen % prod == 0 && maxlen % prod == 0); ASSERT(minlen % prod == 0);
ASSERT(maxlen % prod == 0);
ASSERT(maxlen != 0); ASSERT(maxlen != 0);
/* /*
...@@ -656,8 +644,7 @@ xfs_rtallocate_extent_size( ...@@ -656,8 +644,7 @@ xfs_rtallocate_extent_size(
/* /*
* Get the summary for this level/block. * Get the summary for this level/block.
*/ */
error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, error = xfs_rtget_summary(args, l, i, &sum);
&sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -669,16 +656,16 @@ xfs_rtallocate_extent_size( ...@@ -669,16 +656,16 @@ xfs_rtallocate_extent_size(
/* /*
* Try allocating the extent. * Try allocating the extent.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, i, maxlen, error = xfs_rtallocate_extent_block(args, i, maxlen,
maxlen, len, &n, rbpp, rsb, prod, &r); maxlen, len, &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
/* /*
* If it worked, return that. * If it worked, return that.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
*rtblock = r; *rtx = r;
return 0; return 0;
} }
/* /*
...@@ -686,8 +673,8 @@ xfs_rtallocate_extent_size( ...@@ -686,8 +673,8 @@ xfs_rtallocate_extent_size(
* allocator is beyond the next bitmap block, * allocator is beyond the next bitmap block,
* skip to that bitmap block. * skip to that bitmap block.
*/ */
if (XFS_BITTOBLOCK(mp, n) > i + 1) if (xfs_rtx_to_rbmblock(mp, n) > i + 1)
i = XFS_BITTOBLOCK(mp, n) - 1; i = xfs_rtx_to_rbmblock(mp, n) - 1;
} }
} }
/* /*
...@@ -695,7 +682,7 @@ xfs_rtallocate_extent_size( ...@@ -695,7 +682,7 @@ xfs_rtallocate_extent_size(
* we're asking for a fixed size extent. * we're asking for a fixed size extent.
*/ */
if (minlen > --maxlen) { if (minlen > --maxlen) {
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
ASSERT(minlen != 0); ASSERT(minlen != 0);
...@@ -715,8 +702,7 @@ xfs_rtallocate_extent_size( ...@@ -715,8 +702,7 @@ xfs_rtallocate_extent_size(
/* /*
* Get the summary information for this level/block. * Get the summary information for this level/block.
*/ */
error = xfs_rtget_summary(mp, tp, l, i, rbpp, rsb, error = xfs_rtget_summary(args, l, i, &sum);
&sum);
if (error) { if (error) {
return error; return error;
} }
...@@ -730,18 +716,18 @@ xfs_rtallocate_extent_size( ...@@ -730,18 +716,18 @@ xfs_rtallocate_extent_size(
* minlen/maxlen are in the possible range for * minlen/maxlen are in the possible range for
* this summary level. * this summary level.
*/ */
error = xfs_rtallocate_extent_block(mp, tp, i, error = xfs_rtallocate_extent_block(args, i,
XFS_RTMAX(minlen, 1 << l), XFS_RTMAX(minlen, 1 << l),
XFS_RTMIN(maxlen, (1 << (l + 1)) - 1), XFS_RTMIN(maxlen, (1 << (l + 1)) - 1),
len, &n, rbpp, rsb, prod, &r); len, &n, prod, &r);
if (error) { if (error) {
return error; return error;
} }
/* /*
* If it worked, return that extent. * If it worked, return that extent.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
*rtblock = r; *rtx = r;
return 0; return 0;
} }
/* /*
...@@ -749,14 +735,14 @@ xfs_rtallocate_extent_size( ...@@ -749,14 +735,14 @@ xfs_rtallocate_extent_size(
* allocator is beyond the next bitmap block, * allocator is beyond the next bitmap block,
* skip to that bitmap block. * skip to that bitmap block.
*/ */
if (XFS_BITTOBLOCK(mp, n) > i + 1) if (xfs_rtx_to_rbmblock(mp, n) > i + 1)
i = XFS_BITTOBLOCK(mp, n) - 1; i = xfs_rtx_to_rbmblock(mp, n) - 1;
} }
} }
/* /*
* Got nothing, return failure. * Got nothing, return failure.
*/ */
*rtblock = NULLRTBLOCK; *rtx = NULLRTEXTNO;
return 0; return 0;
} }
...@@ -886,12 +872,14 @@ xfs_alloc_rsum_cache( ...@@ -886,12 +872,14 @@ xfs_alloc_rsum_cache(
xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */ xfs_extlen_t rbmblocks) /* number of rt bitmap blocks */
{ {
/* /*
* The rsum cache is initialized to all zeroes, which is trivially a * The rsum cache is initialized to the maximum value, which is
* lower bound on the minimum level with any free extents. We can * trivially an upper bound on the maximum level with any free extents.
* continue without the cache if it couldn't be allocated. * We can continue without the cache if it couldn't be allocated.
*/ */
mp->m_rsum_cache = kvzalloc(rbmblocks, GFP_KERNEL); mp->m_rsum_cache = kvmalloc(rbmblocks, GFP_KERNEL);
if (!mp->m_rsum_cache) if (mp->m_rsum_cache)
memset(mp->m_rsum_cache, -1, rbmblocks);
else
xfs_warn(mp, "could not allocate realtime summary cache"); xfs_warn(mp, "could not allocate realtime summary cache");
} }
...@@ -907,13 +895,13 @@ xfs_growfs_rt( ...@@ -907,13 +895,13 @@ xfs_growfs_rt(
xfs_mount_t *mp, /* mount point for filesystem */ xfs_mount_t *mp, /* mount point for filesystem */
xfs_growfs_rt_t *in) /* growfs rt input struct */ xfs_growfs_rt_t *in) /* growfs rt input struct */
{ {
xfs_rtblock_t bmbno; /* bitmap block number */ xfs_fileoff_t bmbno; /* bitmap block number */
struct xfs_buf *bp; /* temporary buffer */ struct xfs_buf *bp; /* temporary buffer */
int error; /* error return value */ int error; /* error return value */
xfs_mount_t *nmp; /* new (fake) mount structure */ xfs_mount_t *nmp; /* new (fake) mount structure */
xfs_rfsblock_t nrblocks; /* new number of realtime blocks */ xfs_rfsblock_t nrblocks; /* new number of realtime blocks */
xfs_extlen_t nrbmblocks; /* new number of rt bitmap blocks */ xfs_extlen_t nrbmblocks; /* new number of rt bitmap blocks */
xfs_rtblock_t nrextents; /* new number of realtime extents */ xfs_rtxnum_t nrextents; /* new number of realtime extents */
uint8_t nrextslog; /* new log2 of sb_rextents */ uint8_t nrextslog; /* new log2 of sb_rextents */
xfs_extlen_t nrsumblocks; /* new number of summary blocks */ xfs_extlen_t nrsumblocks; /* new number of summary blocks */
uint nrsumlevels; /* new rt summary levels */ uint nrsumlevels; /* new rt summary levels */
...@@ -922,7 +910,6 @@ xfs_growfs_rt( ...@@ -922,7 +910,6 @@ xfs_growfs_rt(
xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */ xfs_extlen_t rbmblocks; /* current number of rt bitmap blocks */
xfs_extlen_t rsumblocks; /* current number of rt summary blks */ xfs_extlen_t rsumblocks; /* current number of rt summary blks */
xfs_sb_t *sbp; /* old superblock */ xfs_sb_t *sbp; /* old superblock */
xfs_fsblock_t sumbno; /* summary block number */
uint8_t *rsum_cache; /* old summary cache */ uint8_t *rsum_cache; /* old summary cache */
sbp = &mp->m_sb; sbp = &mp->m_sb;
...@@ -954,7 +941,7 @@ xfs_growfs_rt( ...@@ -954,7 +941,7 @@ xfs_growfs_rt(
return -EINVAL; return -EINVAL;
/* Unsupported realtime features. */ /* Unsupported realtime features. */
if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp)) if (xfs_has_rmapbt(mp) || xfs_has_reflink(mp) || xfs_has_quota(mp))
return -EOPNOTSUPP; return -EOPNOTSUPP;
nrblocks = in->newblocks; nrblocks = in->newblocks;
...@@ -976,11 +963,10 @@ xfs_growfs_rt( ...@@ -976,11 +963,10 @@ xfs_growfs_rt(
*/ */
nrextents = nrblocks; nrextents = nrblocks;
do_div(nrextents, in->extsize); do_div(nrextents, in->extsize);
nrbmblocks = howmany_64(nrextents, NBBY * sbp->sb_blocksize); nrbmblocks = xfs_rtbitmap_blockcount(mp, nrextents);
nrextslog = xfs_highbit32(nrextents); nrextslog = xfs_highbit32(nrextents);
nrsumlevels = nrextslog + 1; nrsumlevels = nrextslog + 1;
nrsumsize = (uint)sizeof(xfs_suminfo_t) * nrsumlevels * nrbmblocks; nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels, nrbmblocks);
nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks); nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
/* /*
* New summary size can't be more than half the size of * New summary size can't be more than half the size of
...@@ -1023,6 +1009,12 @@ xfs_growfs_rt( ...@@ -1023,6 +1009,12 @@ xfs_growfs_rt(
((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0); ((sbp->sb_rextents & ((1 << mp->m_blkbit_log) - 1)) != 0);
bmbno < nrbmblocks; bmbno < nrbmblocks;
bmbno++) { bmbno++) {
struct xfs_rtalloc_args args = {
.mp = mp,
};
struct xfs_rtalloc_args nargs = {
.mp = nmp,
};
struct xfs_trans *tp; struct xfs_trans *tp;
xfs_rfsblock_t nrblocks_step; xfs_rfsblock_t nrblocks_step;
...@@ -1032,19 +1024,17 @@ xfs_growfs_rt( ...@@ -1032,19 +1024,17 @@ xfs_growfs_rt(
* Calculate new sb and mount fields for this round. * Calculate new sb and mount fields for this round.
*/ */
nsbp->sb_rextsize = in->extsize; nsbp->sb_rextsize = in->extsize;
nmp->m_rtxblklog = -1; /* don't use shift or masking */
nsbp->sb_rbmblocks = bmbno + 1; nsbp->sb_rbmblocks = bmbno + 1;
nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize * nrblocks_step = (bmbno + 1) * NBBY * nsbp->sb_blocksize *
nsbp->sb_rextsize; nsbp->sb_rextsize;
nsbp->sb_rblocks = min(nrblocks, nrblocks_step); nsbp->sb_rblocks = min(nrblocks, nrblocks_step);
nsbp->sb_rextents = nsbp->sb_rblocks; nsbp->sb_rextents = xfs_rtb_to_rtx(nmp, nsbp->sb_rblocks);
do_div(nsbp->sb_rextents, nsbp->sb_rextsize);
ASSERT(nsbp->sb_rextents != 0); ASSERT(nsbp->sb_rextents != 0);
nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents); nsbp->sb_rextslog = xfs_highbit32(nsbp->sb_rextents);
nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1; nrsumlevels = nmp->m_rsumlevels = nsbp->sb_rextslog + 1;
nrsumsize = nrsumblocks = xfs_rtsummary_blockcount(mp, nrsumlevels,
(uint)sizeof(xfs_suminfo_t) * nrsumlevels * nsbp->sb_rbmblocks);
nsbp->sb_rbmblocks;
nrsumblocks = XFS_B_TO_FSB(mp, nrsumsize);
nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks); nmp->m_rsumsize = nrsumsize = XFS_FSB_TO_B(mp, nrsumblocks);
/* /*
* Start a transaction, get the log reservation. * Start a transaction, get the log reservation.
...@@ -1053,6 +1043,9 @@ xfs_growfs_rt( ...@@ -1053,6 +1043,9 @@ xfs_growfs_rt(
&tp); &tp);
if (error) if (error)
break; break;
args.tp = tp;
nargs.tp = tp;
/* /*
* Lock out other callers by grabbing the bitmap inode lock. * Lock out other callers by grabbing the bitmap inode lock.
*/ */
...@@ -1086,7 +1079,7 @@ xfs_growfs_rt( ...@@ -1086,7 +1079,7 @@ xfs_growfs_rt(
*/ */
if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks || if (sbp->sb_rbmblocks != nsbp->sb_rbmblocks ||
mp->m_rsumlevels != nmp->m_rsumlevels) { mp->m_rsumlevels != nmp->m_rsumlevels) {
error = xfs_rtcopy_summary(mp, nmp, tp); error = xfs_rtcopy_summary(&args, &nargs);
if (error) if (error)
goto error_cancel; goto error_cancel;
} }
...@@ -1111,9 +1104,9 @@ xfs_growfs_rt( ...@@ -1111,9 +1104,9 @@ xfs_growfs_rt(
/* /*
* Free new extent. * Free new extent.
*/ */
bp = NULL; error = xfs_rtfree_range(&nargs, sbp->sb_rextents,
error = xfs_rtfree_range(nmp, tp, sbp->sb_rextents, nsbp->sb_rextents - sbp->sb_rextents);
nsbp->sb_rextents - sbp->sb_rextents, &bp, &sumbno); xfs_rtbuf_cache_relse(&nargs);
if (error) { if (error) {
error_cancel: error_cancel:
xfs_trans_cancel(tp); xfs_trans_cancel(tp);
...@@ -1171,59 +1164,60 @@ xfs_growfs_rt( ...@@ -1171,59 +1164,60 @@ xfs_growfs_rt(
* parameters. The length units are all in realtime extents, as is the * parameters. The length units are all in realtime extents, as is the
* result block number. * result block number.
*/ */
int /* error */ int
xfs_rtallocate_extent( xfs_rtallocate_extent(
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_rtblock_t bno, /* starting block number to allocate */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t *len, /* out: actual length allocated */
int wasdel, /* was a delayed allocation extent */ int wasdel, /* was a delayed allocation extent */
xfs_extlen_t prod, /* extent product factor */ xfs_rtxlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock) /* out: start block allocated */ xfs_rtxnum_t *rtblock) /* out: start rtext allocated */
{ {
xfs_mount_t *mp = tp->t_mountp; struct xfs_rtalloc_args args = {
.mp = tp->t_mountp,
.tp = tp,
};
int error; /* error value */ int error; /* error value */
xfs_rtblock_t r; /* result allocated block */ xfs_rtxnum_t r; /* result allocated rtext */
xfs_fsblock_t sb; /* summary file block number */
struct xfs_buf *sumbp; /* summary file block buffer */
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(args.mp->m_rbmip, XFS_ILOCK_EXCL));
ASSERT(minlen > 0 && minlen <= maxlen); ASSERT(minlen > 0 && minlen <= maxlen);
/* /*
* If prod is set then figure out what to do to minlen and maxlen. * If prod is set then figure out what to do to minlen and maxlen.
*/ */
if (prod > 1) { if (prod > 1) {
xfs_extlen_t i; xfs_rtxlen_t i;
if ((i = maxlen % prod)) if ((i = maxlen % prod))
maxlen -= i; maxlen -= i;
if ((i = minlen % prod)) if ((i = minlen % prod))
minlen += prod - i; minlen += prod - i;
if (maxlen < minlen) { if (maxlen < minlen) {
*rtblock = NULLRTBLOCK; *rtblock = NULLRTEXTNO;
return 0; return 0;
} }
} }
retry: retry:
sumbp = NULL; if (start == 0) {
if (bno == 0) { error = xfs_rtallocate_extent_size(&args, minlen,
error = xfs_rtallocate_extent_size(mp, tp, minlen, maxlen, len, maxlen, len, prod, &r);
&sumbp, &sb, prod, &r);
} else { } else {
error = xfs_rtallocate_extent_near(mp, tp, bno, minlen, maxlen, error = xfs_rtallocate_extent_near(&args, start, minlen,
len, &sumbp, &sb, prod, &r); maxlen, len, prod, &r);
} }
xfs_rtbuf_cache_relse(&args);
if (error) if (error)
return error; return error;
/* /*
* If it worked, update the superblock. * If it worked, update the superblock.
*/ */
if (r != NULLRTBLOCK) { if (r != NULLRTEXTNO) {
long slen = (long)*len; long slen = (long)*len;
ASSERT(*len >= minlen && *len <= maxlen); ASSERT(*len >= minlen && *len <= maxlen);
...@@ -1250,6 +1244,7 @@ xfs_rtmount_init( ...@@ -1250,6 +1244,7 @@ xfs_rtmount_init(
struct xfs_buf *bp; /* buffer for last block of subvolume */ struct xfs_buf *bp; /* buffer for last block of subvolume */
struct xfs_sb *sbp; /* filesystem superblock copy in mount */ struct xfs_sb *sbp; /* filesystem superblock copy in mount */
xfs_daddr_t d; /* address of last block of subvolume */ xfs_daddr_t d; /* address of last block of subvolume */
unsigned int rsumblocks;
int error; int error;
sbp = &mp->m_sb; sbp = &mp->m_sb;
...@@ -1261,10 +1256,9 @@ xfs_rtmount_init( ...@@ -1261,10 +1256,9 @@ xfs_rtmount_init(
return -ENODEV; return -ENODEV;
} }
mp->m_rsumlevels = sbp->sb_rextslog + 1; mp->m_rsumlevels = sbp->sb_rextslog + 1;
mp->m_rsumsize = rsumblocks = xfs_rtsummary_blockcount(mp, mp->m_rsumlevels,
(uint)sizeof(xfs_suminfo_t) * mp->m_rsumlevels * mp->m_sb.sb_rbmblocks);
sbp->sb_rbmblocks; mp->m_rsumsize = XFS_FSB_TO_B(mp, rsumblocks);
mp->m_rsumsize = roundup(mp->m_rsumsize, sbp->sb_blocksize);
mp->m_rbmip = mp->m_rsumip = NULL; mp->m_rbmip = mp->m_rsumip = NULL;
/* /*
* Check that the realtime section is an ok size. * Check that the realtime section is an ok size.
...@@ -1422,23 +1416,23 @@ int /* error */ ...@@ -1422,23 +1416,23 @@ int /* error */
xfs_rtpick_extent( xfs_rtpick_extent(
xfs_mount_t *mp, /* file system mount point */ xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */ xfs_trans_t *tp, /* transaction pointer */
xfs_extlen_t len, /* allocation length (rtextents) */ xfs_rtxlen_t len, /* allocation length (rtextents) */
xfs_rtblock_t *pick) /* result rt extent */ xfs_rtxnum_t *pick) /* result rt extent */
{ {
xfs_rtblock_t b; /* result block */ xfs_rtxnum_t b; /* result rtext */
int log2; /* log of sequence number */ int log2; /* log of sequence number */
uint64_t resid; /* residual after log removed */ uint64_t resid; /* residual after log removed */
uint64_t seq; /* sequence number of file creation */ uint64_t seq; /* sequence number of file creation */
struct timespec64 ts; /* temporary timespec64 storage */ struct timespec64 ts; /* timespec in inode */
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
ts = inode_get_atime(VFS_I(mp->m_rbmip));
if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) { if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) {
mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;
seq = 0; seq = 0;
} else { } else {
ts = inode_get_atime(VFS_I(mp->m_rbmip)); seq = ts.tv_sec;
seq = (uint64_t)ts.tv_sec;
} }
if ((log2 = xfs_highbit64(seq)) == -1) if ((log2 = xfs_highbit64(seq)) == -1)
b = 0; b = 0;
...@@ -1451,7 +1445,7 @@ xfs_rtpick_extent( ...@@ -1451,7 +1445,7 @@ xfs_rtpick_extent(
if (b + len > mp->m_sb.sb_rextents) if (b + len > mp->m_sb.sb_rextents)
b = mp->m_sb.sb_rextents - len; b = mp->m_sb.sb_rextents - len;
} }
ts.tv_sec = (time64_t)seq + 1; ts.tv_sec = seq + 1;
inode_set_atime_to_ts(VFS_I(mp->m_rbmip), ts); inode_set_atime_to_ts(VFS_I(mp->m_rbmip), ts);
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
*pick = b; *pick = b;
......
...@@ -11,22 +11,6 @@ ...@@ -11,22 +11,6 @@
struct xfs_mount; struct xfs_mount;
struct xfs_trans; struct xfs_trans;
/*
* XXX: Most of the realtime allocation functions deal in units of realtime
* extents, not realtime blocks. This looks funny when paired with the type
* name and screams for a larger cleanup.
*/
struct xfs_rtalloc_rec {
xfs_rtblock_t ar_startext;
xfs_rtblock_t ar_extcount;
};
typedef int (*xfs_rtalloc_query_range_fn)(
struct xfs_mount *mp,
struct xfs_trans *tp,
const struct xfs_rtalloc_rec *rec,
void *priv);
#ifdef CONFIG_XFS_RT #ifdef CONFIG_XFS_RT
/* /*
* Function prototypes for exported functions. * Function prototypes for exported functions.
...@@ -40,23 +24,14 @@ typedef int (*xfs_rtalloc_query_range_fn)( ...@@ -40,23 +24,14 @@ typedef int (*xfs_rtalloc_query_range_fn)(
int /* error */ int /* error */
xfs_rtallocate_extent( xfs_rtallocate_extent(
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_rtblock_t bno, /* starting block number to allocate */ xfs_rtxnum_t start, /* starting rtext number to allocate */
xfs_extlen_t minlen, /* minimum length to allocate */ xfs_rtxlen_t minlen, /* minimum length to allocate */
xfs_extlen_t maxlen, /* maximum length to allocate */ xfs_rtxlen_t maxlen, /* maximum length to allocate */
xfs_extlen_t *len, /* out: actual length allocated */ xfs_rtxlen_t *len, /* out: actual length allocated */
int wasdel, /* was a delayed allocation extent */ int wasdel, /* was a delayed allocation extent */
xfs_extlen_t prod, /* extent product factor */ xfs_rtxlen_t prod, /* extent product factor */
xfs_rtblock_t *rtblock); /* out: start block allocated */ xfs_rtxnum_t *rtblock); /* out: start rtext allocated */
/*
* Free an extent in the realtime subvolume. Length is expressed in
* realtime extents, as is the block number.
*/
int /* error */
xfs_rtfree_extent(
struct xfs_trans *tp, /* transaction pointer */
xfs_rtblock_t bno, /* starting block number to free */
xfs_extlen_t len); /* length of extent freed */
/* /*
* Initialize realtime fields in the mount structure. * Initialize realtime fields in the mount structure.
...@@ -87,8 +62,8 @@ int /* error */ ...@@ -87,8 +62,8 @@ int /* error */
xfs_rtpick_extent( xfs_rtpick_extent(
struct xfs_mount *mp, /* file system mount point */ struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_extlen_t len, /* allocation length (rtextents) */ xfs_rtxlen_t len, /* allocation length (rtextents) */
xfs_rtblock_t *pick); /* result rt extent */ xfs_rtxnum_t *pick); /* result rt extent */
/* /*
* Grow the realtime area of the filesystem. * Grow the realtime area of the filesystem.
...@@ -98,54 +73,11 @@ xfs_growfs_rt( ...@@ -98,54 +73,11 @@ xfs_growfs_rt(
struct xfs_mount *mp, /* file system mount structure */ struct xfs_mount *mp, /* file system mount structure */
xfs_growfs_rt_t *in); /* user supplied growfs struct */ xfs_growfs_rt_t *in); /* user supplied growfs struct */
/*
* From xfs_rtbitmap.c
*/
int xfs_rtbuf_get(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t block, int issum, struct xfs_buf **bpp);
int xfs_rtcheck_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len, int val,
xfs_rtblock_t *new, int *stat);
int xfs_rtfind_back(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_rtblock_t limit,
xfs_rtblock_t *rtblock);
int xfs_rtfind_forw(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_rtblock_t limit,
xfs_rtblock_t *rtblock);
int xfs_rtmodify_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len, int val);
int xfs_rtmodify_summary_int(struct xfs_mount *mp, struct xfs_trans *tp,
int log, xfs_rtblock_t bbno, int delta,
struct xfs_buf **rbpp, xfs_fsblock_t *rsb,
xfs_suminfo_t *sum);
int xfs_rtmodify_summary(struct xfs_mount *mp, struct xfs_trans *tp, int log,
xfs_rtblock_t bbno, int delta, struct xfs_buf **rbpp,
xfs_fsblock_t *rsb);
int xfs_rtfree_range(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len,
struct xfs_buf **rbpp, xfs_fsblock_t *rsb);
int xfs_rtalloc_query_range(struct xfs_mount *mp, struct xfs_trans *tp,
const struct xfs_rtalloc_rec *low_rec,
const struct xfs_rtalloc_rec *high_rec,
xfs_rtalloc_query_range_fn fn, void *priv);
int xfs_rtalloc_query_all(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtalloc_query_range_fn fn,
void *priv);
bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
int xfs_rtalloc_extent_is_free(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_rtblock_t start, xfs_extlen_t len,
bool *is_free);
int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp); int xfs_rtalloc_reinit_frextents(struct xfs_mount *mp);
#else #else
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS) # define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (-ENOSYS)
# define xfs_rtfree_extent(t,b,l) (ENOSYS) # define xfs_rtpick_extent(m,t,l,rb) (-ENOSYS)
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS) # define xfs_growfs_rt(mp,in) (-ENOSYS)
# define xfs_growfs_rt(mp,in) (ENOSYS)
# define xfs_rtalloc_query_range(t,l,h,f,p) (ENOSYS)
# define xfs_rtalloc_query_all(m,t,f,p) (ENOSYS)
# define xfs_rtbuf_get(m,t,b,i,p) (ENOSYS)
# define xfs_verify_rtbno(m, r) (false)
# define xfs_rtalloc_extent_is_free(m,t,s,l,i) (ENOSYS)
# define xfs_rtalloc_reinit_frextents(m) (0) # define xfs_rtalloc_reinit_frextents(m) (0)
static inline int /* error */ static inline int /* error */
xfs_rtmount_init( xfs_rtmount_init(
...@@ -157,7 +89,7 @@ xfs_rtmount_init( ...@@ -157,7 +89,7 @@ xfs_rtmount_init(
xfs_warn(mp, "Not built with CONFIG_XFS_RT"); xfs_warn(mp, "Not built with CONFIG_XFS_RT");
return -ENOSYS; return -ENOSYS;
} }
# define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (-ENOSYS))
# define xfs_rtunmount_inodes(m) # define xfs_rtunmount_inodes(m)
#endif /* CONFIG_XFS_RT */ #endif /* CONFIG_XFS_RT */
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "xfs_xattr.h" #include "xfs_xattr.h"
#include "xfs_iunlink_item.h" #include "xfs_iunlink_item.h"
#include "xfs_dahash_test.h" #include "xfs_dahash_test.h"
#include "xfs_rtbitmap.h"
#include "scrub/stats.h" #include "scrub/stats.h"
#include <linux/magic.h> #include <linux/magic.h>
...@@ -896,7 +897,7 @@ xfs_fs_statfs( ...@@ -896,7 +897,7 @@ xfs_fs_statfs(
statp->f_blocks = sbp->sb_rblocks; statp->f_blocks = sbp->sb_rblocks;
freertx = percpu_counter_sum_positive(&mp->m_frextents); freertx = percpu_counter_sum_positive(&mp->m_frextents);
statp->f_bavail = statp->f_bfree = freertx * sbp->sb_rextsize; statp->f_bavail = statp->f_bfree = xfs_rtx_to_rtb(mp, freertx);
} }
return 0; return 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "xfs_dquot_item.h" #include "xfs_dquot_item.h"
#include "xfs_dquot.h" #include "xfs_dquot.h"
#include "xfs_icache.h" #include "xfs_icache.h"
#include "xfs_rtbitmap.h"
struct kmem_cache *xfs_trans_cache; struct kmem_cache *xfs_trans_cache;
...@@ -655,6 +656,10 @@ xfs_trans_unreserve_and_mod_sb( ...@@ -655,6 +656,10 @@ xfs_trans_unreserve_and_mod_sb(
mp->m_sb.sb_agcount += tp->t_agcount_delta; mp->m_sb.sb_agcount += tp->t_agcount_delta;
mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta; mp->m_sb.sb_imax_pct += tp->t_imaxpct_delta;
mp->m_sb.sb_rextsize += tp->t_rextsize_delta; mp->m_sb.sb_rextsize += tp->t_rextsize_delta;
if (tp->t_rextsize_delta) {
mp->m_rtxblklog = log2_if_power2(mp->m_sb.sb_rextsize);
mp->m_rtxblkmask = mask64_if_power2(mp->m_sb.sb_rextsize);
}
mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta; mp->m_sb.sb_rbmblocks += tp->t_rbmblocks_delta;
mp->m_sb.sb_rblocks += tp->t_rblocks_delta; mp->m_sb.sb_rblocks += tp->t_rblocks_delta;
mp->m_sb.sb_rextents += tp->t_rextents_delta; mp->m_sb.sb_rextents += tp->t_rextents_delta;
...@@ -1196,7 +1201,7 @@ xfs_trans_alloc_inode( ...@@ -1196,7 +1201,7 @@ xfs_trans_alloc_inode(
retry: retry:
error = xfs_trans_alloc(mp, resv, dblocks, error = xfs_trans_alloc(mp, resv, dblocks,
rblocks / mp->m_sb.sb_rextsize, xfs_extlen_to_rtxlen(mp, rblocks),
force ? XFS_TRANS_RESERVE : 0, &tp); force ? XFS_TRANS_RESERVE : 0, &tp);
if (error) if (error)
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment