diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_rtbitmap.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_rtbitmap.c | 147 |
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; |