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

Commit c3f8fc73 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers
Browse files

xfs: make buffer read verication an IO completion function



Add a verifier function callback capability to the buffer read
interfaces.  This will be used by the callers to supply a function
that verifies the contents of the buffer when it is read from disk.
This patch does not provide callback functions, but simply modifies
the interfaces to allow them to be called.

The reason for adding this to the read interfaces is that it is very
difficult to tell fom the outside is a buffer was just read from
disk or whether we just pulled it out of cache. Supplying a callbck
allows the buffer cache to use it's internal knowledge of the buffer
to execute it only when the buffer is read from disk.

It is intended that the verifier functions will mark the buffer with
an EFSCORRUPTED error when verification fails. This allows the
reading context to distinguish a verification error from an IO
error, and potentially take further actions on the buffer (e.g.
attempt repair) based on the error reported.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarPhil White <pwhite@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent fb595814
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -447,7 +447,7 @@ xfs_alloc_read_agfl(
	error = xfs_trans_read_buf(
			mp, tp, mp->m_ddev_targp,
			XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
			XFS_FSS_TO_BB(mp, 1), 0, &bp);
			XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
	if (error)
		return error;
	ASSERT(!xfs_buf_geterror(bp));
@@ -2110,7 +2110,7 @@ xfs_read_agf(
	error = xfs_trans_read_buf(
			mp, tp, mp->m_ddev_targp,
			XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
			XFS_FSS_TO_BB(mp, 1), flags, bpp);
			XFS_FSS_TO_BB(mp, 1), flags, bpp, NULL);
	if (error)
		return error;
	if (!*bpp)
+1 −1
Original line number Diff line number Diff line
@@ -1994,7 +1994,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args)
			dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
			blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
			error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
						   dblkno, blkcnt, 0, &bp);
						   dblkno, blkcnt, 0, &bp, NULL);
			if (error)
				return(error);

+12 −9
Original line number Diff line number Diff line
@@ -266,9 +266,12 @@ xfs_btree_dup_cursor(
	for (i = 0; i < new->bc_nlevels; i++) {
		new->bc_ptrs[i] = cur->bc_ptrs[i];
		new->bc_ra[i] = cur->bc_ra[i];
		if ((bp = cur->bc_bufs[i])) {
			if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
				XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
		bp = cur->bc_bufs[i];
		if (bp) {
			error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
						   XFS_BUF_ADDR(bp), mp->m_bsize,
						   0, &bp, NULL);
			if (error) {
				xfs_btree_del_cursor(new, error);
				*ncur = NULL;
				return error;
@@ -624,10 +627,10 @@ xfs_btree_read_bufl(

	ASSERT(fsbno != NULLFSBLOCK);
	d = XFS_FSB_TO_DADDR(mp, fsbno);
	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
			mp->m_bsize, lock, &bp))) {
	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
				   mp->m_bsize, lock, &bp, NULL);
	if (error)
		return error;
	}
	ASSERT(!xfs_buf_geterror(bp));
	if (bp)
		xfs_buf_set_ref(bp, refval);
@@ -650,7 +653,7 @@ xfs_btree_reada_bufl(

	ASSERT(fsbno != NULLFSBLOCK);
	d = XFS_FSB_TO_DADDR(mp, fsbno);
	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, NULL);
}

/*
@@ -670,7 +673,7 @@ xfs_btree_reada_bufs(
	ASSERT(agno != NULLAGNUMBER);
	ASSERT(agbno != NULLAGBLOCK);
	d = XFS_AGB_TO_DADDR(mp, agno, agbno);
	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
	xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count, NULL);
}

STATIC int
@@ -1013,7 +1016,7 @@ xfs_btree_read_buf_block(

	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);
				   mp->m_bsize, flags, bpp, NULL);
	if (error)
		return error;

+9 −4
Original line number Diff line number Diff line
@@ -654,7 +654,8 @@ xfs_buf_read_map(
	struct xfs_buftarg	*target,
	struct xfs_buf_map	*map,
	int			nmaps,
	xfs_buf_flags_t		flags)
	xfs_buf_flags_t		flags,
	xfs_buf_iodone_t	verify)
{
	struct xfs_buf		*bp;

@@ -666,6 +667,7 @@ xfs_buf_read_map(

		if (!XFS_BUF_ISDONE(bp)) {
			XFS_STATS_INC(xb_get_read);
			bp->b_iodone = verify;
			_xfs_buf_read(bp, flags);
		} else if (flags & XBF_ASYNC) {
			/*
@@ -691,13 +693,14 @@ void
xfs_buf_readahead_map(
	struct xfs_buftarg	*target,
	struct xfs_buf_map	*map,
	int			nmaps)
	int			nmaps,
	xfs_buf_iodone_t	verify)
{
	if (bdi_read_congested(target->bt_bdi))
		return;

	xfs_buf_read_map(target, map, nmaps,
		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD);
		     XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD, verify);
}

/*
@@ -709,7 +712,8 @@ xfs_buf_read_uncached(
	struct xfs_buftarg	*target,
	xfs_daddr_t		daddr,
	size_t			numblks,
	int			flags)
	int			flags,
	xfs_buf_iodone_t	verify)
{
	xfs_buf_t		*bp;
	int			error;
@@ -723,6 +727,7 @@ xfs_buf_read_uncached(
	bp->b_bn = daddr;
	bp->b_maps[0].bm_bn = daddr;
	bp->b_flags |= XBF_READ;
	bp->b_iodone = verify;

	xfsbdstrat(target->bt_mount, bp);
	error = xfs_buf_iowait(bp);
+12 −8
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ typedef struct xfs_buftarg {
struct xfs_buf;
typedef void (*xfs_buf_iodone_t)(struct xfs_buf *);


#define XB_PAGES	2

struct xfs_buf_map {
@@ -159,7 +160,6 @@ typedef struct xfs_buf {
#endif
} xfs_buf_t;


/* Finding and Reading Buffers */
struct xfs_buf *_xfs_buf_find(struct xfs_buftarg *target,
			      struct xfs_buf_map *map, int nmaps,
@@ -196,9 +196,10 @@ struct xfs_buf *xfs_buf_get_map(struct xfs_buftarg *target,
			       xfs_buf_flags_t flags);
struct xfs_buf *xfs_buf_read_map(struct xfs_buftarg *target,
			       struct xfs_buf_map *map, int nmaps,
			       xfs_buf_flags_t flags);
			       xfs_buf_flags_t flags, xfs_buf_iodone_t verify);
void xfs_buf_readahead_map(struct xfs_buftarg *target,
			       struct xfs_buf_map *map, int nmaps);
			       struct xfs_buf_map *map, int nmaps,
			       xfs_buf_iodone_t verify);

static inline struct xfs_buf *
xfs_buf_get(
@@ -216,20 +217,22 @@ xfs_buf_read(
	struct xfs_buftarg	*target,
	xfs_daddr_t		blkno,
	size_t			numblks,
	xfs_buf_flags_t		flags)
	xfs_buf_flags_t		flags,
	xfs_buf_iodone_t	verify)
{
	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
	return xfs_buf_read_map(target, &map, 1, flags);
	return xfs_buf_read_map(target, &map, 1, flags, verify);
}

static inline void
xfs_buf_readahead(
	struct xfs_buftarg	*target,
	xfs_daddr_t		blkno,
	size_t			numblks)
	size_t			numblks,
	xfs_buf_iodone_t	verify)
{
	DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
	return xfs_buf_readahead_map(target, &map, 1);
	return xfs_buf_readahead_map(target, &map, 1, verify);
}

struct xfs_buf *xfs_buf_get_empty(struct xfs_buftarg *target, size_t numblks);
@@ -239,7 +242,8 @@ int xfs_buf_associate_memory(struct xfs_buf *bp, void *mem, size_t length);
struct xfs_buf *xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks,
				int flags);
struct xfs_buf *xfs_buf_read_uncached(struct xfs_buftarg *target,
				xfs_daddr_t daddr, size_t numblks, int flags);
				xfs_daddr_t daddr, size_t numblks, int flags,
				xfs_buf_iodone_t verify);
void xfs_buf_hold(struct xfs_buf *bp);

/* Releasing Buffers */
Loading