Re: [PATCH 18/30] xfs: scrub inode btrees

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Oct 11, 2017 at 06:42:41PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
> 
> Check the records of the inode btrees to make sure that the values
> make sense given the inode records themselves.

.....

I think maybe I missed this first time around...

> +/* Check a particular inode with ir_free. */
> +STATIC int
> +xfs_scrub_iallocbt_check_cluster_freemask(
> +	struct xfs_scrub_btree		*bs,
> +	xfs_ino_t			fsino,
> +	xfs_agino_t			chunkino,
> +	xfs_agino_t			clusterino,
> +	struct xfs_inobt_rec_incore	*irec,
> +	struct xfs_buf			*bp)
> +{
> +	struct xfs_dinode		*dip;
> +	struct xfs_mount		*mp = bs->cur->bc_mp;
> +	bool				freemask_ok;
> +	bool				inuse;
> +	int				error;
> +
> +	dip = xfs_buf_offset(bp, clusterino * mp->m_sb.sb_inodesize);
> +	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
> +	    (dip->di_version >= 3 &&
> +	     be64_to_cpu(dip->di_ino) != fsino + clusterino)) {
> +		xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0);
> +		goto out;
> +	}
> +
> +	freemask_ok = (irec->ir_free & XFS_INOBT_MASK(chunkino + clusterino));

Ok, so if the inode if free, the corresponding bit in the mask
will be set....

> +	error = xfs_icache_inode_is_allocated(mp, bs->cur->bc_tp,
> +			fsino + clusterino, &inuse);
> +	if (error == -ENODATA) {
> +		/* Not cached, just read the disk buffer */
> +		freemask_ok ^= !!(dip->di_mode);

And this uses the lowest bit of the mask? How does that work?

/me spends 10 minutes trying to work out this function before he
realises that freemask_ok is a boolean, so the initial freemask
bit is collapsed down to a single bit.

Ok, that's definitely unexpected and not obvious from the code or
comments. The name "freemask_ok" is misleading the way it's used.
The first time it is set is means "inode is free", then after this
operation it means "inode matches free mask"....

> +		if (!bs->sc->try_harder && !freemask_ok)
> +			return -EDEADLOCK;
> +	} else if (error < 0) {
> +		/*
> +		 * Inode is only half assembled, or there was an IO error,
> +		 * or the verifier failed, so don't bother trying to check.
> +		 * The inode scrubber can deal with this.
> +		 */
> +		freemask_ok = true;

And here it means "we didn't check the free mask"

> +	} else {
> +		/* Inode is all there. */
> +		freemask_ok ^= inuse;

And here is means "inode matches free mask" again....

> +	}
> +	if (!freemask_ok)
> +		xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0);
> +out:
> +	return 0;

Can we rewrite this to be a little more obvious?

	bool		inode_is_free = false;
	bool		freemask_ok;
....
	if (irec->ir_free & XFS_INOBT_MASK(chunkino + clusterino))
		inode_is_free = true;
....
	if (error == -ENODATA) {
		freemask_ok = inode_is_free ^ !!(dip->di_mode);
....
	else if (error < 0) {
		/*
		 * Inode is only half assembled, .....
		 */
		goto out;
	} else {
		freemask_ok = inode_is_free ^ inuse;
	}

That's a lot more obvious what the code is checking...


> +/* Scrub an inobt/finobt record. */
> +STATIC int
> +xfs_scrub_iallocbt_helper(

s/helper/rec/

-Dave.
-- 
Dave Chinner
david@xxxxxxxxxxxxx
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux