Skip to content

Commit

Permalink
GFS2: Speed up starting point selection for block allocation
Browse files Browse the repository at this point in the history
When setting the starting point for block allocation, there were calls
to both gfs2_rbm_to_block() and gfs2_rbm_from_block() in the common case
of there being an active reservation. The gfs2_rbm_from_block() function
can be quite slow, and since the two conversions were effectively a
no-op, it makes sense to avoid them entirely in this case.

There is no functional change here, but the code should be a bit more
efficient after this patch.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
  • Loading branch information
Steven Whitehouse committed Oct 2, 2013
1 parent 7b9cff4 commit 9e07f2c
Showing 1 changed file with 31 additions and 10 deletions.
41 changes: 31 additions & 10 deletions fs/gfs2/rgrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,35 @@ static void gfs2_adjust_reservation(struct gfs2_inode *ip,
spin_unlock(&rgd->rd_rsspin);
}

/**
* gfs2_set_alloc_start - Set starting point for block allocation
* @rbm: The rbm which will be set to the required location
* @ip: The gfs2 inode
* @dinode: Flag to say if allocation includes a new inode
*
* This sets the starting point from the reservation if one is active
* otherwise it falls back to guessing a start point based on the
* inode's goal block or the last allocation point in the rgrp.
*/

static void gfs2_set_alloc_start(struct gfs2_rbm *rbm,
const struct gfs2_inode *ip, bool dinode)
{
u64 goal;

if (gfs2_rs_active(ip->i_res)) {
*rbm = ip->i_res->rs_rbm;
return;
}

if (!dinode && rgrp_contains_block(rbm->rgd, ip->i_goal))
goal = ip->i_goal;
else
goal = rbm->rgd->rd_last_alloc + rbm->rgd->rd_data0;

gfs2_rbm_from_block(rbm, goal);
}

/**
* gfs2_alloc_blocks - Allocate one or more blocks of data and/or a dinode
* @ip: the inode to allocate the block for
Expand All @@ -2151,22 +2180,14 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
struct buffer_head *dibh;
struct gfs2_rbm rbm = { .rgd = ip->i_rgd, };
unsigned int ndata;
u64 goal;
u64 block; /* block, within the file system scope */
int error;

if (gfs2_rs_active(ip->i_res))
goal = gfs2_rbm_to_block(&ip->i_res->rs_rbm);
else if (!dinode && rgrp_contains_block(rbm.rgd, ip->i_goal))
goal = ip->i_goal;
else
goal = rbm.rgd->rd_last_alloc + rbm.rgd->rd_data0;

gfs2_rbm_from_block(&rbm, goal);
gfs2_set_alloc_start(&rbm, ip, dinode);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, ip, false);

if (error == -ENOSPC) {
gfs2_rbm_from_block(&rbm, goal);
gfs2_set_alloc_start(&rbm, ip, dinode);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, 0, NULL, false);
}

Expand Down

0 comments on commit 9e07f2c

Please sign in to comment.