aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2012-08-25 13:21:47 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2012-09-24 05:47:21 -0400
commitc743ffd09fa7d3464c6f74767a3ae2ca5dc3ebf7 (patch)
treea3d6e4b359f6523c91f742b091c714ad72453c58 /fs/gfs2
parent9e733d3923fb0e4eeae7b827019332d246576a22 (diff)
GFS2: Fix unclaimed_blocks() wrapping bug and clean up
When rgd->rd_free_clone is less than rgd->rd_reserved, the unclaimed_blocks() calculation would wrap and produce incorrect results. This patch checks for this condition when this function is called from gfs2_mblk_search() In addition, the use of this particular function in other places in the code has been dropped by means of a general clean up of gfs2_inplace_reserve(). This function is now much easier to follow. Also the setting of the rgd->rd_last_alloc field is corrected. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/rgrp.c193
1 files changed, 88 insertions, 105 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 87ee0b70f818..886954126704 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1231,7 +1231,7 @@ static struct gfs2_blkreserv *rs_insert(struct gfs2_bitmap *bi,
1231 BUG_ON(!ip->i_res); 1231 BUG_ON(!ip->i_res);
1232 BUG_ON(gfs2_rs_active(rs)); 1232 BUG_ON(gfs2_rs_active(rs));
1233 /* Figure out where to put new node */ 1233 /* Figure out where to put new node */
1234 /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/ 1234
1235 while (*newn) { 1235 while (*newn) {
1236 struct gfs2_blkreserv *cur = 1236 struct gfs2_blkreserv *cur =
1237 rb_entry(*newn, struct gfs2_blkreserv, rs_node); 1237 rb_entry(*newn, struct gfs2_blkreserv, rs_node);
@@ -1276,17 +1276,16 @@ static u32 unclaimed_blocks(struct gfs2_rgrpd *rgd)
1276/** 1276/**
1277 * rg_mblk_search - find a group of multiple free blocks 1277 * rg_mblk_search - find a group of multiple free blocks
1278 * @rgd: the resource group descriptor 1278 * @rgd: the resource group descriptor
1279 * @rs: the block reservation
1280 * @ip: pointer to the inode for which we're reserving blocks 1279 * @ip: pointer to the inode for which we're reserving blocks
1280 * @requested: number of blocks required for this allocation
1281 * 1281 *
1282 * This is very similar to rgblk_search, except we're looking for whole 1282 * This is very similar to rgblk_search, except we're looking for whole
1283 * 64-bit words that represent a chunk of 32 free blocks. I'm only focusing 1283 * 64-bit words that represent a chunk of 32 free blocks. I'm only focusing
1284 * on aligned dwords for speed's sake. 1284 * on aligned dwords for speed's sake.
1285 * 1285 *
1286 * Returns: 0 if successful or BFITNOENT if there isn't enough free space
1287 */ 1286 */
1288 1287
1289static int rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, unsigned requested) 1288static void rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, unsigned requested)
1290{ 1289{
1291 struct gfs2_bitmap *bi = rgd->rd_bits; 1290 struct gfs2_bitmap *bi = rgd->rd_bits;
1292 const u32 length = rgd->rd_length; 1291 const u32 length = rgd->rd_length;
@@ -1299,11 +1298,16 @@ static int rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, unsigne
1299 u32 best_rs_bytes, unclaimed; 1298 u32 best_rs_bytes, unclaimed;
1300 int best_rs_blocks; 1299 int best_rs_blocks;
1301 1300
1301 if ((rgd->rd_free_clone < rgd->rd_reserved) ||
1302 (unclaimed_blocks(rgd) < max(requested, RGRP_RSRV_MINBLKS)))
1303 return;
1304
1302 /* Find bitmap block that contains bits for goal block */ 1305 /* Find bitmap block that contains bits for goal block */
1303 if (rgrp_contains_block(rgd, ip->i_goal)) 1306 if (rgrp_contains_block(rgd, ip->i_goal))
1304 goal = ip->i_goal - rgd->rd_data0; 1307 goal = ip->i_goal - rgd->rd_data0;
1305 else 1308 else
1306 goal = rgd->rd_last_alloc; 1309 goal = rgd->rd_last_alloc;
1310
1307 for (buf = 0; buf < length; buf++) { 1311 for (buf = 0; buf < length; buf++) {
1308 bi = rgd->rd_bits + buf; 1312 bi = rgd->rd_bits + buf;
1309 /* Convert scope of "goal" from rgrp-wide to within 1313 /* Convert scope of "goal" from rgrp-wide to within
@@ -1366,10 +1370,8 @@ do_search:
1366 BUG_ON(blk >= bi->bi_len * GFS2_NBBY); 1370 BUG_ON(blk >= bi->bi_len * GFS2_NBBY);
1367 rs = rs_insert(bi, ip, blk, 1371 rs = rs_insert(bi, ip, blk,
1368 rsv_bytes * GFS2_NBBY); 1372 rsv_bytes * GFS2_NBBY);
1369 if (IS_ERR(rs))
1370 return PTR_ERR(rs);
1371 if (rs) 1373 if (rs)
1372 return 0; 1374 return;
1373 } 1375 }
1374 ptr += ALIGN(search_bytes, sizeof(u64)); 1376 ptr += ALIGN(search_bytes, sizeof(u64));
1375 } 1377 }
@@ -1380,35 +1382,6 @@ skip:
1380 buf %= length; 1382 buf %= length;
1381 goal = 0; 1383 goal = 0;
1382 } 1384 }
1383
1384 return BFITNOENT;
1385}
1386
1387/**
1388 * try_rgrp_fit - See if a given reservation will fit in a given RG
1389 * @rgd: the RG data
1390 * @ip: the inode
1391 *
1392 * If there's room for the requested blocks to be allocated from the RG:
1393 * This will try to get a multi-block reservation first, and if that doesn't
1394 * fit, it will take what it can.
1395 *
1396 * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
1397 */
1398
1399static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip,
1400 unsigned requested)
1401{
1402 if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
1403 return 0;
1404 /* Look for a multi-block reservation. */
1405 if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS &&
1406 rg_mblk_search(rgd, ip, requested) != BFITNOENT)
1407 return 1;
1408 if (unclaimed_blocks(rgd) >= requested)
1409 return 1;
1410
1411 return 0;
1412} 1385}
1413 1386
1414/** 1387/**
@@ -1678,6 +1651,19 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
1678 return; 1651 return;
1679} 1652}
1680 1653
1654static bool gfs2_select_rgrp(struct gfs2_rgrpd **pos, const struct gfs2_rgrpd *begin)
1655{
1656 struct gfs2_rgrpd *rgd = *pos;
1657
1658 rgd = gfs2_rgrpd_get_next(rgd);
1659 if (rgd == NULL)
1660 rgd = gfs2_rgrpd_get_next(NULL);
1661 *pos = rgd;
1662 if (rgd != begin) /* If we didn't wrap */
1663 return true;
1664 return false;
1665}
1666
1681/** 1667/**
1682 * gfs2_inplace_reserve - Reserve space in the filesystem 1668 * gfs2_inplace_reserve - Reserve space in the filesystem
1683 * @ip: the inode to reserve space for 1669 * @ip: the inode to reserve space for
@@ -1697,10 +1683,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
1697 1683
1698 if (sdp->sd_args.ar_rgrplvb) 1684 if (sdp->sd_args.ar_rgrplvb)
1699 flags |= GL_SKIP; 1685 flags |= GL_SKIP;
1700 if (gfs2_assert_warn(sdp, requested)) { 1686 if (gfs2_assert_warn(sdp, requested))
1701 error = -EINVAL; 1687 return -EINVAL;
1702 goto out;
1703 }
1704 if (gfs2_rs_active(rs)) { 1688 if (gfs2_rs_active(rs)) {
1705 begin = rs->rs_rbm.rgd; 1689 begin = rs->rs_rbm.rgd;
1706 flags = 0; /* Yoda: Do or do not. There is no try */ 1690 flags = 0; /* Yoda: Do or do not. There is no try */
@@ -1713,84 +1697,82 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, u32 requested)
1713 return -EBADSLT; 1697 return -EBADSLT;
1714 1698
1715 while (loops < 3) { 1699 while (loops < 3) {
1716 rg_locked = 0; 1700 rg_locked = 1;
1717 1701
1718 if (gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) { 1702 if (!gfs2_glock_is_locked_by_me(rs->rs_rbm.rgd->rd_gl)) {
1719 rg_locked = 1; 1703 rg_locked = 0;
1720 error = 0;
1721 } else if (!loops && !gfs2_rs_active(rs) &&
1722 rs->rs_rbm.rgd->rd_rs_cnt > RGRP_RSRV_MAX_CONTENDERS) {
1723 /* If the rgrp already is maxed out for contenders,
1724 we can eliminate it as a "first pass" without even
1725 requesting the rgrp glock. */
1726 error = GLR_TRYFAILED;
1727 } else {
1728 error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl, 1704 error = gfs2_glock_nq_init(rs->rs_rbm.rgd->rd_gl,
1729 LM_ST_EXCLUSIVE, flags, 1705 LM_ST_EXCLUSIVE, flags,
1730 &rs->rs_rgd_gh); 1706 &rs->rs_rgd_gh);
1731 if (!error && sdp->sd_args.ar_rgrplvb) { 1707 if (error == GLR_TRYFAILED)
1708 goto next_rgrp;
1709 if (unlikely(error))
1710 return error;
1711 if (sdp->sd_args.ar_rgrplvb) {
1732 error = update_rgrp_lvb(rs->rs_rbm.rgd); 1712 error = update_rgrp_lvb(rs->rs_rbm.rgd);
1733 if (error) { 1713 if (unlikely(error)) {
1734 gfs2_glock_dq_uninit(&rs->rs_rgd_gh); 1714 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1735 return error; 1715 return error;
1736 } 1716 }
1737 } 1717 }
1738 } 1718 }
1739 switch (error) {
1740 case 0:
1741 if (gfs2_rs_active(rs)) {
1742 if (unclaimed_blocks(rs->rs_rbm.rgd) +
1743 rs->rs_free >= requested) {
1744 ip->i_rgd = rs->rs_rbm.rgd;
1745 return 0;
1746 }
1747 /* We have a multi-block reservation, but the
1748 rgrp doesn't have enough free blocks to
1749 satisfy the request. Free the reservation
1750 and look for a suitable rgrp. */
1751 gfs2_rs_deltree(ip, rs);
1752 }
1753 if (try_rgrp_fit(rs->rs_rbm.rgd, ip, requested)) {
1754 if (sdp->sd_args.ar_rgrplvb)
1755 gfs2_rgrp_bh_get(rs->rs_rbm.rgd);
1756 ip->i_rgd = rs->rs_rbm.rgd;
1757 return 0;
1758 }
1759 if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK) {
1760 if (sdp->sd_args.ar_rgrplvb)
1761 gfs2_rgrp_bh_get(rs->rs_rbm.rgd);
1762 try_rgrp_unlink(rs->rs_rbm.rgd, &last_unlinked,
1763 ip->i_no_addr);
1764 }
1765 if (!rg_locked)
1766 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1767 /* fall through */
1768 case GLR_TRYFAILED:
1769 rs->rs_rbm.rgd = gfs2_rgrpd_get_next(rs->rs_rbm.rgd);
1770 rs->rs_rbm.rgd = rs->rs_rbm.rgd ? : begin; /* if NULL, wrap */
1771 if (rs->rs_rbm.rgd != begin) /* If we didn't wrap */
1772 break;
1773 1719
1774 flags &= ~LM_FLAG_TRY; 1720 /* Skip unuseable resource groups */
1775 loops++; 1721 if (rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
1776 /* Check that fs hasn't grown if writing to rindex */ 1722 goto skip_rgrp;
1777 if (ip == GFS2_I(sdp->sd_rindex) && 1723
1778 !sdp->sd_rindex_uptodate) { 1724 if (sdp->sd_args.ar_rgrplvb)
1779 error = gfs2_ri_update(ip); 1725 gfs2_rgrp_bh_get(rs->rs_rbm.rgd);
1780 if (error) 1726
1781 goto out; 1727 /* Get a reservation if we don't already have one */
1782 } else if (loops == 2) 1728 if (!gfs2_rs_active(rs))
1783 /* Flushing the log may release space */ 1729 rg_mblk_search(rs->rs_rbm.rgd, ip, requested);
1784 gfs2_log_flush(sdp, NULL); 1730
1785 break; 1731 /* Skip rgrps when we can't get a reservation on first pass */
1786 default: 1732 if (!gfs2_rs_active(rs) && (loops < 1))
1787 goto out; 1733 goto check_rgrp;
1734
1735 /* If rgrp has enough free space, use it */
1736 if (rs->rs_rbm.rgd->rd_free_clone >= requested) {
1737 ip->i_rgd = rs->rs_rbm.rgd;
1738 return 0;
1788 } 1739 }
1740
1741 /* Drop reservation, if we couldn't use reserved rgrp */
1742 if (gfs2_rs_active(rs))
1743 gfs2_rs_deltree(ip, rs);
1744check_rgrp:
1745 /* Check for unlinked inodes which can be reclaimed */
1746 if (rs->rs_rbm.rgd->rd_flags & GFS2_RDF_CHECK)
1747 try_rgrp_unlink(rs->rs_rbm.rgd, &last_unlinked,
1748 ip->i_no_addr);
1749skip_rgrp:
1750 /* Unlock rgrp if required */
1751 if (!rg_locked)
1752 gfs2_glock_dq_uninit(&rs->rs_rgd_gh);
1753next_rgrp:
1754 /* Find the next rgrp, and continue looking */
1755 if (gfs2_select_rgrp(&rs->rs_rbm.rgd, begin))
1756 continue;
1757
1758 /* If we've scanned all the rgrps, but found no free blocks
1759 * then this checks for some less likely conditions before
1760 * trying again.
1761 */
1762 flags &= ~LM_FLAG_TRY;
1763 loops++;
1764 /* Check that fs hasn't grown if writing to rindex */
1765 if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
1766 error = gfs2_ri_update(ip);
1767 if (error)
1768 return error;
1769 }
1770 /* Flushing the log may release space */
1771 if (loops == 2)
1772 gfs2_log_flush(sdp, NULL);
1789 } 1773 }
1790 error = -ENOSPC;
1791 1774
1792out: 1775 return -ENOSPC;
1793 return error;
1794} 1776}
1795 1777
1796/** 1778/**
@@ -2024,6 +2006,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
2024 2006
2025 gfs2_alloc_extent(&rbm, dinode, nblocks); 2007 gfs2_alloc_extent(&rbm, dinode, nblocks);
2026 block = gfs2_rbm_to_block(&rbm); 2008 block = gfs2_rbm_to_block(&rbm);
2009 rbm.rgd->rd_last_alloc = block - rbm.rgd->rd_data0;
2027 if (gfs2_rs_active(ip->i_res)) 2010 if (gfs2_rs_active(ip->i_res))
2028 gfs2_adjust_reservation(ip, &rbm, *nblocks); 2011 gfs2_adjust_reservation(ip, &rbm, *nblocks);
2029 ndata = *nblocks; 2012 ndata = *nblocks;