summaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2009-04-23 08:59:41 +0100
committerSteven Whitehouse <swhiteho@redhat.com>2009-04-23 10:07:37 +0100
commitd9ba7615bfd8bb06f79c853f9dfff9e93a837941 (patch)
tree647f6078a7804a53b4902b90942864942e9d425b /fs/gfs2
parentd8bd504ab800c8e9aadb983914a33e7166320bec (diff)
downloadlinux-d9ba7615bfd8bb06f79c853f9dfff9e93a837941.tar.gz
linux-d9ba7615bfd8bb06f79c853f9dfff9e93a837941.tar.bz2
linux-d9ba7615bfd8bb06f79c853f9dfff9e93a837941.zip
GFS2: Ensure that the inode goal block settings are updated
GFS2 has a goal block associated with each inode indicating the search start position for future block allocations (in fact there are two, but thats for backward compatibility with GFS1 as they are set to identical locations in GFS2). In some circumstances, depending on the ordering of updates to the inode it was possible for the goal block settings to not be updated on disk. This patch ensures that the goal block will always get updated, thus reducing the potential for searching the same (already allocated) blocks again when looking for free space during block allocation. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/rgrp.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index c9786a46cdfc..565038243fa2 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1444,10 +1444,12 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart,
u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct buffer_head *dibh;
struct gfs2_alloc *al = ip->i_alloc;
struct gfs2_rgrpd *rgd = al->al_rgd;
u32 goal, blk;
u64 block;
+ int error;
if (rgrp_contains_block(rgd, ip->i_goal))
goal = ip->i_goal - rgd->rd_data0;
@@ -1460,7 +1462,13 @@ u64 gfs2_alloc_block(struct gfs2_inode *ip, unsigned int *n)
rgd->rd_last_alloc = blk;
block = rgd->rd_data0 + blk;
ip->i_goal = block;
-
+ error = gfs2_meta_inode_buffer(ip, &dibh);
+ if (error == 0) {
+ struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data;
+ gfs2_trans_add_bh(ip->i_gl, dibh, 1);
+ di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal);
+ brelse(dibh);
+ }
gfs2_assert_withdraw(sdp, rgd->rd_free >= *n);
rgd->rd_free -= *n;