diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/rgrp.c | 193 |
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 | ||
1289 | static int rg_mblk_search(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip, unsigned requested) | 1288 | static 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 | |||
1399 | static 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 | ||
1654 | static 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); | ||
1744 | check_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); | ||
1749 | skip_rgrp: | ||
1750 | /* Unlock rgrp if required */ | ||
1751 | if (!rg_locked) | ||
1752 | gfs2_glock_dq_uninit(&rs->rs_rgd_gh); | ||
1753 | next_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 | ||
1792 | out: | 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; |