xfs: check xfs_buf_read_uncached returns correctly
xfs_buf_read_uncached() has two failure modes. If can either return NULL or bp->b_error != 0 depending on the type of failure, and not all callers check for both. Fix it so that xfs_buf_read_uncached() always returns the error status, and the buffer is returned as a function parameter. The buffer will only be returned on success. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
595bff75dc
commit
ba3726742c
|
@ -688,29 +688,39 @@ xfs_buf_readahead_map(
|
||||||
* Read an uncached buffer from disk. Allocates and returns a locked
|
* Read an uncached buffer from disk. Allocates and returns a locked
|
||||||
* buffer containing the disk contents or nothing.
|
* buffer containing the disk contents or nothing.
|
||||||
*/
|
*/
|
||||||
struct xfs_buf *
|
int
|
||||||
xfs_buf_read_uncached(
|
xfs_buf_read_uncached(
|
||||||
struct xfs_buftarg *target,
|
struct xfs_buftarg *target,
|
||||||
xfs_daddr_t daddr,
|
xfs_daddr_t daddr,
|
||||||
size_t numblks,
|
size_t numblks,
|
||||||
int flags,
|
int flags,
|
||||||
|
struct xfs_buf **bpp,
|
||||||
const struct xfs_buf_ops *ops)
|
const struct xfs_buf_ops *ops)
|
||||||
{
|
{
|
||||||
struct xfs_buf *bp;
|
struct xfs_buf *bp;
|
||||||
|
|
||||||
|
*bpp = NULL;
|
||||||
|
|
||||||
bp = xfs_buf_get_uncached(target, numblks, flags);
|
bp = xfs_buf_get_uncached(target, numblks, flags);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* set up the buffer for a read IO */
|
/* set up the buffer for a read IO */
|
||||||
ASSERT(bp->b_map_count == 1);
|
ASSERT(bp->b_map_count == 1);
|
||||||
bp->b_bn = daddr;
|
bp->b_bn = XFS_BUF_DADDR_NULL; /* always null for uncached buffers */
|
||||||
bp->b_maps[0].bm_bn = daddr;
|
bp->b_maps[0].bm_bn = daddr;
|
||||||
bp->b_flags |= XBF_READ;
|
bp->b_flags |= XBF_READ;
|
||||||
bp->b_ops = ops;
|
bp->b_ops = ops;
|
||||||
|
|
||||||
xfs_buf_submit_wait(bp);
|
xfs_buf_submit_wait(bp);
|
||||||
return bp;
|
if (bp->b_error) {
|
||||||
|
int error = bp->b_error;
|
||||||
|
xfs_buf_relse(bp);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bpp = bp;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -269,9 +269,9 @@ 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,
|
struct xfs_buf *xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks,
|
||||||
int flags);
|
int flags);
|
||||||
struct xfs_buf *xfs_buf_read_uncached(struct xfs_buftarg *target,
|
int xfs_buf_read_uncached(struct xfs_buftarg *target, xfs_daddr_t daddr,
|
||||||
xfs_daddr_t daddr, size_t numblks, int flags,
|
size_t numblks, int flags, struct xfs_buf **bpp,
|
||||||
const struct xfs_buf_ops *ops);
|
const struct xfs_buf_ops *ops);
|
||||||
void xfs_buf_hold(struct xfs_buf *bp);
|
void xfs_buf_hold(struct xfs_buf *bp);
|
||||||
|
|
||||||
/* Releasing Buffers */
|
/* Releasing Buffers */
|
||||||
|
|
|
@ -172,16 +172,11 @@ xfs_growfs_data_private(
|
||||||
if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
|
if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
|
||||||
return error;
|
return error;
|
||||||
dpct = pct - mp->m_sb.sb_imax_pct;
|
dpct = pct - mp->m_sb.sb_imax_pct;
|
||||||
bp = xfs_buf_read_uncached(mp->m_ddev_targp,
|
error = xfs_buf_read_uncached(mp->m_ddev_targp,
|
||||||
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
|
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
|
||||||
XFS_FSS_TO_BB(mp, 1), 0, NULL);
|
XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
|
||||||
if (!bp)
|
if (error)
|
||||||
return -EIO;
|
|
||||||
if (bp->b_error) {
|
|
||||||
error = bp->b_error;
|
|
||||||
xfs_buf_relse(bp);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
new = nb; /* use new as a temporary here */
|
new = nb; /* use new as a temporary here */
|
||||||
|
|
|
@ -302,21 +302,15 @@ xfs_readsb(
|
||||||
* access to the superblock.
|
* access to the superblock.
|
||||||
*/
|
*/
|
||||||
reread:
|
reread:
|
||||||
bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
|
error = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
|
||||||
BTOBB(sector_size), 0, buf_ops);
|
BTOBB(sector_size), 0, &bp, buf_ops);
|
||||||
if (!bp) {
|
if (error) {
|
||||||
if (loud)
|
|
||||||
xfs_warn(mp, "SB buffer read failed");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
if (bp->b_error) {
|
|
||||||
error = bp->b_error;
|
|
||||||
if (loud)
|
if (loud)
|
||||||
xfs_warn(mp, "SB validate failed with error %d.", error);
|
xfs_warn(mp, "SB validate failed with error %d.", error);
|
||||||
/* bad CRC means corrupted metadata */
|
/* bad CRC means corrupted metadata */
|
||||||
if (error == -EFSBADCRC)
|
if (error == -EFSBADCRC)
|
||||||
error = -EFSCORRUPTED;
|
error = -EFSCORRUPTED;
|
||||||
goto release_buf;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -546,40 +540,43 @@ xfs_set_inoalignment(xfs_mount_t *mp)
|
||||||
* Check that the data (and log if separate) is an ok size.
|
* Check that the data (and log if separate) is an ok size.
|
||||||
*/
|
*/
|
||||||
STATIC int
|
STATIC int
|
||||||
xfs_check_sizes(xfs_mount_t *mp)
|
xfs_check_sizes(
|
||||||
|
struct xfs_mount *mp)
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp;
|
struct xfs_buf *bp;
|
||||||
xfs_daddr_t d;
|
xfs_daddr_t d;
|
||||||
|
int error;
|
||||||
|
|
||||||
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
|
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
|
||||||
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
|
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
|
||||||
xfs_warn(mp, "filesystem size mismatch detected");
|
xfs_warn(mp, "filesystem size mismatch detected");
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
bp = xfs_buf_read_uncached(mp->m_ddev_targp,
|
error = xfs_buf_read_uncached(mp->m_ddev_targp,
|
||||||
d - XFS_FSS_TO_BB(mp, 1),
|
d - XFS_FSS_TO_BB(mp, 1),
|
||||||
XFS_FSS_TO_BB(mp, 1), 0, NULL);
|
XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
|
||||||
if (!bp) {
|
if (error) {
|
||||||
xfs_warn(mp, "last sector read failed");
|
xfs_warn(mp, "last sector read failed");
|
||||||
return -EIO;
|
return error;
|
||||||
}
|
}
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
if (mp->m_logdev_targp != mp->m_ddev_targp) {
|
if (mp->m_logdev_targp == mp->m_ddev_targp)
|
||||||
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
|
return 0;
|
||||||
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
|
|
||||||
xfs_warn(mp, "log size mismatch detected");
|
d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
|
||||||
return -EFBIG;
|
if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
|
||||||
}
|
xfs_warn(mp, "log size mismatch detected");
|
||||||
bp = xfs_buf_read_uncached(mp->m_logdev_targp,
|
return -EFBIG;
|
||||||
d - XFS_FSB_TO_BB(mp, 1),
|
|
||||||
XFS_FSB_TO_BB(mp, 1), 0, NULL);
|
|
||||||
if (!bp) {
|
|
||||||
xfs_warn(mp, "log device read failed");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
xfs_buf_relse(bp);
|
|
||||||
}
|
}
|
||||||
|
error = xfs_buf_read_uncached(mp->m_logdev_targp,
|
||||||
|
d - XFS_FSB_TO_BB(mp, 1),
|
||||||
|
XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
|
||||||
|
if (error) {
|
||||||
|
xfs_warn(mp, "log device read failed");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
xfs_buf_relse(bp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -972,16 +972,11 @@ xfs_growfs_rt(
|
||||||
/*
|
/*
|
||||||
* Read in the last block of the device, make sure it exists.
|
* Read in the last block of the device, make sure it exists.
|
||||||
*/
|
*/
|
||||||
bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
|
error = xfs_buf_read_uncached(mp->m_rtdev_targp,
|
||||||
XFS_FSB_TO_BB(mp, nrblocks - 1),
|
XFS_FSB_TO_BB(mp, nrblocks - 1),
|
||||||
XFS_FSB_TO_BB(mp, 1), 0, NULL);
|
XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
|
||||||
if (!bp)
|
if (error)
|
||||||
return -EIO;
|
|
||||||
if (bp->b_error) {
|
|
||||||
error = bp->b_error;
|
|
||||||
xfs_buf_relse(bp);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1235,11 +1230,12 @@ xfs_rtallocate_extent(
|
||||||
*/
|
*/
|
||||||
int /* error */
|
int /* error */
|
||||||
xfs_rtmount_init(
|
xfs_rtmount_init(
|
||||||
xfs_mount_t *mp) /* file system mount structure */
|
struct xfs_mount *mp) /* file system mount structure */
|
||||||
{
|
{
|
||||||
xfs_buf_t *bp; /* buffer for last block of subvolume */
|
struct xfs_buf *bp; /* buffer for last block of subvolume */
|
||||||
xfs_daddr_t d; /* address of last block of subvolume */
|
struct xfs_sb *sbp; /* filesystem superblock copy in mount */
|
||||||
xfs_sb_t *sbp; /* filesystem superblock copy in mount */
|
xfs_daddr_t d; /* address of last block of subvolume */
|
||||||
|
int error;
|
||||||
|
|
||||||
sbp = &mp->m_sb;
|
sbp = &mp->m_sb;
|
||||||
if (sbp->sb_rblocks == 0)
|
if (sbp->sb_rblocks == 0)
|
||||||
|
@ -1265,14 +1261,12 @@ xfs_rtmount_init(
|
||||||
(unsigned long long) mp->m_sb.sb_rblocks);
|
(unsigned long long) mp->m_sb.sb_rblocks);
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
bp = xfs_buf_read_uncached(mp->m_rtdev_targp,
|
error = xfs_buf_read_uncached(mp->m_rtdev_targp,
|
||||||
d - XFS_FSB_TO_BB(mp, 1),
|
d - XFS_FSB_TO_BB(mp, 1),
|
||||||
XFS_FSB_TO_BB(mp, 1), 0, NULL);
|
XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
|
||||||
if (!bp || bp->b_error) {
|
if (error) {
|
||||||
xfs_warn(mp, "realtime device size check failed");
|
xfs_warn(mp, "realtime device size check failed");
|
||||||
if (bp)
|
return error;
|
||||||
xfs_buf_relse(bp);
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
xfs_buf_relse(bp);
|
xfs_buf_relse(bp);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue