diff options
author | Bob Peterson <rpeterso@redhat.com> | 2013-11-25 06:16:25 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2014-01-03 04:58:08 -0500 |
commit | 5ea5050cec9c02e86ceb5e707a889003f895a690 (patch) | |
tree | 782554af83cacb80322874654782709dddd4174e /fs/gfs2/rgrp.c | |
parent | 1330edbeaf304703052fb583dd660b96309e4536 (diff) |
GFS2: Implement a "rgrp has no extents longer than X" scheme
With the preceding patch, we started accepting block reservations
smaller than the ideal size, which requires a lot more parsing of the
bitmaps. To reduce the amount of bitmap searching, this patch
implements a scheme whereby each rgrp keeps track of the point
at this multi-block reservations will fail.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 1ccf89ab42b6..797f1d3114ef 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -641,9 +641,13 @@ static void __rs_deltree(struct gfs2_blkreserv *rs) | |||
641 | /* return reserved blocks to the rgrp */ | 641 | /* return reserved blocks to the rgrp */ |
642 | BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free); | 642 | BUG_ON(rs->rs_rbm.rgd->rd_reserved < rs->rs_free); |
643 | rs->rs_rbm.rgd->rd_reserved -= rs->rs_free; | 643 | rs->rs_rbm.rgd->rd_reserved -= rs->rs_free; |
644 | /* The rgrp extent failure point is likely not to increase; | ||
645 | it will only do so if the freed blocks are somehow | ||
646 | contiguous with a span of free blocks that follows. Still, | ||
647 | it will force the number to be recalculated later. */ | ||
648 | rgd->rd_extfail_pt += rs->rs_free; | ||
644 | rs->rs_free = 0; | 649 | rs->rs_free = 0; |
645 | clear_bit(GBF_FULL, &bi->bi_flags); | 650 | clear_bit(GBF_FULL, &bi->bi_flags); |
646 | smp_mb__after_clear_bit(); | ||
647 | } | 651 | } |
648 | } | 652 | } |
649 | 653 | ||
@@ -1132,6 +1136,8 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
1132 | gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); | 1136 | gfs2_rgrp_in(rgd, (rgd->rd_bits[0].bi_bh)->b_data); |
1133 | rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); | 1137 | rgd->rd_flags |= (GFS2_RDF_UPTODATE | GFS2_RDF_CHECK); |
1134 | rgd->rd_free_clone = rgd->rd_free; | 1138 | rgd->rd_free_clone = rgd->rd_free; |
1139 | /* max out the rgrp allocation failure point */ | ||
1140 | rgd->rd_extfail_pt = rgd->rd_free; | ||
1135 | } | 1141 | } |
1136 | if (cpu_to_be32(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) { | 1142 | if (cpu_to_be32(GFS2_MAGIC) != rgd->rd_rgl->rl_magic) { |
1137 | rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd)); | 1143 | rgd->rd_rgl->rl_unlinked = cpu_to_be32(count_unlinked(rgd)); |
@@ -1593,6 +1599,8 @@ fail: | |||
1593 | * Side effects: | 1599 | * Side effects: |
1594 | * - If looking for free blocks, we set GBF_FULL on each bitmap which | 1600 | * - If looking for free blocks, we set GBF_FULL on each bitmap which |
1595 | * has no free blocks in it. | 1601 | * has no free blocks in it. |
1602 | * - If looking for free blocks, we set rd_extfail_pt on each rgrp which | ||
1603 | * has come up short on a free block search. | ||
1596 | * | 1604 | * |
1597 | * Returns: 0 on success, -ENOSPC if there is no block of the requested state | 1605 | * Returns: 0 on success, -ENOSPC if there is no block of the requested state |
1598 | */ | 1606 | */ |
@@ -1604,6 +1612,8 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext, | |||
1604 | struct buffer_head *bh; | 1612 | struct buffer_head *bh; |
1605 | int initial_bii; | 1613 | int initial_bii; |
1606 | u32 initial_offset; | 1614 | u32 initial_offset; |
1615 | int first_bii = rbm->bii; | ||
1616 | u32 first_offset = rbm->offset; | ||
1607 | u32 offset; | 1617 | u32 offset; |
1608 | u8 *buffer; | 1618 | u8 *buffer; |
1609 | int n = 0; | 1619 | int n = 0; |
@@ -1679,6 +1689,13 @@ next_iter: | |||
1679 | if (minext == NULL || state != GFS2_BLKST_FREE) | 1689 | if (minext == NULL || state != GFS2_BLKST_FREE) |
1680 | return -ENOSPC; | 1690 | return -ENOSPC; |
1681 | 1691 | ||
1692 | /* If the extent was too small, and it's smaller than the smallest | ||
1693 | to have failed before, remember for future reference that it's | ||
1694 | useless to search this rgrp again for this amount or more. */ | ||
1695 | if ((first_offset == 0) && (first_bii == 0) && | ||
1696 | (*minext < rbm->rgd->rd_extfail_pt)) | ||
1697 | rbm->rgd->rd_extfail_pt = *minext; | ||
1698 | |||
1682 | /* If the maximum extent we found is big enough to fulfill the | 1699 | /* If the maximum extent we found is big enough to fulfill the |
1683 | minimum requirements, use it anyway. */ | 1700 | minimum requirements, use it anyway. */ |
1684 | if (maxext.len) { | 1701 | if (maxext.len) { |
@@ -1924,7 +1941,9 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, const struct gfs2_alloc_parms *a | |||
1924 | } | 1941 | } |
1925 | 1942 | ||
1926 | /* Skip unuseable resource groups */ | 1943 | /* Skip unuseable resource groups */ |
1927 | if (rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) | 1944 | if ((rs->rs_rbm.rgd->rd_flags & (GFS2_RGF_NOALLOC | |
1945 | GFS2_RDF_ERROR)) || | ||
1946 | (ap && (ap->target > rs->rs_rbm.rgd->rd_extfail_pt))) | ||
1928 | goto skip_rgrp; | 1947 | goto skip_rgrp; |
1929 | 1948 | ||
1930 | if (sdp->sd_args.ar_rgrplvb) | 1949 | if (sdp->sd_args.ar_rgrplvb) |
@@ -2106,10 +2125,10 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
2106 | 2125 | ||
2107 | if (rgd == NULL) | 2126 | if (rgd == NULL) |
2108 | return 0; | 2127 | return 0; |
2109 | gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u r:%u\n", | 2128 | gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u r:%u e:%u\n", |
2110 | (unsigned long long)rgd->rd_addr, rgd->rd_flags, | 2129 | (unsigned long long)rgd->rd_addr, rgd->rd_flags, |
2111 | rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes, | 2130 | rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes, |
2112 | rgd->rd_reserved); | 2131 | rgd->rd_reserved, rgd->rd_extfail_pt); |
2113 | spin_lock(&rgd->rd_rsspin); | 2132 | spin_lock(&rgd->rd_rsspin); |
2114 | for (n = rb_first(&rgd->rd_rstree); n; n = rb_next(&trs->rs_node)) { | 2133 | for (n = rb_first(&rgd->rd_rstree); n; n = rb_next(&trs->rs_node)) { |
2115 | trs = rb_entry(n, struct gfs2_blkreserv, rs_node); | 2134 | trs = rb_entry(n, struct gfs2_blkreserv, rs_node); |
@@ -2228,9 +2247,10 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, | |||
2228 | 2247 | ||
2229 | /* Since all blocks are reserved in advance, this shouldn't happen */ | 2248 | /* Since all blocks are reserved in advance, this shouldn't happen */ |
2230 | if (error) { | 2249 | if (error) { |
2231 | fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d\n", | 2250 | fs_warn(sdp, "inum=%llu error=%d, nblocks=%u, full=%d fail_pt=%d\n", |
2232 | (unsigned long long)ip->i_no_addr, error, *nblocks, | 2251 | (unsigned long long)ip->i_no_addr, error, *nblocks, |
2233 | test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags)); | 2252 | test_bit(GBF_FULL, &rbm.rgd->rd_bits->bi_flags), |
2253 | rbm.rgd->rd_extfail_pt); | ||
2234 | goto rgrp_error; | 2254 | goto rgrp_error; |
2235 | } | 2255 | } |
2236 | 2256 | ||