summaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs/xfs_rtbitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/libxfs/xfs_rtbitmap.c')
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c147
1 files changed, 76 insertions, 71 deletions
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c
index 07841969ada9..5a2d5eaaba57 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.c
+++ b/fs/xfs/libxfs/xfs_rtbitmap.c
@@ -47,6 +47,23 @@ const struct xfs_buf_ops xfs_rtbuf_ops = {
.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.
* The buffer is returned read and locked.
@@ -59,13 +76,42 @@ xfs_rtbuf_get(
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_inode *ip; /* bitmap or summary inode */
struct xfs_bmbt_irec map;
+ enum xfs_blft type;
int nmap = 1;
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) {
+ *bpp = *cbpp;
+ 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);
if (error)
@@ -81,9 +127,9 @@ xfs_rtbuf_get(
if (error)
return error;
- xfs_trans_buf_set_type(args->tp, bp, issum ? XFS_BLFT_RTSUMMARY_BUF
- : XFS_BLFT_RTBITMAP_BUF);
- *bpp = bp;
+ xfs_trans_buf_set_type(args->tp, bp, type);
+ *cbpp = *bpp = bp;
+ *coffp = block;
return 0;
}
@@ -153,7 +199,6 @@ xfs_rtfind_back(
/*
* Different. Mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i = bit - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1;
return 0;
@@ -167,7 +212,6 @@ xfs_rtfind_back(
/*
* If done with this block, get the previous one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, --block, 0, &bp);
if (error) {
return error;
@@ -194,7 +238,6 @@ xfs_rtfind_back(
/*
* Different, mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1;
return 0;
@@ -208,7 +251,6 @@ xfs_rtfind_back(
/*
* If done with this block, get the previous one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, --block, 0, &bp);
if (error) {
return error;
@@ -236,7 +278,6 @@ xfs_rtfind_back(
/*
* Different, mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_NBWORD - 1 - XFS_RTHIBIT(wdiff);
*rtx = start - i + 1;
return 0;
@@ -246,7 +287,6 @@ xfs_rtfind_back(
/*
* No match, return that we scanned the whole area.
*/
- xfs_trans_brelse(args->tp, bp);
*rtx = start - i + 1;
return 0;
}
@@ -316,7 +356,6 @@ xfs_rtfind_forw(
/*
* Different. Mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i = XFS_RTLOBIT(wdiff) - bit;
*rtx = start + i - 1;
return 0;
@@ -330,7 +369,6 @@ xfs_rtfind_forw(
/*
* If done with this block, get the previous one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, ++block, 0, &bp);
if (error) {
return error;
@@ -357,7 +395,6 @@ xfs_rtfind_forw(
/*
* Different, mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_RTLOBIT(wdiff);
*rtx = start + i - 1;
return 0;
@@ -371,7 +408,6 @@ xfs_rtfind_forw(
/*
* If done with this block, get the next one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, ++block, 0, &bp);
if (error) {
return error;
@@ -397,7 +433,6 @@ xfs_rtfind_forw(
/*
* Different, mark where we are and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_RTLOBIT(wdiff);
*rtx = start + i - 1;
return 0;
@@ -407,7 +442,6 @@ xfs_rtfind_forw(
/*
* No match, return that we scanned the whole area.
*/
- xfs_trans_brelse(args->tp, bp);
*rtx = start + i - 1;
return 0;
}
@@ -442,8 +476,6 @@ xfs_rtmodify_summary_int(
int log, /* log2 of extent size */
xfs_fileoff_t bbno, /* bitmap block number */
int delta, /* change to make to summary info */
- struct xfs_buf **rbpp, /* in/out: summary block buffer */
- xfs_fileoff_t *rsb, /* in/out: summary block number */
xfs_suminfo_t *sum) /* out: summary info for this block */
{
struct xfs_mount *mp = args->mp;
@@ -461,30 +493,11 @@ xfs_rtmodify_summary_int(
* Compute the block number in the summary file.
*/
sb = xfs_rtsumoffs_to_block(mp, so);
- /*
- * If we have an old buffer, and the block number matches, use that.
- */
- 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(args->tp, *rbpp);
- error = xfs_rtbuf_get(args, sb, 1, &bp);
- if (error) {
- return error;
- }
- /*
- * Remember this buffer and block for the next call.
- */
- *rbpp = bp;
- *rsb = sb;
- }
+
+ error = xfs_rtbuf_get(args, sb, 1, &bp);
+ if (error)
+ return error;
+
/*
* Point to the summary information, modify/log it, and/or copy it out.
*/
@@ -512,11 +525,9 @@ xfs_rtmodify_summary(
struct xfs_rtalloc_args *args,
int log, /* log2 of extent size */
xfs_fileoff_t bbno, /* bitmap block number */
- int delta, /* change to make to summary info */
- struct xfs_buf **rbpp, /* in/out: summary block buffer */
- xfs_fileoff_t *rsb) /* in/out: summary block number */
+ int delta) /* in/out: summary block number */
{
- return xfs_rtmodify_summary_int(args, log, bbno, delta, rbpp, rsb, NULL);
+ return xfs_rtmodify_summary_int(args, log, bbno, delta, NULL);
}
/* Log rtbitmap block from the word @from to the byte before @next. */
@@ -687,9 +698,7 @@ int
xfs_rtfree_range(
struct xfs_rtalloc_args *args,
xfs_rtxnum_t start, /* starting rtext to free */
- xfs_rtxlen_t len, /* length to free */
- struct xfs_buf **rbpp, /* in/out: summary block buffer */
- xfs_fileoff_t *rsb) /* in/out: summary block number */
+ xfs_rtxlen_t len) /* in/out: summary block number */
{
struct xfs_mount *mp = args->mp;
xfs_rtxnum_t end; /* end of the freed extent */
@@ -718,7 +727,7 @@ xfs_rtfree_range(
* Find the next allocated block (end of allocated extent).
*/
error = xfs_rtfind_forw(args, end, mp->m_sb.sb_rextents - 1,
- &postblock);
+ &postblock);
if (error)
return error;
/*
@@ -727,8 +736,8 @@ xfs_rtfree_range(
*/
if (preblock < start) {
error = xfs_rtmodify_summary(args,
- XFS_RTBLOCKLOG(start - preblock),
- xfs_rtx_to_rbmblock(mp, preblock), -1, rbpp, rsb);
+ XFS_RTBLOCKLOG(start - preblock),
+ xfs_rtx_to_rbmblock(mp, preblock), -1);
if (error) {
return error;
}
@@ -739,8 +748,8 @@ xfs_rtfree_range(
*/
if (postblock > end) {
error = xfs_rtmodify_summary(args,
- XFS_RTBLOCKLOG(postblock - end),
- xfs_rtx_to_rbmblock(mp, end + 1), -1, rbpp, rsb);
+ XFS_RTBLOCKLOG(postblock - end),
+ xfs_rtx_to_rbmblock(mp, end + 1), -1);
if (error) {
return error;
}
@@ -749,10 +758,9 @@ xfs_rtfree_range(
* Increment the summary information corresponding to the entire
* (new) free extent.
*/
- error = xfs_rtmodify_summary(args,
- XFS_RTBLOCKLOG(postblock + 1 - preblock),
- xfs_rtx_to_rbmblock(mp, preblock), 1, rbpp, rsb);
- return error;
+ return xfs_rtmodify_summary(args,
+ XFS_RTBLOCKLOG(postblock + 1 - preblock),
+ xfs_rtx_to_rbmblock(mp, preblock), 1);
}
/*
@@ -822,7 +830,6 @@ xfs_rtcheck_range(
/*
* Different, compute first wrong bit and return.
*/
- xfs_trans_brelse(args->tp, bp);
i = XFS_RTLOBIT(wdiff) - bit;
*new = start + i;
*stat = 0;
@@ -837,7 +844,6 @@ xfs_rtcheck_range(
/*
* If done with this block, get the next one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, ++block, 0, &bp);
if (error) {
return error;
@@ -864,7 +870,6 @@ xfs_rtcheck_range(
/*
* Different, compute first wrong bit and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_RTLOBIT(wdiff);
*new = start + i;
*stat = 0;
@@ -879,7 +884,6 @@ xfs_rtcheck_range(
/*
* If done with this block, get the next one.
*/
- xfs_trans_brelse(args->tp, bp);
error = xfs_rtbuf_get(args, ++block, 0, &bp);
if (error) {
return error;
@@ -905,7 +909,6 @@ xfs_rtcheck_range(
/*
* Different, compute first wrong bit and return.
*/
- xfs_trans_brelse(args->tp, bp);
i += XFS_RTLOBIT(wdiff);
*new = start + i;
*stat = 0;
@@ -916,7 +919,6 @@ xfs_rtcheck_range(
/*
* Successful, return.
*/
- xfs_trans_brelse(args->tp, bp);
*new = start + i;
*stat = 1;
return 0;
@@ -961,8 +963,6 @@ xfs_rtfree_extent(
.tp = tp,
};
int error;
- xfs_fsblock_t sb; /* summary file block number */
- struct xfs_buf *sumbp = NULL; /* summary file block buffer */
ASSERT(mp->m_rbmip->i_itemp != NULL);
ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
@@ -974,10 +974,10 @@ xfs_rtfree_extent(
/*
* Free the range of realtime blocks.
*/
- error = xfs_rtfree_range(&args, start, len, &sumbp, &sb);
- if (error) {
- return error;
- }
+ error = xfs_rtfree_range(&args, start, len);
+ if (error)
+ goto out;
+
/*
* Mark more blocks free in the superblock.
*/
@@ -993,7 +993,10 @@ xfs_rtfree_extent(
*(uint64_t *)&VFS_I(mp->m_rbmip)->i_atime = 0;
xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
}
- return 0;
+ error = 0;
+out:
+ xfs_rtbuf_cache_relse(&args);
+ return error;
}
/*
@@ -1084,6 +1087,7 @@ xfs_rtalloc_query_range(
rtstart = rtend + 1;
}
+ xfs_rtbuf_cache_relse(&args);
return error;
}
@@ -1122,6 +1126,7 @@ xfs_rtalloc_extent_is_free(
int error;
error = xfs_rtcheck_range(&args, start, len, 1, &end, &matches);
+ xfs_rtbuf_cache_relse(&args);
if (error)
return error;