Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6050b9c7 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

GFS2: Improve error handling in inode allocation



A little while back, block allocation was given some improved
error handling which meant that -EIO was returned in the case
of there being a problem in the resource group data. In addition
a message is printed explaning what went wrong and how to fix it.
This extends that error handling so that it also covers inode
allocation too.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent 440d6da2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -731,7 +731,7 @@ static int alloc_dinode(struct gfs2_inode *dip, u64 *no_addr, u64 *generation)
	if (error)
		goto out_ipreserv;

	*no_addr = gfs2_alloc_di(dip, generation);
	error = gfs2_alloc_di(dip, no_addr, generation);

	gfs2_trans_end(sdp);

+25 −11
Original line number Diff line number Diff line
@@ -1459,6 +1459,16 @@ int gfs2_rgrp_dump(struct seq_file *seq, const struct gfs2_glock *gl)
	return 0;
}

static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
{
	struct gfs2_sbd *sdp = rgd->rd_sbd;
	fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
	        (unsigned long long)rgd->rd_addr);
	fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
	gfs2_rgrp_dump(NULL, rgd->rd_gl);
	rgd->rd_flags |= GFS2_RDF_ERROR;
}

/**
 * gfs2_alloc_block - Allocate one or more blocks
 * @ip: the inode to allocate the block for
@@ -1520,22 +1530,20 @@ int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n)
	return 0;

rgrp_error:
	fs_warn(sdp, "rgrp %llu has an error, marking it readonly until umount\n",
	        (unsigned long long)rgd->rd_addr);
	fs_warn(sdp, "umount on all nodes and run fsck.gfs2 to fix the error\n");
	gfs2_rgrp_dump(NULL, rgd->rd_gl);
	rgd->rd_flags |= GFS2_RDF_ERROR;
	gfs2_rgrp_error(rgd);
	return -EIO;
}

/**
 * gfs2_alloc_di - Allocate a dinode
 * @dip: the directory that the inode is going in
 * @bn: the block number which is allocated
 * @generation: the generation number of the inode
 *
 * Returns: the block allocated
 * Returns: 0 on success or error
 */

u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
int gfs2_alloc_di(struct gfs2_inode *dip, u64 *bn, u64 *generation)
{
	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
	struct gfs2_alloc *al = dip->i_alloc;
@@ -1546,12 +1554,13 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)

	blk = rgblk_search(rgd, rgd->rd_last_alloc,
			   GFS2_BLKST_FREE, GFS2_BLKST_DINODE, &n);
	BUG_ON(blk == BFITNOENT);

	rgd->rd_last_alloc = blk;
	/* Since all blocks are reserved in advance, this shouldn't happen */
	if (blk == BFITNOENT)
		goto rgrp_error;

	rgd->rd_last_alloc = blk;
	block = rgd->rd_data0 + blk;

	gfs2_assert_withdraw(sdp, rgd->rd_free);
	rgd->rd_free--;
	rgd->rd_dinodes++;
@@ -1568,7 +1577,12 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation)
	rgd->rd_free_clone--;
	spin_unlock(&sdp->sd_rindex_spin);
	trace_gfs2_block_alloc(dip, block, 1, GFS2_BLKST_DINODE);
	return block;
	*bn = block;
	return 0;

rgrp_error:
	gfs2_rgrp_error(rgd);
	return -EIO;
}

/**
+1 −1
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ extern void gfs2_inplace_release(struct gfs2_inode *ip);
extern unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block);

extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
extern u64 gfs2_alloc_di(struct gfs2_inode *ip, u64 *generation);
extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);

extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);