public inbox for linux-xfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Dave Chinner <david@fromorbit.com>
To: Christoph Hellwig <hch@lst.de>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH 09/21] implement generic xfs_btree_increment
Date: Wed, 30 Jul 2008 12:06:45 +1000	[thread overview]
Message-ID: <20080730020645.GJ13395@disturbed> (raw)
In-Reply-To: <20080729193053.GJ19104@lst.de>

On Tue, Jul 29, 2008 at 09:30:53PM +0200, Christoph Hellwig wrote:
> From: Dave Chinner <dgc@sgi.com>
> 
> Because this is the first major generic btree routine this patch
> includes some infrastrucure, fistly a few routines to deal with
> a btree block that can be either in short or long form, and secondly
> xfs_btree_read_buf_block, which is the new central routine to read
> a btree block given a cursor.
> 
> [hch: split out from bigger patch and minor adaptions]
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

.....

> @@ -502,6 +506,23 @@ xfs_btree_setbuf(
>  	int			lev,	/* level in btree */
>  	struct xfs_buf		*bp);	/* new buffer to set */
>  
> +/*
> + * Common btree core entry points.
> + */
> +
> +int xfs_btree_increment(struct xfs_btree_cur *, int, int *);

I think for these interfaces it woul dbe better to include
variable names in the prototypes. i.e.:

int xfs_btree_increment(struct xfs_btree_cur *cur, int level, int *stat);

> Index: linux-2.6-xfs/fs/xfs/xfs_btree.c
> ===================================================================
> --- linux-2.6-xfs.orig/fs/xfs/xfs_btree.c	2008-07-21 04:41:51.000000000 +0200
> +++ linux-2.6-xfs/fs/xfs/xfs_btree.c	2008-07-21 06:47:21.000000000 +0200
> @@ -35,6 +35,7 @@
>  #include "xfs_dinode.h"
>  #include "xfs_inode.h"
>  #include "xfs_btree.h"
> +#include "xfs_btree_trace.h"
>  #include "xfs_ialloc.h"
>  #include "xfs_error.h"
>  
> @@ -829,3 +830,230 @@ xfs_btree_setbuf(
>  			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
>  	}
>  }
> +
> +STATIC int
> +xfs_btree_ptr_is_null(
> +	struct xfs_btree_cur	*cur,
> +	union xfs_btree_ptr	*ptr)
> +{
> +	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
> +		return be64_to_cpu(ptr->l) == NULLFSBLOCK;
> +	else
> +		return be32_to_cpu(ptr->s) == NULLAGBLOCK;

Can kill the else there:

	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
		return be64_to_cpu(ptr->l) == NULLFSBLOCK;
	return be32_to_cpu(ptr->s) == NULLAGBLOCK;

> +}
> +
> +/*
> + * Get/set/init sibling pointers
> + */
> +STATIC void
> +xfs_btree_get_sibling(
> +	struct xfs_btree_cur	*cur,
> +	struct xfs_btree_block	*block,
> +	union xfs_btree_ptr	*ptr,
> +	int			lr)
> +{
> +	ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB);
> +
> +	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
> +		if (lr == XFS_BB_RIGHTSIB)
> +			ptr->l = block->bb_u.l.bb_rightsib;
> +		else
> +			ptr->l = block->bb_u.l.bb_leftsib;
> +	} else {
> +		if (lr == XFS_BB_RIGHTSIB)
> +			ptr->s = block->bb_u.s.bb_rightsib;
> +		else
> +			ptr->s = block->bb_u.s.bb_leftsib;
> +	}
> +}

Should we use trinary notation for this? i.e:

{
	ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB);
	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
		ptr->l = (lr == XFS_BB_RIGHTSIB) ? block->bb_u.l.bb_rightsib
						 : block->bb_u.l.bb_leftsib;
	} else {
		ptr->s = (lr == XFS_BB_RIGHTSIB) ? block->bb_u.s.bb_rightsib
						 : block->bb_u.s.bb_leftsib;
	}
}

> +STATIC xfs_daddr_t
> +xfs_btree_ptr_to_daddr(
> +	struct xfs_btree_cur	*cur,
> +	union xfs_btree_ptr	*ptr)
> +{
> +	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
> +		ASSERT(be64_to_cpu(ptr->l) != NULLFSBLOCK);
> +
> +		return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
> +	} else {
> +		ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
> +		ASSERT(be32_to_cpu(ptr->s) != NULLAGBLOCK);
> +
> +		return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
> +					be32_to_cpu(ptr->s));
> +	}
> +}

Can kill the else here as well...

> +/*
> + * Read in the buffer at the given ptr and return the buffer and
> + * the block pointer within the buffer.
> + */
> +STATIC int
> +xfs_btree_read_buf_block(
> +	struct xfs_btree_cur	*cur,
> +	union xfs_btree_ptr	*ptr,
> +	int			level,
> +	int			flags,
> +	struct xfs_btree_block	**block,
> +	struct xfs_buf		**bpp)
> +{
> +	struct xfs_mount	*mp = cur->bc_mp;
> +	xfs_daddr_t		d;
> +	int			error;
> +
> +	/* need to sort out how callers deal with failures first */
> +	ASSERT(!(flags & XFS_BUF_TRYLOCK));
> +
> +	d = xfs_btree_ptr_to_daddr(cur, ptr);
> +	error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
> +				   mp->m_bsize, flags, bpp);
> +	if (error)
> +		return error;
> +
> +	ASSERT(*bpp != NULL);
> +	ASSERT(!XFS_BUF_GETERROR(*bpp));
> +
> +	xfs_btree_set_refs(cur, *bpp);
> +	*block = XFS_BUF_TO_BLOCK(*bpp);
> +
> +	return xfs_btree_check_block(cur, *block, level, *bpp);
> +}

Hmmm - if xfs_btree_check_block() returns an error, we won't release
the buffer in the error handling path. While this may not be a
problem right now (as the only error is EFSCORRUPTED) we want to be
able to recover from errors here in the future so we should really
exit cleanly form this function....

> +/*
> + * Increment cursor by one record at the level.
> + * For nonzero levels the leaf-ward information is untouched.
> + */
> +int						/* error */
> +xfs_btree_increment(
> +	struct xfs_btree_cur	*cur,
> +	int			level,
> +	int			*stat)		/* success/failure */
> +{
.....
> +	/*
> +	 * If we went off the root then we are either seriously
> +	 * confused or have the tree root in an inode.
> +	 */
> +	if (lev == cur->bc_nlevels) {
> +		ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
> +		goto out0;
> +	}

Would it be better here to explicitly test this rather than assert?
ie.:

	if (lev == cur->bc_nlevels) {
		if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
			goto out0;
		ASSERT(0);
		error = EFSCORRUPTED;
		goto error0;
	}

So that we get an explicit error reported in the production systems
rather than carrying on and dying a horrible death somewhere else....

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

  reply	other threads:[~2008-07-30  2:06 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-29 19:30 [PATCH 09/21] implement generic xfs_btree_increment Christoph Hellwig
2008-07-30  2:06 ` Dave Chinner [this message]
2008-08-01 19:40   ` Christoph Hellwig
2008-08-02  0:35     ` Dave Chinner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080730020645.GJ13395@disturbed \
    --to=david@fromorbit.com \
    --cc=hch@lst.de \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox