aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-09-01 08:31:59 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-10-21 07:39:34 -0400
commit54335b1fca27b84baa75b1f45985d98262003837 (patch)
treec6b21aff1759d86be56208e9981117e4383c3f47 /fs/gfs2/rgrp.c
parent8339ee543ece6e2dcc1bbd97d5350163c198cf00 (diff)
GFS2: Cache the most recently used resource group in the inode
This means that after the initial allocation for any inode, the last used resource group is cached in the inode for future use. This drastically reduces the number of lookups of resource groups in the common case, and this the contention on that data structure. The allocation algorithm is the same as previously, except that we always check to see if the goal block is within the cached rgrp first before going to the rbtree to look one up. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c51
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 88d5b75067a8..5bfb97002c2a 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -882,24 +882,21 @@ struct gfs2_alloc *gfs2_alloc_get(struct gfs2_inode *ip)
882/** 882/**
883 * try_rgrp_fit - See if a given reservation will fit in a given RG 883 * try_rgrp_fit - See if a given reservation will fit in a given RG
884 * @rgd: the RG data 884 * @rgd: the RG data
885 * @al: the struct gfs2_alloc structure describing the reservation 885 * @ip: the inode
886 * 886 *
887 * If there's room for the requested blocks to be allocated from the RG: 887 * If there's room for the requested blocks to be allocated from the RG:
888 * Sets the $al_rgd field in @al.
889 * 888 *
890 * Returns: 1 on success (it fits), 0 on failure (it doesn't fit) 889 * Returns: 1 on success (it fits), 0 on failure (it doesn't fit)
891 */ 890 */
892 891
893static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) 892static int try_rgrp_fit(const struct gfs2_rgrpd *rgd, const struct gfs2_inode *ip)
894{ 893{
894 const struct gfs2_alloc *al = ip->i_alloc;
895
895 if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR)) 896 if (rgd->rd_flags & (GFS2_RGF_NOALLOC | GFS2_RDF_ERROR))
896 return 0; 897 return 0;
897 898 if (rgd->rd_free_clone >= al->al_requested)
898 if (rgd->rd_free_clone >= al->al_requested) {
899 al->al_rgd = rgd;
900 return 1; 899 return 1;
901 }
902
903 return 0; 900 return 0;
904} 901}
905 902
@@ -985,7 +982,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
985 int error, rg_locked; 982 int error, rg_locked;
986 int loops = 0; 983 int loops = 0;
987 984
988 rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal); 985 if (ip->i_rgd && rgrp_contains_block(ip->i_rgd, ip->i_goal))
986 rgd = begin = ip->i_rgd;
987 else
988 rgd = begin = gfs2_blk2rgrpd(sdp, ip->i_goal);
989 989
990 if (rgd == NULL) 990 if (rgd == NULL)
991 return -EBADSLT; 991 return -EBADSLT;
@@ -1002,8 +1002,10 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1002 } 1002 }
1003 switch (error) { 1003 switch (error) {
1004 case 0: 1004 case 0:
1005 if (try_rgrp_fit(rgd, al)) 1005 if (try_rgrp_fit(rgd, ip)) {
1006 ip->i_rgd = rgd;
1006 return 0; 1007 return 0;
1008 }
1007 if (rgd->rd_flags & GFS2_RDF_CHECK) 1009 if (rgd->rd_flags & GFS2_RDF_CHECK)
1008 try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); 1010 try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr);
1009 if (!rg_locked) 1011 if (!rg_locked)
@@ -1014,7 +1016,6 @@ static int get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1014 if (rgd == begin) 1016 if (rgd == begin)
1015 loops++; 1017 loops++;
1016 break; 1018 break;
1017
1018 default: 1019 default:
1019 return error; 1020 return error;
1020 } 1021 }
@@ -1042,21 +1043,20 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip,
1042 if (gfs2_assert_warn(sdp, al->al_requested)) 1043 if (gfs2_assert_warn(sdp, al->al_requested))
1043 return -EINVAL; 1044 return -EINVAL;
1044 1045
1045try_again:
1046 do { 1046 do {
1047 error = get_local_rgrp(ip, &last_unlinked); 1047 error = get_local_rgrp(ip, &last_unlinked);
1048 /* If there is no space, flushing the log may release some */ 1048 if (error != -ENOSPC)
1049 if (error) { 1049 break;
1050 if (ip == GFS2_I(sdp->sd_rindex) && 1050 /* Check that fs hasn't grown if writing to rindex */
1051 !sdp->sd_rindex_uptodate) { 1051 if (ip == GFS2_I(sdp->sd_rindex) && !sdp->sd_rindex_uptodate) {
1052 error = gfs2_ri_update(ip); 1052 error = gfs2_ri_update(ip);
1053 if (error) 1053 if (error)
1054 return error; 1054 break;
1055 goto try_again; 1055 continue;
1056 }
1057 gfs2_log_flush(sdp, NULL);
1058 } 1056 }
1059 } while (error && tries++ < 3); 1057 /* Flushing the log may release space */
1058 gfs2_log_flush(sdp, NULL);
1059 } while (tries++ < 3);
1060 1060
1061 if (error) 1061 if (error)
1062 return error; 1062 return error;
@@ -1086,7 +1086,6 @@ void gfs2_inplace_release(struct gfs2_inode *ip)
1086 al->al_alloced, al->al_requested, al->al_file, 1086 al->al_alloced, al->al_requested, al->al_file,
1087 al->al_line); 1087 al->al_line);
1088 1088
1089 al->al_rgd = NULL;
1090 if (al->al_rgd_gh.gh_gl) 1089 if (al->al_rgd_gh.gh_gl)
1091 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1090 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1092} 1091}
@@ -1339,7 +1338,7 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
1339 if (al == NULL) 1338 if (al == NULL)
1340 return -ECANCELED; 1339 return -ECANCELED;
1341 1340
1342 rgd = al->al_rgd; 1341 rgd = ip->i_rgd;
1343 1342
1344 if (rgrp_contains_block(rgd, ip->i_goal)) 1343 if (rgrp_contains_block(rgd, ip->i_goal))
1345 goal = ip->i_goal - rgd->rd_data0; 1344 goal = ip->i_goal - rgd->rd_data0;
@@ -1398,7 +1397,7 @@ int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation)
1398{ 1397{
1399 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); 1398 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
1400 struct gfs2_alloc *al = dip->i_alloc; 1399 struct gfs2_alloc *al = dip->i_alloc;
1401 struct gfs2_rgrpd *rgd = al->al_rgd; 1400 struct gfs2_rgrpd *rgd = dip->i_rgd;
1402 u32 blk; 1401 u32 blk;
1403 u64 block; 1402 u64 block;
1404 unsigned int n = 1; 1403 unsigned int n = 1;