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

Commit 09010978 authored by Steven Whitehouse's avatar Steven Whitehouse
Browse files

GFS2: Improve resource group error handling



This patch improves the error handling in the case where we
discover that the summary information in the resource group
doesn't match the bitmap information while in the process of
allocating blocks. Originally this resulted in a kernel bug,
but this patch changes that so that we return -EIO and print
some messages explaining what went wrong, and how to fix it.

We also remember locally not to try and allocate from the
same rgrp again, so that a subsequent allocation in a
different rgrp should succeed.

Signed-off-by: default avatarSteven Whitehouse <swhiteho@redhat.com>
parent ef9e8b14
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -136,7 +136,9 @@ int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page)
		   and write it out to disk */

		unsigned int n = 1;
		block = gfs2_alloc_block(ip, &n);
		error = gfs2_alloc_block(ip, &block, &n);
		if (error)
			goto out_brelse;
		if (isdir) {
			gfs2_trans_add_unrevoke(GFS2_SB(&ip->i_inode), block, 1);
			error = gfs2_dir_get_new_buffer(ip, block, &bh);
@@ -476,8 +478,11 @@ static int gfs2_bmap_alloc(struct inode *inode, const sector_t lblock,
	blks = dblks + iblks;
	i = sheight;
	do {
		int error;
		n = blks - alloced;
		bn = gfs2_alloc_block(ip, &n);
		error = gfs2_alloc_block(ip, &bn, &n);
		if (error)
			return error;
		alloced += n;
		if (state != ALLOC_DATA || gfs2_is_jdata(ip))
			gfs2_trans_add_unrevoke(sdp, bn, n);
+9 −2
Original line number Diff line number Diff line
@@ -803,13 +803,20 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
{
	struct gfs2_inode *ip = GFS2_I(inode);
	unsigned int n = 1;
	u64 bn = gfs2_alloc_block(ip, &n);
	struct buffer_head *bh = gfs2_meta_new(ip->i_gl, bn);
	u64 bn;
	int error;
	struct buffer_head *bh;
	struct gfs2_leaf *leaf;
	struct gfs2_dirent *dent;
	struct qstr name = { .name = "", .len = 0, .hash = 0 };

	error = gfs2_alloc_block(ip, &bn, &n);
	if (error)
		return NULL;
	bh = gfs2_meta_new(ip->i_gl, bn);
	if (!bh)
		return NULL;

	gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, 1);
	gfs2_trans_add_bh(ip->i_gl, bh, 1);
	gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF);
+11 −3
Original line number Diff line number Diff line
@@ -582,8 +582,11 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp)
	struct gfs2_ea_header *ea;
	unsigned int n = 1;
	u64 block;
	int error;

	block = gfs2_alloc_block(ip, &n);
	error = gfs2_alloc_block(ip, &block, &n);
	if (error)
		return error;
	gfs2_trans_add_unrevoke(sdp, block, 1);
	*bhp = gfs2_meta_new(ip->i_gl, block);
	gfs2_trans_add_bh(ip->i_gl, *bhp, 1);
@@ -617,6 +620,7 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
		    struct gfs2_ea_request *er)
{
	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
	int error;

	ea->ea_data_len = cpu_to_be32(er->er_data_len);
	ea->ea_name_len = er->er_name_len;
@@ -642,7 +646,9 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
			int mh_size = sizeof(struct gfs2_meta_header);
			unsigned int n = 1;

			block = gfs2_alloc_block(ip, &n);
			error = gfs2_alloc_block(ip, &block, &n);
			if (error)
				return error;
			gfs2_trans_add_unrevoke(sdp, block, 1);
			bh = gfs2_meta_new(ip->i_gl, block);
			gfs2_trans_add_bh(ip->i_gl, bh, 1);
@@ -963,7 +969,9 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
	} else {
		u64 blk;
		unsigned int n = 1;
		blk = gfs2_alloc_block(ip, &n);
		error = gfs2_alloc_block(ip, &blk, &n);
		if (error)
			return error;
		gfs2_trans_add_unrevoke(sdp, blk, 1);
		indbh = gfs2_meta_new(ip->i_gl, blk);
		gfs2_trans_add_bh(ip->i_gl, indbh, 1);
+1 −19
Original line number Diff line number Diff line
@@ -309,24 +309,6 @@ static void rgrp_go_unlock(struct gfs2_holder *gh)
	gfs2_rgrp_bh_put(gh->gh_gl->gl_object);
}

/**
 * rgrp_go_dump - print out an rgrp
 * @seq: The iterator
 * @gl: The glock in question
 *
 */

static int rgrp_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
{
	const struct gfs2_rgrpd *rgd = gl->gl_object;
	if (rgd == NULL)
		return 0;
	gfs2_print_dbg(seq, " R: n:%llu f:%02x b:%u/%u i:%u\n",
		       (unsigned long long)rgd->rd_addr, rgd->rd_flags,
		       rgd->rd_free, rgd->rd_free_clone, rgd->rd_dinodes);
	return 0;
}

/**
 * trans_go_sync - promote/demote the transaction glock
 * @gl: the glock
@@ -410,7 +392,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = {
	.go_demote_ok = rgrp_go_demote_ok,
	.go_lock = rgrp_go_lock,
	.go_unlock = rgrp_go_unlock,
	.go_dump = rgrp_go_dump,
	.go_dump = gfs2_rgrp_dump,
	.go_type = LM_TYPE_RGRP,
	.go_min_hold_time = HZ / 5,
};
+4 −3
Original line number Diff line number Diff line
@@ -92,9 +92,10 @@ struct gfs2_rgrpd {
	unsigned int rd_bh_count;
	u32 rd_last_alloc;
	unsigned char rd_flags;
#define GFS2_RDF_CHECK        0x01      /* Need to check for unlinked inodes */
#define GFS2_RDF_NOALLOC      0x02      /* rg prohibits allocation */
#define GFS2_RDF_UPTODATE     0x04      /* rg is up to date */
#define GFS2_RDF_CHECK		0x10000000 /* check for unlinked inodes */
#define GFS2_RDF_UPTODATE	0x20000000 /* rg is up to date */
#define GFS2_RDF_ERROR		0x40000000 /* error in rg */
#define GFS2_RDF_MASK		0xf0000000 /* mask for internal flags */
};

enum gfs2_state_bits {
Loading