Commit f38e998f authored by Andreas Gruenbacher's avatar Andreas Gruenbacher
Browse files

gfs2: Also reflect single-block allocations in rgd->rd_extfail_pt



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: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent 560b8eba
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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;
@@ -1800,7 +1801,7 @@ 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
@@ -1808,7 +1809,7 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
	   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. */
@@ -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 */