Skip to content

Commit

Permalink
gfs2: Also reflect single-block allocations in rgd->rd_extfail_pt
Browse files Browse the repository at this point in the history
Pass a non-NULL minext to gfs2_rbm_find even for single-block allocations.  In
gfs2_rbm_find, also set rgd->rd_extfail_pt when a single-block allocation
fails in a resource group: there is no reason for treating that case
differently.  In gfs2_reservation_check_and_update, only check how many free
blocks we have if more than one block is requested; we already know there's at
least one free block.

In addition, when allocating N blocks fails in gfs2_rbm_find, we need to set
rd_extfail_pt to N - 1 rather than N:  rd_extfail_pt defines the biggest
allocation that might still succeed.

Finally, reset rd_extfail_pt when updating the resource group statistics in
update_rgrp_lvb, as we already do in gfs2_rgrp_bh_get.

Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
  • Loading branch information
Andreas Gruenbacher committed Feb 17, 2021
1 parent 560b8eb commit f38e998
Showing 1 changed file with 10 additions and 8 deletions.
18 changes: 10 additions & 8 deletions fs/gfs2/rgrp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,8 @@ static int update_rgrp_lvb(struct gfs2_rgrpd *rgd)
rgd->rd_free = be32_to_cpu(rgd->rd_rgl->rl_free);
rgrp_set_bitmap_flags(rgd);
rgd->rd_free_clone = rgd->rd_free;
/* max out the rgrp allocation failure point */
rgd->rd_extfail_pt = rgd->rd_free;
rgd->rd_dinodes = be32_to_cpu(rgd->rd_rgl->rl_dinodes);
rgd->rd_igeneration = be64_to_cpu(rgd->rd_rgl->rl_igeneration);
return 0;
Expand Down Expand Up @@ -1676,7 +1678,7 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
* If we have a minimum extent length, then skip over any extent
* which is less than the min extent length in size.
*/
if (minext) {
if (minext > 1) {
extlen = gfs2_free_extlen(rbm, minext);
if (extlen <= maxext->len)
goto fail;
Expand Down Expand Up @@ -1711,7 +1713,7 @@ static int gfs2_reservation_check_and_update(struct gfs2_rbm *rbm,
* gfs2_rbm_find - Look for blocks of a particular state
* @rbm: Value/result starting position and final position
* @state: The state which we want to find
* @minext: Pointer to the requested extent length (NULL for a single block)
* @minext: Pointer to the requested extent length
* This is updated to be the actual reservation size.
* @ip: If set, check for reservations
* @nowrap: Stop looking at the end of the rgrp, rather than wrapping
Expand Down Expand Up @@ -1767,8 +1769,7 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
if (ip == NULL)
return 0;

ret = gfs2_reservation_check_and_update(rbm, ip,
minext ? *minext : 0,
ret = gfs2_reservation_check_and_update(rbm, ip, *minext,
&maxext);
if (ret == 0)
return 0;
Expand Down Expand Up @@ -1800,15 +1801,15 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
break;
}

if (minext == NULL || state != GFS2_BLKST_FREE)
if (state != GFS2_BLKST_FREE)
return -ENOSPC;

/* If the extent was too small, and it's smaller than the smallest
to have failed before, remember for future reference that it's
useless to search this rgrp again for this amount or more. */
if (wrapped && (scan_from_start || rbm->bii > last_bii) &&
*minext < rbm->rgd->rd_extfail_pt)
rbm->rgd->rd_extfail_pt = *minext;
rbm->rgd->rd_extfail_pt = *minext - 1;

/* If the maximum extent we found is big enough to fulfill the
minimum requirements, use it anyway. */
Expand Down Expand Up @@ -2382,14 +2383,15 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
struct buffer_head *dibh;
struct gfs2_rbm rbm = { .rgd = ip->i_res.rs_rgd, };
u64 block; /* block, within the file system scope */
u32 minext = 1;
int error;

gfs2_set_alloc_start(&rbm, ip, dinode);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, NULL, ip, false);
error = gfs2_rbm_find(&rbm, GFS2_BLKST_FREE, &minext, ip, false);

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

/* Since all blocks are reserved in advance, this shouldn't happen */
Expand Down

0 comments on commit f38e998

Please sign in to comment.