mirror of https://gitee.com/openkylin/linux.git
(More) new code for 5.6:
- Refactor the metadata buffer functions to return the usual int error value instead of the open coded error checking mess we have now. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEUzaAxoMeQq6m2jMV+H93GTRKtOsFAl47QScACgkQ+H93GTRK tOssRw//SysStMKUk0nsQOIB+Y0BqzmMyjuY7CLEOWpQeFh5MRMYH288KSCiI5k2 ljHEXeBUU7AoLQEegL5ivIMa7p4gfzkorRAYrcB7dcPwo4tYqwhfC97yU/5tYuxk fOfm0ZaxJ0E+KNDBRd6vqe/lbWE24ySyZWxv7kzJs2ndc3RW4kEFzFFDGIVfi256 rPMzTxn7B4D0c359o4P0LGP5e5OeUeLH8FrvkITZCml7zMApdpo+eQzn1YxFRcGo 62daaO2uxtHBVnd30c1BhMPWfXGr+Pqls6QxZKr7YLvGSP5Jb6lRKnB9v3ImmjgH OmOq+sXsVgKpNKo4lItnNJditAb0kR0UQHjmEccaUKbkAgEnGkSYqOtPbk2nkHw5 Eb05y+36DH20GRCp6lKbmdnFOxwL53pfWm8m3xieU/dE/gYH2bphFJNQokm50yaS Onoz7zhdvqwLHQafnCLrwZWHVcsEQ1bjKC4nkWZdrcv6UlPYbuTKzJe3OaN79nE2 IFu9ilhX50M6dS2qsF0NDTEXrPAie6YOlikCvZotJIWaqpzEtWj/+t02jCtPhquC M5yBYo0ljA3kYDUMZdng44FaO1h3E8MQIA/+dycyIQWTYIXYPB8mZni8D+YTVTbE 1jZT8qwBc83mTewYoOV5s+e9ja5hoHZtsZ/KnNssgSbQ66dq/7g= =APXi -----END PGP SIGNATURE----- Merge tag 'xfs-5.6-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux Pull moar xfs updates from Darrick Wong: "This contains the buffer error code refactoring I mentioned last week, now that it has had extra time to complete the full xfs fuzz testing suite to make sure there aren't any obvious new bugs" * tag 'xfs-5.6-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: fix xfs_buf_ioerror_alert location reporting xfs: remove unnecessary null pointer checks from _read_agf callers xfs: make xfs_*read_agf return EAGAIN to ALLOC_FLAG_TRYLOCK callers xfs: remove the xfs_btree_get_buf[ls] functions xfs: make xfs_trans_get_buf return an error code xfs: make xfs_trans_get_buf_map return an error code xfs: make xfs_buf_read return an error code xfs: make xfs_buf_get_uncached return an error code xfs: make xfs_buf_get return an error code xfs: make xfs_buf_read_map return an error code xfs: make xfs_buf_get_map return an error code xfs: make xfs_buf_alloc return an error code
This commit is contained in:
commit
99be3f6098
|
@ -23,25 +23,28 @@
|
|||
#include "xfs_ag_resv.h"
|
||||
#include "xfs_health.h"
|
||||
|
||||
static struct xfs_buf *
|
||||
static int
|
||||
xfs_get_aghdr_buf(
|
||||
struct xfs_mount *mp,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
struct xfs_buf **bpp,
|
||||
const struct xfs_buf_ops *ops)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
bp = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, 0);
|
||||
if (!bp)
|
||||
return NULL;
|
||||
error = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
|
||||
bp->b_bn = blkno;
|
||||
bp->b_maps[0].bm_bn = blkno;
|
||||
bp->b_ops = ops;
|
||||
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool is_log_ag(struct xfs_mount *mp, struct aghdr_init_data *id)
|
||||
|
@ -340,13 +343,13 @@ xfs_ag_init_hdr(
|
|||
struct aghdr_init_data *id,
|
||||
aghdr_init_work_f work,
|
||||
const struct xfs_buf_ops *ops)
|
||||
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
bp = xfs_get_aghdr_buf(mp, id->daddr, id->numblks, ops);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = xfs_get_aghdr_buf(mp, id->daddr, id->numblks, &bp, ops);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
(*work)(mp, bp, id);
|
||||
|
||||
|
|
|
@ -1070,11 +1070,11 @@ xfs_alloc_ag_vextent_small(
|
|||
if (args->datatype & XFS_ALLOC_USERDATA) {
|
||||
struct xfs_buf *bp;
|
||||
|
||||
bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno);
|
||||
if (XFS_IS_CORRUPT(args->mp, !bp)) {
|
||||
error = -EFSCORRUPTED;
|
||||
error = xfs_trans_get_buf(args->tp, args->mp->m_ddev_targp,
|
||||
XFS_AGB_TO_DADDR(args->mp, args->agno, fbno),
|
||||
args->mp->m_bsize, 0, &bp);
|
||||
if (error)
|
||||
goto error;
|
||||
}
|
||||
xfs_trans_binval(args->tp, bp);
|
||||
}
|
||||
*fbnop = args->agbno = fbno;
|
||||
|
@ -2347,9 +2347,11 @@ xfs_free_agfl_block(
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno);
|
||||
if (XFS_IS_CORRUPT(tp->t_mountp, !bp))
|
||||
return -EFSCORRUPTED;
|
||||
error = xfs_trans_get_buf(tp, tp->t_mountp->m_ddev_targp,
|
||||
XFS_AGB_TO_DADDR(tp->t_mountp, agno, agbno),
|
||||
tp->t_mountp->m_bsize, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
xfs_trans_binval(tp, bp);
|
||||
|
||||
return 0;
|
||||
|
@ -2500,12 +2502,11 @@ xfs_alloc_fix_freelist(
|
|||
|
||||
if (!pag->pagf_init) {
|
||||
error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
|
||||
if (error)
|
||||
if (error) {
|
||||
/* Couldn't lock the AGF so skip this AG. */
|
||||
if (error == -EAGAIN)
|
||||
error = 0;
|
||||
goto out_no_agbp;
|
||||
if (!pag->pagf_init) {
|
||||
ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
|
||||
ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
||||
goto out_agbp_relse;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2531,11 +2532,10 @@ xfs_alloc_fix_freelist(
|
|||
*/
|
||||
if (!agbp) {
|
||||
error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp);
|
||||
if (error)
|
||||
goto out_no_agbp;
|
||||
if (!agbp) {
|
||||
ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK);
|
||||
ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING));
|
||||
if (error) {
|
||||
/* Couldn't lock the AGF so skip this AG. */
|
||||
if (error == -EAGAIN)
|
||||
error = 0;
|
||||
goto out_no_agbp;
|
||||
}
|
||||
}
|
||||
|
@ -2766,11 +2766,10 @@ xfs_alloc_pagf_init(
|
|||
xfs_buf_t *bp;
|
||||
int error;
|
||||
|
||||
if ((error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp)))
|
||||
return error;
|
||||
if (bp)
|
||||
error = xfs_alloc_read_agf(mp, tp, agno, flags, &bp);
|
||||
if (!error)
|
||||
xfs_trans_brelse(tp, bp);
|
||||
return 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2956,14 +2955,11 @@ xfs_read_agf(
|
|||
trace_xfs_read_agf(mp, agno);
|
||||
|
||||
ASSERT(agno != NULLAGNUMBER);
|
||||
error = xfs_trans_read_buf(
|
||||
mp, tp, mp->m_ddev_targp,
|
||||
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_agf_buf_ops);
|
||||
if (error)
|
||||
return error;
|
||||
if (!*bpp)
|
||||
return 0;
|
||||
|
||||
ASSERT(!(*bpp)->b_error);
|
||||
xfs_buf_set_ref(*bpp, XFS_AGF_REF);
|
||||
|
@ -2987,14 +2983,15 @@ xfs_alloc_read_agf(
|
|||
|
||||
trace_xfs_alloc_read_agf(mp, agno);
|
||||
|
||||
/* We don't support trylock when freeing. */
|
||||
ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) !=
|
||||
(XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK));
|
||||
ASSERT(agno != NULLAGNUMBER);
|
||||
error = xfs_read_agf(mp, tp, agno,
|
||||
(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0,
|
||||
bpp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!*bpp)
|
||||
return 0;
|
||||
ASSERT(!(*bpp)->b_error);
|
||||
|
||||
agf = XFS_BUF_TO_AGF(*bpp);
|
||||
|
|
|
@ -418,20 +418,10 @@ xfs_attr_rmtval_get(
|
|||
(map[i].br_startblock != HOLESTARTBLOCK));
|
||||
dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock);
|
||||
dblkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
|
||||
bp = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt, 0,
|
||||
&xfs_attr3_rmt_buf_ops);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_relse(bp);
|
||||
|
||||
/* bad CRC means corrupted metadata */
|
||||
if (error == -EFSBADCRC)
|
||||
error = -EFSCORRUPTED;
|
||||
error = xfs_buf_read(mp->m_ddev_targp, dblkno, dblkcnt,
|
||||
0, &bp, &xfs_attr3_rmt_buf_ops);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xfs_attr_rmtval_copyout(mp, bp, args->dp->i_ino,
|
||||
&offset, &valuelen,
|
||||
|
@ -555,9 +545,9 @@ xfs_attr_rmtval_set(
|
|||
dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
|
||||
dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
|
||||
|
||||
bp = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = xfs_buf_get(mp->m_ddev_targp, dblkno, dblkcnt, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
bp->b_ops = &xfs_attr3_rmt_buf_ops;
|
||||
|
||||
xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
|
||||
|
|
|
@ -730,11 +730,11 @@ xfs_bmap_extents_to_btree(
|
|||
cur->bc_private.b.allocated++;
|
||||
ip->i_d.di_nblocks++;
|
||||
xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
|
||||
abp = xfs_btree_get_bufl(mp, tp, args.fsbno);
|
||||
if (XFS_IS_CORRUPT(mp, !abp)) {
|
||||
error = -EFSCORRUPTED;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(mp, args.fsbno),
|
||||
mp->m_bsize, 0, &abp);
|
||||
if (error)
|
||||
goto out_unreserve_dquot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the child block.
|
||||
|
@ -878,7 +878,11 @@ xfs_bmap_local_to_extents(
|
|||
ASSERT(args.fsbno != NULLFSBLOCK);
|
||||
ASSERT(args.len == 1);
|
||||
tp->t_firstblock = args.fsbno;
|
||||
bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno);
|
||||
error = xfs_trans_get_buf(tp, args.mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(args.mp, args.fsbno),
|
||||
args.mp->m_bsize, 0, &bp);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Initialize the block, copy the data and log the remote buffer.
|
||||
|
@ -3307,11 +3311,12 @@ xfs_bmap_longest_free_extent(
|
|||
pag = xfs_perag_get(mp, ag);
|
||||
if (!pag->pagf_init) {
|
||||
error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (!pag->pagf_init) {
|
||||
*notinit = 1;
|
||||
if (error) {
|
||||
/* Couldn't lock the AGF, so skip this AG. */
|
||||
if (error == -EAGAIN) {
|
||||
*notinit = 1;
|
||||
error = 0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -678,42 +678,6 @@ xfs_btree_get_block(
|
|||
return XFS_BUF_TO_BLOCK(*bpp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a buffer for the block, return it with no data read.
|
||||
* Long-form addressing.
|
||||
*/
|
||||
xfs_buf_t * /* buffer for fsbno */
|
||||
xfs_btree_get_bufl(
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_fsblock_t fsbno) /* file system block number */
|
||||
{
|
||||
xfs_daddr_t d; /* real disk block address */
|
||||
|
||||
ASSERT(fsbno != NULLFSBLOCK);
|
||||
d = XFS_FSB_TO_DADDR(mp, fsbno);
|
||||
return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a buffer for the block, return it with no data read.
|
||||
* Short-form addressing.
|
||||
*/
|
||||
xfs_buf_t * /* buffer for agno/agbno */
|
||||
xfs_btree_get_bufs(
|
||||
xfs_mount_t *mp, /* file system mount point */
|
||||
xfs_trans_t *tp, /* transaction pointer */
|
||||
xfs_agnumber_t agno, /* allocation group number */
|
||||
xfs_agblock_t agbno) /* allocation group block number */
|
||||
{
|
||||
xfs_daddr_t d; /* real disk block address */
|
||||
|
||||
ASSERT(agno != NULLAGNUMBER);
|
||||
ASSERT(agbno != NULLAGBLOCK);
|
||||
d = XFS_AGB_TO_DADDR(mp, agno, agbno);
|
||||
return xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the cursor to point to the first record at the given level.
|
||||
* Other levels are unaffected.
|
||||
|
@ -1270,11 +1234,10 @@ xfs_btree_get_buf_block(
|
|||
error = xfs_btree_ptr_to_daddr(cur, ptr, &d);
|
||||
if (error)
|
||||
return error;
|
||||
*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize, 0);
|
||||
|
||||
if (!*bpp)
|
||||
return -ENOMEM;
|
||||
error = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d, mp->m_bsize,
|
||||
0, bpp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
(*bpp)->b_ops = cur->bc_ops->buf_ops;
|
||||
*block = XFS_BUF_TO_BLOCK(*bpp);
|
||||
|
|
|
@ -296,27 +296,6 @@ xfs_btree_dup_cursor(
|
|||
xfs_btree_cur_t *cur, /* input cursor */
|
||||
xfs_btree_cur_t **ncur);/* output cursor */
|
||||
|
||||
/*
|
||||
* Get a buffer for the block, return it with no data read.
|
||||
* Long-form addressing.
|
||||
*/
|
||||
struct xfs_buf * /* buffer for fsbno */
|
||||
xfs_btree_get_bufl(
|
||||
struct xfs_mount *mp, /* file system mount point */
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_fsblock_t fsbno); /* file system block number */
|
||||
|
||||
/*
|
||||
* Get a buffer for the block, return it with no data read.
|
||||
* Short-form addressing.
|
||||
*/
|
||||
struct xfs_buf * /* buffer for agno/agbno */
|
||||
xfs_btree_get_bufs(
|
||||
struct xfs_mount *mp, /* file system mount point */
|
||||
struct xfs_trans *tp, /* transaction pointer */
|
||||
xfs_agnumber_t agno, /* allocation group number */
|
||||
xfs_agblock_t agbno); /* allocation group block number */
|
||||
|
||||
/*
|
||||
* Compute first and last byte offsets for the fields given.
|
||||
* Interprets the offsets table, which contains struct field offsets.
|
||||
|
|
|
@ -2591,13 +2591,9 @@ xfs_da_get_buf(
|
|||
if (error || nmap == 0)
|
||||
goto out_free;
|
||||
|
||||
bp = xfs_trans_get_buf_map(tp, mp->m_ddev_targp, mapp, nmap, 0);
|
||||
error = bp ? bp->b_error : -EIO;
|
||||
if (error) {
|
||||
if (bp)
|
||||
xfs_trans_brelse(tp, bp);
|
||||
error = xfs_trans_get_buf_map(tp, mp->m_ddev_targp, mapp, nmap, 0, &bp);
|
||||
if (error)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
*bpp = bp;
|
||||
|
||||
|
|
|
@ -276,6 +276,7 @@ xfs_ialloc_inode_init(
|
|||
int i, j;
|
||||
xfs_daddr_t d;
|
||||
xfs_ino_t ino = 0;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Loop over the new block(s), filling in the inodes. For small block
|
||||
|
@ -327,12 +328,11 @@ xfs_ialloc_inode_init(
|
|||
*/
|
||||
d = XFS_AGB_TO_DADDR(mp, agno, agbno +
|
||||
(j * M_IGEO(mp)->blocks_per_cluster));
|
||||
fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize *
|
||||
M_IGEO(mp)->blocks_per_cluster,
|
||||
XBF_UNMAPPED);
|
||||
if (!fbuf)
|
||||
return -ENOMEM;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize * M_IGEO(mp)->blocks_per_cluster,
|
||||
XBF_UNMAPPED, &fbuf);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Initialize the inode buffers and log them appropriately. */
|
||||
fbuf->b_ops = &xfs_inode_buf_ops;
|
||||
|
|
|
@ -1177,8 +1177,6 @@ xfs_refcount_finish_one(
|
|||
XFS_ALLOC_FLAG_FREEING, &agbp);
|
||||
if (error)
|
||||
return error;
|
||||
if (XFS_IS_CORRUPT(tp->t_mountp, !agbp))
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
|
||||
if (!rcur) {
|
||||
|
@ -1718,10 +1716,6 @@ xfs_refcount_recover_cow_leftovers(
|
|||
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
|
||||
if (error)
|
||||
goto out_trans;
|
||||
if (!agbp) {
|
||||
error = -ENOMEM;
|
||||
goto out_trans;
|
||||
}
|
||||
cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
|
||||
|
||||
/* Find all the leftover CoW staging extents. */
|
||||
|
|
|
@ -985,9 +985,9 @@ xfs_update_secondary_sbs(
|
|||
for (agno = 1; agno < mp->m_sb.sb_agcount; agno++) {
|
||||
struct xfs_buf *bp;
|
||||
|
||||
bp = xfs_buf_get(mp->m_ddev_targp,
|
||||
error = xfs_buf_get(mp->m_ddev_targp,
|
||||
XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
|
||||
XFS_FSS_TO_BB(mp, 1));
|
||||
XFS_FSS_TO_BB(mp, 1), &bp);
|
||||
/*
|
||||
* If we get an error reading or writing alternate superblocks,
|
||||
* continue. xfs_repair chooses the "best" superblock based
|
||||
|
@ -995,12 +995,12 @@ xfs_update_secondary_sbs(
|
|||
* superblocks un-updated than updated, and xfs_repair may
|
||||
* pick them over the properly-updated primary.
|
||||
*/
|
||||
if (!bp) {
|
||||
if (error) {
|
||||
xfs_warn(mp,
|
||||
"error allocating secondary superblock for ag %d",
|
||||
agno);
|
||||
if (!saved_error)
|
||||
saved_error = -ENOMEM;
|
||||
saved_error = error;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1185,13 +1185,14 @@ xfs_sb_get_secondary(
|
|||
struct xfs_buf **bpp)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
ASSERT(agno != 0 && agno != NULLAGNUMBER);
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_AG_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
|
||||
XFS_FSS_TO_BB(mp, 1), 0);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
XFS_FSS_TO_BB(mp, 1), 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
bp->b_ops = &xfs_sb_buf_ops;
|
||||
xfs_buf_oneshot(bp);
|
||||
*bpp = bp;
|
||||
|
|
|
@ -659,8 +659,6 @@ xrep_agfl(
|
|||
error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.agno, 0, &agf_bp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!agf_bp)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Make sure we have the AGFL buffer, as scrub might have decided it
|
||||
|
@ -735,8 +733,6 @@ xrep_agi_find_btrees(
|
|||
error = xfs_alloc_read_agf(mp, sc->tp, sc->sa.agno, 0, &agf_bp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!agf_bp)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Find the btree roots. */
|
||||
error = xrep_find_ag_btree_roots(sc, agf_bp, fab, NULL);
|
||||
|
|
|
@ -83,9 +83,6 @@ xchk_fscount_warmup(
|
|||
error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &agf_bp);
|
||||
if (error)
|
||||
break;
|
||||
error = -ENOMEM;
|
||||
if (!agf_bp || !agi_bp)
|
||||
break;
|
||||
|
||||
/*
|
||||
* These are supposed to be initialized by the header read
|
||||
|
|
|
@ -341,13 +341,17 @@ xrep_init_btblock(
|
|||
struct xfs_trans *tp = sc->tp;
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
trace_xrep_init_btblock(mp, XFS_FSB_TO_AGNO(mp, fsb),
|
||||
XFS_FSB_TO_AGBNO(mp, fsb), btnum);
|
||||
|
||||
ASSERT(XFS_FSB_TO_AGNO(mp, fsb) == sc->sa.agno);
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, XFS_FSB_TO_DADDR(mp, fsb),
|
||||
XFS_FSB_TO_BB(mp, 1), 0);
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(mp, fsb), XFS_FSB_TO_BB(mp, 1), 0,
|
||||
&bp);
|
||||
if (error)
|
||||
return error;
|
||||
xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
|
||||
xfs_btree_init_block(mp, bp, btnum, 0, 0, sc->sa.agno);
|
||||
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF);
|
||||
|
@ -542,8 +546,6 @@ xrep_reap_block(
|
|||
error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf_bp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!agf_bp)
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
agf_bp = sc->sa.agf_bp;
|
||||
}
|
||||
|
|
|
@ -205,11 +205,12 @@ xfs_attr3_node_inactive(
|
|||
/*
|
||||
* Remove the subsidiary block from the cache and from the log.
|
||||
*/
|
||||
child_bp = xfs_trans_get_buf(*trans, mp->m_ddev_targp,
|
||||
error = xfs_trans_get_buf(*trans, mp->m_ddev_targp,
|
||||
child_blkno,
|
||||
XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0);
|
||||
if (!child_bp)
|
||||
return -EIO;
|
||||
XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0,
|
||||
&child_bp);
|
||||
if (error)
|
||||
return error;
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_trans_brelse(*trans, child_bp);
|
||||
|
@ -298,10 +299,10 @@ xfs_attr3_root_inactive(
|
|||
/*
|
||||
* Invalidate the incore copy of the root block.
|
||||
*/
|
||||
bp = xfs_trans_get_buf(*trans, mp->m_ddev_targp, blkno,
|
||||
XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0);
|
||||
if (!bp)
|
||||
return -EIO;
|
||||
error = xfs_trans_get_buf(*trans, mp->m_ddev_targp, blkno,
|
||||
XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_trans_brelse(*trans, bp);
|
||||
|
|
161
fs/xfs/xfs_buf.c
161
fs/xfs/xfs_buf.c
|
@ -198,20 +198,22 @@ xfs_buf_free_maps(
|
|||
}
|
||||
}
|
||||
|
||||
static struct xfs_buf *
|
||||
static int
|
||||
_xfs_buf_alloc(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
*bpp = NULL;
|
||||
bp = kmem_zone_zalloc(xfs_buf_zone, KM_NOFS);
|
||||
if (unlikely(!bp))
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* We don't want certain flags to appear in b_flags unless they are
|
||||
|
@ -239,7 +241,7 @@ _xfs_buf_alloc(
|
|||
error = xfs_buf_get_maps(bp, nmaps);
|
||||
if (error) {
|
||||
kmem_cache_free(xfs_buf_zone, bp);
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
bp->b_bn = map[0].bm_bn;
|
||||
|
@ -256,7 +258,8 @@ _xfs_buf_alloc(
|
|||
XFS_STATS_INC(bp->b_mount, xb_create);
|
||||
trace_xfs_buf_init(bp, _RET_IP_);
|
||||
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -682,53 +685,39 @@ xfs_buf_incore(
|
|||
* cache hits, as metadata intensive workloads will see 3 orders of magnitude
|
||||
* more hits than misses.
|
||||
*/
|
||||
struct xfs_buf *
|
||||
int
|
||||
xfs_buf_get_map(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_buf *new_bp;
|
||||
int error = 0;
|
||||
|
||||
*bpp = NULL;
|
||||
error = xfs_buf_find(target, map, nmaps, flags, NULL, &bp);
|
||||
|
||||
switch (error) {
|
||||
case 0:
|
||||
/* cache hit */
|
||||
if (!error)
|
||||
goto found;
|
||||
case -EAGAIN:
|
||||
/* cache hit, trylock failure, caller handles failure */
|
||||
ASSERT(flags & XBF_TRYLOCK);
|
||||
return NULL;
|
||||
case -ENOENT:
|
||||
/* cache miss, go for insert */
|
||||
break;
|
||||
case -EFSCORRUPTED:
|
||||
default:
|
||||
/*
|
||||
* None of the higher layers understand failure types
|
||||
* yet, so return NULL to signal a fatal lookup error.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
if (error != -ENOENT)
|
||||
return error;
|
||||
|
||||
new_bp = _xfs_buf_alloc(target, map, nmaps, flags);
|
||||
if (unlikely(!new_bp))
|
||||
return NULL;
|
||||
error = _xfs_buf_alloc(target, map, nmaps, flags, &new_bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_buf_allocate_memory(new_bp, flags);
|
||||
if (error) {
|
||||
xfs_buf_free(new_bp);
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xfs_buf_find(target, map, nmaps, flags, new_bp, &bp);
|
||||
if (error) {
|
||||
xfs_buf_free(new_bp);
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (bp != new_bp)
|
||||
|
@ -741,7 +730,7 @@ xfs_buf_get_map(
|
|||
xfs_warn(target->bt_mount,
|
||||
"%s: failed to map pagesn", __func__);
|
||||
xfs_buf_relse(bp);
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,7 +743,8 @@ xfs_buf_get_map(
|
|||
|
||||
XFS_STATS_INC(target->bt_mount, xb_get);
|
||||
trace_xfs_buf_get(bp, flags, _RET_IP_);
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -806,46 +796,77 @@ xfs_buf_reverify(
|
|||
return bp->b_error;
|
||||
}
|
||||
|
||||
xfs_buf_t *
|
||||
int
|
||||
xfs_buf_read_map(
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags,
|
||||
const struct xfs_buf_ops *ops)
|
||||
struct xfs_buf **bpp,
|
||||
const struct xfs_buf_ops *ops,
|
||||
xfs_failaddr_t fa)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
flags |= XBF_READ;
|
||||
*bpp = NULL;
|
||||
|
||||
bp = xfs_buf_get_map(target, map, nmaps, flags);
|
||||
if (!bp)
|
||||
return NULL;
|
||||
error = xfs_buf_get_map(target, map, nmaps, flags, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
trace_xfs_buf_read(bp, flags, _RET_IP_);
|
||||
|
||||
if (!(bp->b_flags & XBF_DONE)) {
|
||||
/* Initiate the buffer read and wait. */
|
||||
XFS_STATS_INC(target->bt_mount, xb_get_read);
|
||||
bp->b_ops = ops;
|
||||
_xfs_buf_read(bp, flags);
|
||||
return bp;
|
||||
error = _xfs_buf_read(bp, flags);
|
||||
|
||||
/* Readahead iodone already dropped the buffer, so exit. */
|
||||
if (flags & XBF_ASYNC)
|
||||
return 0;
|
||||
} else {
|
||||
/* Buffer already read; all we need to do is check it. */
|
||||
error = xfs_buf_reverify(bp, ops);
|
||||
|
||||
/* Readahead already finished; drop the buffer and exit. */
|
||||
if (flags & XBF_ASYNC) {
|
||||
xfs_buf_relse(bp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We do not want read in the flags */
|
||||
bp->b_flags &= ~XBF_READ;
|
||||
ASSERT(bp->b_ops != NULL || ops == NULL);
|
||||
}
|
||||
|
||||
xfs_buf_reverify(bp, ops);
|
||||
/*
|
||||
* If we've had a read error, then the contents of the buffer are
|
||||
* invalid and should not be used. To ensure that a followup read tries
|
||||
* to pull the buffer from disk again, we clear the XBF_DONE flag and
|
||||
* mark the buffer stale. This ensures that anyone who has a current
|
||||
* reference to the buffer will interpret it's contents correctly and
|
||||
* future cache lookups will also treat it as an empty, uninitialised
|
||||
* buffer.
|
||||
*/
|
||||
if (error) {
|
||||
if (!XFS_FORCED_SHUTDOWN(target->bt_mount))
|
||||
xfs_buf_ioerror_alert(bp, fa);
|
||||
|
||||
if (flags & XBF_ASYNC) {
|
||||
/*
|
||||
* Read ahead call which is already satisfied,
|
||||
* drop the buffer
|
||||
*/
|
||||
bp->b_flags &= ~XBF_DONE;
|
||||
xfs_buf_stale(bp);
|
||||
xfs_buf_relse(bp);
|
||||
return NULL;
|
||||
|
||||
/* bad CRC means corrupted metadata */
|
||||
if (error == -EFSBADCRC)
|
||||
error = -EFSCORRUPTED;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* We do not want read in the flags */
|
||||
bp->b_flags &= ~XBF_READ;
|
||||
ASSERT(bp->b_ops != NULL || ops == NULL);
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -859,11 +880,14 @@ xfs_buf_readahead_map(
|
|||
int nmaps,
|
||||
const struct xfs_buf_ops *ops)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
|
||||
if (bdi_read_congested(target->bt_bdev->bd_bdi))
|
||||
return;
|
||||
|
||||
xfs_buf_read_map(target, map, nmaps,
|
||||
XBF_TRYLOCK|XBF_ASYNC|XBF_READ_AHEAD, ops);
|
||||
XBF_TRYLOCK | XBF_ASYNC | XBF_READ_AHEAD, &bp, ops,
|
||||
__this_address);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -880,12 +904,13 @@ xfs_buf_read_uncached(
|
|||
const struct xfs_buf_ops *ops)
|
||||
{
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
*bpp = NULL;
|
||||
|
||||
bp = xfs_buf_get_uncached(target, numblks, flags);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = xfs_buf_get_uncached(target, numblks, flags, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* set up the buffer for a read IO */
|
||||
ASSERT(bp->b_map_count == 1);
|
||||
|
@ -896,7 +921,7 @@ xfs_buf_read_uncached(
|
|||
|
||||
xfs_buf_submit(bp);
|
||||
if (bp->b_error) {
|
||||
int error = bp->b_error;
|
||||
error = bp->b_error;
|
||||
xfs_buf_relse(bp);
|
||||
return error;
|
||||
}
|
||||
|
@ -905,20 +930,23 @@ xfs_buf_read_uncached(
|
|||
return 0;
|
||||
}
|
||||
|
||||
xfs_buf_t *
|
||||
int
|
||||
xfs_buf_get_uncached(
|
||||
struct xfs_buftarg *target,
|
||||
size_t numblks,
|
||||
int flags)
|
||||
int flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
unsigned long page_count;
|
||||
int error, i;
|
||||
struct xfs_buf *bp;
|
||||
DEFINE_SINGLE_BUF_MAP(map, XFS_BUF_DADDR_NULL, numblks);
|
||||
|
||||
*bpp = NULL;
|
||||
|
||||
/* flags might contain irrelevant bits, pass only what we care about */
|
||||
bp = _xfs_buf_alloc(target, &map, 1, flags & XBF_NO_IOACCT);
|
||||
if (unlikely(bp == NULL))
|
||||
error = _xfs_buf_alloc(target, &map, 1, flags & XBF_NO_IOACCT, &bp);
|
||||
if (error)
|
||||
goto fail;
|
||||
|
||||
page_count = PAGE_ALIGN(numblks << BBSHIFT) >> PAGE_SHIFT;
|
||||
|
@ -928,8 +956,10 @@ xfs_buf_get_uncached(
|
|||
|
||||
for (i = 0; i < page_count; i++) {
|
||||
bp->b_pages[i] = alloc_page(xb_to_gfp(flags));
|
||||
if (!bp->b_pages[i])
|
||||
if (!bp->b_pages[i]) {
|
||||
error = -ENOMEM;
|
||||
goto fail_free_mem;
|
||||
}
|
||||
}
|
||||
bp->b_flags |= _XBF_PAGES;
|
||||
|
||||
|
@ -941,7 +971,8 @@ xfs_buf_get_uncached(
|
|||
}
|
||||
|
||||
trace_xfs_buf_get_uncached(bp, _RET_IP_);
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
|
||||
fail_free_mem:
|
||||
while (--i >= 0)
|
||||
|
@ -951,7 +982,7 @@ xfs_buf_get_uncached(
|
|||
xfs_buf_free_maps(bp);
|
||||
kmem_cache_free(xfs_buf_zone, bp);
|
||||
fail:
|
||||
return NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1205,10 +1236,10 @@ __xfs_buf_ioerror(
|
|||
void
|
||||
xfs_buf_ioerror_alert(
|
||||
struct xfs_buf *bp,
|
||||
const char *func)
|
||||
xfs_failaddr_t func)
|
||||
{
|
||||
xfs_alert(bp->b_mount,
|
||||
"metadata I/O error in \"%s\" at daddr 0x%llx len %d error %d",
|
||||
"metadata I/O error in \"%pS\" at daddr 0x%llx len %d error %d",
|
||||
func, (uint64_t)XFS_BUF_ADDR(bp), bp->b_length,
|
||||
-bp->b_error);
|
||||
}
|
||||
|
|
|
@ -192,37 +192,40 @@ struct xfs_buf *xfs_buf_incore(struct xfs_buftarg *target,
|
|||
xfs_daddr_t blkno, size_t numblks,
|
||||
xfs_buf_flags_t flags);
|
||||
|
||||
struct xfs_buf *xfs_buf_get_map(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
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,
|
||||
const struct xfs_buf_ops *ops);
|
||||
int xfs_buf_get_map(struct xfs_buftarg *target, struct xfs_buf_map *map,
|
||||
int nmaps, xfs_buf_flags_t flags, struct xfs_buf **bpp);
|
||||
int xfs_buf_read_map(struct xfs_buftarg *target, struct xfs_buf_map *map,
|
||||
int nmaps, xfs_buf_flags_t flags, struct xfs_buf **bpp,
|
||||
const struct xfs_buf_ops *ops, xfs_failaddr_t fa);
|
||||
void xfs_buf_readahead_map(struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
const struct xfs_buf_ops *ops);
|
||||
|
||||
static inline struct xfs_buf *
|
||||
static inline int
|
||||
xfs_buf_get(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks)
|
||||
size_t numblks,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_buf_get_map(target, &map, 1, 0);
|
||||
|
||||
return xfs_buf_get_map(target, &map, 1, 0, bpp);
|
||||
}
|
||||
|
||||
static inline struct xfs_buf *
|
||||
static inline int
|
||||
xfs_buf_read(
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
size_t numblks,
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp,
|
||||
const struct xfs_buf_ops *ops)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_buf_read_map(target, &map, 1, flags, ops);
|
||||
|
||||
return xfs_buf_read_map(target, &map, 1, flags, bpp, ops,
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -236,8 +239,8 @@ xfs_buf_readahead(
|
|||
return xfs_buf_readahead_map(target, &map, 1, ops);
|
||||
}
|
||||
|
||||
struct xfs_buf *xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks,
|
||||
int flags);
|
||||
int xfs_buf_get_uncached(struct xfs_buftarg *target, size_t numblks, int flags,
|
||||
struct xfs_buf **bpp);
|
||||
int xfs_buf_read_uncached(struct xfs_buftarg *target, xfs_daddr_t daddr,
|
||||
size_t numblks, int flags, struct xfs_buf **bpp,
|
||||
const struct xfs_buf_ops *ops);
|
||||
|
@ -259,7 +262,7 @@ extern void xfs_buf_ioend(struct xfs_buf *bp);
|
|||
extern void __xfs_buf_ioerror(struct xfs_buf *bp, int error,
|
||||
xfs_failaddr_t failaddr);
|
||||
#define xfs_buf_ioerror(bp, err) __xfs_buf_ioerror((bp), (err), __this_address)
|
||||
extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
|
||||
extern void xfs_buf_ioerror_alert(struct xfs_buf *bp, xfs_failaddr_t fa);
|
||||
|
||||
extern int __xfs_buf_submit(struct xfs_buf *bp, bool);
|
||||
static inline int xfs_buf_submit(struct xfs_buf *bp)
|
||||
|
|
|
@ -1113,7 +1113,7 @@ xfs_buf_iodone_callback_error(
|
|||
if (bp->b_target != lasttarg ||
|
||||
time_after(jiffies, (lasttime + 5*HZ))) {
|
||||
lasttime = jiffies;
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_ioerror_alert(bp, __this_address);
|
||||
}
|
||||
lasttarg = bp->b_target;
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ xfs_trim_extents(
|
|||
xfs_log_force(mp, XFS_LOG_SYNC);
|
||||
|
||||
error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp);
|
||||
if (error || !agbp)
|
||||
if (error)
|
||||
goto out_put_perag;
|
||||
|
||||
cur = xfs_allocbt_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_CNT);
|
||||
|
|
|
@ -320,10 +320,10 @@ xfs_dquot_disk_alloc(
|
|||
dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock);
|
||||
|
||||
/* now we can just get the buffer (there's nothing to read yet) */
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno,
|
||||
mp->m_quotainfo->qi_dqchunklen, 0);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno,
|
||||
mp->m_quotainfo->qi_dqchunklen, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
bp->b_ops = &xfs_dquot_buf_ops;
|
||||
|
||||
/*
|
||||
|
|
|
@ -159,16 +159,15 @@ xfs_filestream_pick_ag(
|
|||
|
||||
if (!pag->pagf_init) {
|
||||
err = xfs_alloc_pagf_init(mp, NULL, ag, trylock);
|
||||
if (err && !trylock) {
|
||||
if (err) {
|
||||
xfs_perag_put(pag);
|
||||
return err;
|
||||
if (err != -EAGAIN)
|
||||
return err;
|
||||
/* Couldn't lock the AGF, skip this AG. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Might fail sometimes during the 1st pass with trylock set. */
|
||||
if (!pag->pagf_init)
|
||||
goto next_ag;
|
||||
|
||||
/* Keep track of the AG with the most free blocks. */
|
||||
if (pag->pagf_freeblks > maxfree) {
|
||||
maxfree = pag->pagf_freeblks;
|
||||
|
|
|
@ -2546,6 +2546,7 @@ xfs_ifree_cluster(
|
|||
struct xfs_perag *pag;
|
||||
struct xfs_ino_geometry *igeo = M_IGEO(mp);
|
||||
xfs_ino_t inum;
|
||||
int error;
|
||||
|
||||
inum = xic->first_ino;
|
||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, inum));
|
||||
|
@ -2574,12 +2575,11 @@ xfs_ifree_cluster(
|
|||
* complete before we get a lock on it, and hence we may fail
|
||||
* to mark all the active inodes on the buffer stale.
|
||||
*/
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
|
||||
mp->m_bsize * igeo->blocks_per_cluster,
|
||||
XBF_UNMAPPED);
|
||||
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
|
||||
mp->m_bsize * igeo->blocks_per_cluster,
|
||||
XBF_UNMAPPED, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* This buffer may not have been correctly initialised as we
|
||||
|
|
|
@ -294,7 +294,7 @@ xlog_recover_iodone(
|
|||
* this during recovery. One strike!
|
||||
*/
|
||||
if (!XFS_FORCED_SHUTDOWN(bp->b_mount)) {
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_ioerror_alert(bp, __this_address);
|
||||
xfs_force_shutdown(bp->b_mount, SHUTDOWN_META_IO_ERROR);
|
||||
}
|
||||
}
|
||||
|
@ -2745,15 +2745,10 @@ xlog_recover_buffer_pass2(
|
|||
if (buf_f->blf_flags & XFS_BLF_INODE_BUF)
|
||||
buf_flags |= XBF_UNMAPPED;
|
||||
|
||||
bp = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len,
|
||||
buf_flags, NULL);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#1)");
|
||||
goto out_release;
|
||||
}
|
||||
error = xfs_buf_read(mp->m_ddev_targp, buf_f->blf_blkno, buf_f->blf_len,
|
||||
buf_flags, &bp, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* Recover the buffer only if we get an LSN from it and it's less than
|
||||
|
@ -2950,17 +2945,10 @@ xlog_recover_inode_pass2(
|
|||
}
|
||||
trace_xfs_log_recover_inode_recover(log, in_f);
|
||||
|
||||
bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0,
|
||||
&xfs_inode_buf_ops);
|
||||
if (!bp) {
|
||||
error = -ENOMEM;
|
||||
error = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len,
|
||||
0, &bp, &xfs_inode_buf_ops);
|
||||
if (error)
|
||||
goto error;
|
||||
}
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_buf_ioerror_alert(bp, "xlog_recover_do..(read#2)");
|
||||
goto out_release;
|
||||
}
|
||||
ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
|
||||
dip = xfs_buf_offset(bp, in_f->ilf_boffset);
|
||||
|
||||
|
@ -5639,7 +5627,7 @@ xlog_do_recover(
|
|||
error = xfs_buf_submit(bp);
|
||||
if (error) {
|
||||
if (!XFS_FORCED_SHUTDOWN(mp)) {
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_ioerror_alert(bp, __this_address);
|
||||
ASSERT(0);
|
||||
}
|
||||
xfs_buf_relse(bp);
|
||||
|
|
|
@ -143,8 +143,6 @@ xfs_reflink_find_shared(
|
|||
error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!agbp)
|
||||
return -ENOMEM;
|
||||
|
||||
cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
|
||||
|
||||
|
|
|
@ -826,12 +826,10 @@ xfs_growfs_rt_alloc(
|
|||
* Get a buffer for the block.
|
||||
*/
|
||||
d = XFS_FSB_TO_DADDR(mp, fsbno);
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize, 0);
|
||||
if (bp == NULL) {
|
||||
error = -EIO;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
mp->m_bsize, 0, &bp);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
}
|
||||
memset(bp->b_addr, 0, mp->m_sb.sb_blocksize);
|
||||
xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1);
|
||||
/*
|
||||
|
|
|
@ -53,20 +53,10 @@ xfs_readlink_bmap_ilocked(
|
|||
d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
|
||||
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
|
||||
|
||||
bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
|
||||
&xfs_symlink_buf_ops);
|
||||
if (!bp)
|
||||
return -ENOMEM;
|
||||
error = bp->b_error;
|
||||
if (error) {
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_relse(bp);
|
||||
|
||||
/* bad CRC means corrupted metadata */
|
||||
if (error == -EFSBADCRC)
|
||||
error = -EFSCORRUPTED;
|
||||
goto out;
|
||||
}
|
||||
error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
|
||||
&bp, &xfs_symlink_buf_ops);
|
||||
if (error)
|
||||
return error;
|
||||
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
|
||||
if (pathlen < byte_cnt)
|
||||
byte_cnt = pathlen;
|
||||
|
@ -290,12 +280,10 @@ xfs_symlink(
|
|||
|
||||
d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
|
||||
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
BTOBB(byte_cnt), 0);
|
||||
if (!bp) {
|
||||
error = -ENOMEM;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
|
||||
BTOBB(byte_cnt), 0, &bp);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
}
|
||||
bp->b_ops = &xfs_symlink_buf_ops;
|
||||
|
||||
byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
|
||||
|
@ -433,13 +421,12 @@ xfs_inactive_symlink_rmt(
|
|||
* Invalidate the block(s). No validation is done.
|
||||
*/
|
||||
for (i = 0; i < nmaps; i++) {
|
||||
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
|
||||
XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0);
|
||||
if (!bp) {
|
||||
error = -ENOMEM;
|
||||
error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
|
||||
XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
|
||||
XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
|
||||
&bp);
|
||||
if (error)
|
||||
goto error_trans_cancel;
|
||||
}
|
||||
xfs_trans_binval(tp, bp);
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -169,21 +169,21 @@ int xfs_trans_alloc_empty(struct xfs_mount *mp,
|
|||
struct xfs_trans **tpp);
|
||||
void xfs_trans_mod_sb(xfs_trans_t *, uint, int64_t);
|
||||
|
||||
struct xfs_buf *xfs_trans_get_buf_map(struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps,
|
||||
uint flags);
|
||||
int xfs_trans_get_buf_map(struct xfs_trans *tp, struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map, int nmaps, xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp);
|
||||
|
||||
static inline struct xfs_buf *
|
||||
static inline int
|
||||
xfs_trans_get_buf(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
xfs_daddr_t blkno,
|
||||
int numblks,
|
||||
uint flags)
|
||||
uint flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
DEFINE_SINGLE_BUF_MAP(map, blkno, numblks);
|
||||
return xfs_trans_get_buf_map(tp, target, &map, 1, flags);
|
||||
return xfs_trans_get_buf_map(tp, target, &map, 1, flags, bpp);
|
||||
}
|
||||
|
||||
int xfs_trans_read_buf_map(struct xfs_mount *mp,
|
||||
|
|
|
@ -112,19 +112,22 @@ xfs_trans_bjoin(
|
|||
* If the transaction pointer is NULL, make this just a normal
|
||||
* get_buf() call.
|
||||
*/
|
||||
struct xfs_buf *
|
||||
int
|
||||
xfs_trans_get_buf_map(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buftarg *target,
|
||||
struct xfs_buf_map *map,
|
||||
int nmaps,
|
||||
xfs_buf_flags_t flags)
|
||||
xfs_buf_flags_t flags,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_buf_t *bp;
|
||||
struct xfs_buf_log_item *bip;
|
||||
int error;
|
||||
|
||||
*bpp = NULL;
|
||||
if (!tp)
|
||||
return xfs_buf_get_map(target, map, nmaps, flags);
|
||||
return xfs_buf_get_map(target, map, nmaps, flags, bpp);
|
||||
|
||||
/*
|
||||
* If we find the buffer in the cache with this transaction
|
||||
|
@ -146,19 +149,20 @@ xfs_trans_get_buf_map(
|
|||
ASSERT(atomic_read(&bip->bli_refcount) > 0);
|
||||
bip->bli_recur++;
|
||||
trace_xfs_trans_get_buf_recur(bip);
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bp = xfs_buf_get_map(target, map, nmaps, flags);
|
||||
if (bp == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
error = xfs_buf_get_map(target, map, nmaps, flags, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ASSERT(!bp->b_error);
|
||||
|
||||
_xfs_trans_bjoin(tp, bp, 1);
|
||||
trace_xfs_trans_get_buf(bp->b_log_item);
|
||||
return bp;
|
||||
*bpp = bp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -276,7 +280,7 @@ xfs_trans_read_buf_map(
|
|||
ASSERT(bp->b_ops != NULL);
|
||||
error = xfs_buf_reverify(bp, ops);
|
||||
if (error) {
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
xfs_buf_ioerror_alert(bp, __return_address);
|
||||
|
||||
if (tp->t_flags & XFS_TRANS_DIRTY)
|
||||
xfs_force_shutdown(tp->t_mountp,
|
||||
|
@ -298,36 +302,17 @@ xfs_trans_read_buf_map(
|
|||
return 0;
|
||||
}
|
||||
|
||||
bp = xfs_buf_read_map(target, map, nmaps, flags, ops);
|
||||
if (!bp) {
|
||||
if (!(flags & XBF_TRYLOCK))
|
||||
return -ENOMEM;
|
||||
return tp ? 0 : -EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've had a read error, then the contents of the buffer are
|
||||
* invalid and should not be used. To ensure that a followup read tries
|
||||
* to pull the buffer from disk again, we clear the XBF_DONE flag and
|
||||
* mark the buffer stale. This ensures that anyone who has a current
|
||||
* reference to the buffer will interpret it's contents correctly and
|
||||
* future cache lookups will also treat it as an empty, uninitialised
|
||||
* buffer.
|
||||
*/
|
||||
if (bp->b_error) {
|
||||
error = bp->b_error;
|
||||
if (!XFS_FORCED_SHUTDOWN(mp))
|
||||
xfs_buf_ioerror_alert(bp, __func__);
|
||||
bp->b_flags &= ~XBF_DONE;
|
||||
xfs_buf_stale(bp);
|
||||
|
||||
error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops,
|
||||
__return_address);
|
||||
switch (error) {
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
if (tp && (tp->t_flags & XFS_TRANS_DIRTY))
|
||||
xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
|
||||
xfs_buf_relse(bp);
|
||||
|
||||
/* bad CRC means corrupted metadata */
|
||||
if (error == -EFSBADCRC)
|
||||
error = -EFSCORRUPTED;
|
||||
/* fall through */
|
||||
case -ENOMEM:
|
||||
case -EAGAIN:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue