[Ocfs2-tools-devel] [PATCH 39/50] fsck.ocfs2: Check refcount of clusters.

Tao Ma tao.ma at oracle.com
Tue Jan 19 17:18:10 PST 2010



Joel Becker wrote:
> On Mon, Jan 11, 2010 at 11:31:25PM +0800, Tao Ma wrote:
>> +		assert(extent->p_cpos >= cpos);
> 
> 	There are many asserts throughout this code.  I think asserting
> to trust your code is good, but I want to be sure they are true asserts.
> That is, these conditions can't happen because of corrupt disk data.
> They only happen if you messed up building data structures in earlier
> passes.  I think that's the case, but I just wanted to make sure ;-)
I will refactor the code so that it is more readable.

Regards,
Tao
> 
>> +static errcode_t o2fsck_check_clusters_in_refcount(o2fsck_state *ost,
>> +						   struct refcount_tree *tree,
>> +						   uint64_t p_cpos,
>> +						   uint32_t clusters,
>> +						   uint32_t refcount)
>> +{
> 
> 	Huge function, lots of gotos.  Is there any way you can make
> some sub-functions so that this is much more readable?  Even just break
> some of the checks out
> 
>> +	errcode_t ret = 0;
>> +	uint32_t rec_len;
>> +	struct ocfs2_refcount_rec tmp_rec, *rec = &tree->rec;
>> +	uint64_t cpos, range;
>> +	unsigned int len;
>> +	int index;
>> +
>> +	if (!clusters)
>> +		return 0;
>> +
>> +	/*
>> +	 * the previous check ended at tree->p_cend, and now we get
>> +	 * p_cpos, so any refcount record between p_cend and p_cpos
>> +	 * should be considered as redundant.
>> +	 */
>> +	cpos = tree->p_cend;
>> +	range = p_cpos - cpos;
>> +	while (range) {
>> +		len = range > UINT_MAX ? UINT_MAX : range;
>> +
>> +		ret = ocfs2_get_refcount_rec(ost->ost_fs, tree->root_buf,
>> +				     cpos, len, &tmp_rec,
>> +				     &index, tree->leaf_buf);
>> +		if (ret) {
>> +			com_err(whoami, ret, "while getting refcount rec at "
>> +				"%"PRIu64" in tree %"PRIu64,
>> +				cpos, tree->rf_blkno);
>> +			goto out;
>> +		}
>> +
>> +		if ((tmp_rec.r_refcount || tmp_rec.r_clusters != len) &&
>> +		    prompt(ost, PY, PR_REFCOUNT_REC_REDUNDANT,
>> +			   "refcount records among clusters (%"PRIu64
>> +			   ", %u) are found with no physical clusters "
>> +			   "corresponding to them. Remove them?", cpos, len)) {
>> +			ret = o2fsck_refcount_punch_hole(ost, tree, cpos, len);
>> +			if (ret) {
>> +				com_err(whoami, ret, "while punching "
>> +					"hole in (%"PRIu64", %u) in refcount "
>> +					"tree %"PRIu64,
>> +					cpos, len, tree->rf_blkno);
>> +				goto out;
>> +			}
>> +
>> +			/*
>> +			 * We have punch a hole at (cpos, len),
>> +			 * so fix the recorded index and r_offset in the tree
>> +			 * if we have read them.
>> +			 */
>> +			if (tree->index != -1) {
>> +				if (cpos + len >=
>> +				    rec->r_cpos + rec->r_clusters) {
>> +					tree->r_offset = 0;
>> +					tree->index = -1;
>> +				} else
>> +					tree->r_offset =
>> +						cpos + len - rec->r_cpos;
>> +			}
>> +		}
>> +
>> +		cpos += len;
>> +		range -= len;
>> +	}
> 
> 	Like, can this be a sub-function?
> 
>> +again:
>> +	if (tree->index == -1) {
>> +		ret = ocfs2_get_refcount_rec(ost->ost_fs, tree->root_buf,
>> +					     p_cpos, clusters, rec,
>> +					     &tree->index, tree->leaf_buf);
>> +		if (ret) {
>> +			com_err(whoami, ret, "while getting refcount rec at "
>> +				"%"PRIu64" in tree %"PRIu64,
>> +				p_cpos, tree->rf_blkno);
>> +			goto out;
>> +		}
>> +	}
>> +
>> +	/*
>> +	 * Actually ocfs2_get_refcount_rec will fake some refcount record
>> +	 * in case it can't find p_cpos in the refcount tree. So we really
>> +	 * shouldn't meet with a case rec->r_cpos + tree->r_offset > p_cpos.
>> +	 * And as for rec->r_cpos + tree->r_offset < p_pcos, it should already
>> +	 * be resolved by the previous punch_hole.
>> +	 */
>> +	assert(rec->r_cpos + tree->r_offset == p_cpos);
>> +
>> +	rec_len = ocfs2_min(p_cpos + clusters,
>> +			    (uint64_t)rec->r_cpos + rec->r_clusters) - p_cpos;
>> +	if (rec->r_refcount != refcount) {
>> +		if (prompt(ost, PY, PR_REFCOUNT_COUNT_INVALID,
>> +			   "clusters %"PRIu64 " with len %u have %u refcount "
>> +			   "while there are %u files point to them. "
>> +			   "Correct the refcount value?",
>> +			   p_cpos, rec_len, rec->r_refcount, refcount)) {
>> +			ret = o2fsck_change_refcount(ost, tree,
>> +						     p_cpos, rec_len, refcount);
>> +			if (ret) {
>> +				com_err(whoami, ret, "while updating refcount "
>> +					"%u at %"PRIu64" len %u in tree "
>> +					"%"PRIu64, refcount, p_cpos,
>> +					rec_len, tree->rf_blkno);
>> +				goto out;
>> +			}
>> +		} else {
>> +			/*
>> +			 * XXX:
>> +			 * Do we need to ask user for adding them to dup?
>> +			 */
>> +			o2fsck_mark_clusters_allocated(ost, p_cpos, rec_len);
>> +			ret = o2fsck_refcount_punch_hole(ost, tree,
>> +							 p_cpos, rec_len);
>> +			if (ret) {
>> +				com_err(whoami, ret, "while punching "
>> +					"hole at %"PRIu64"in refcount "
>> +					"tree %"PRIu64, p_cpos,
>> +					tree->rf_blkno);
>> +				goto out;
>> +			}
>> +
>> +			ret = o2fsck_clear_refcount(ost, tree, p_cpos, rec_len);
>> +			if (ret) {
>> +				com_err(whoami, ret,
>> +					"while clearing refcount for "
>> +					"cluster %"PRIu64" len %u in %"PRIu64,
>> +					p_cpos, rec_len, tree->rf_blkno);
>> +				goto out;
>> +			}
>> +		}
>> +	}
> 
> 	And this if block?  You get the idea.
> 
>> +/*
>> + * Given a refcount tree, check the refcounted clusters and their refcount.
>> + */
>> +static errcode_t o2fsck_check_refcount(o2fsck_state *ost,
>> +				       struct refcount_tree *tree)
>> +{
> 
> 	And let's try the same with this big function.
> 
> Joel
> 



More information about the Ocfs2-tools-devel mailing list