Commit a69e9051 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'xfs-5.3-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux

Pull xfs fixes from Darrick Wong:

 - Fix crashes when the attr fork isn't present due to errors but inode
   inactivation tries to zap the attr data anyway.

 - Convert more directory corruption debugging asserts to actual
   EFSCORRUPTED returns instead of blowing up later on.

 - Don't fail writeback just because we ran out of memory allocating
   metadata log data.

* tag 'xfs-5.3-fixes-2' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux:
  xfs: don't crash on null attr fork xfs_bmapi_read
  xfs: remove more ondisk directory corruption asserts
  fs: xfs: xfs_log: Don't use KM_MAYFAIL at xfs_log_reserve().
parents 4ec1fa69 8612de3f
...@@ -3835,9 +3835,9 @@ xfs_bmapi_read( ...@@ -3835,9 +3835,9 @@ xfs_bmapi_read(
XFS_STATS_INC(mp, xs_blk_mapr); XFS_STATS_INC(mp, xs_blk_mapr);
ifp = XFS_IFORK_PTR(ip, whichfork); ifp = XFS_IFORK_PTR(ip, whichfork);
if (!ifp) {
/* No CoW fork? Return a hole. */ /* No CoW fork? Return a hole. */
if (whichfork == XFS_COW_FORK && !ifp) { if (whichfork == XFS_COW_FORK) {
mval->br_startoff = bno; mval->br_startoff = bno;
mval->br_startblock = HOLESTARTBLOCK; mval->br_startblock = HOLESTARTBLOCK;
mval->br_blockcount = len; mval->br_blockcount = len;
...@@ -3846,6 +3846,19 @@ xfs_bmapi_read( ...@@ -3846,6 +3846,19 @@ xfs_bmapi_read(
return 0; return 0;
} }
/*
* A missing attr ifork implies that the inode says we're in
* extents or btree format but failed to pass the inode fork
* verifier while trying to load it. Treat that as a file
* corruption too.
*/
#ifdef DEBUG
xfs_alert(mp, "%s: inode %llu missing fork %d",
__func__, ip->i_ino, whichfork);
#endif /* DEBUG */
return -EFSCORRUPTED;
}
if (!(ifp->if_flags & XFS_IFEXTENTS)) { if (!(ifp->if_flags & XFS_IFEXTENTS)) {
error = xfs_iread_extents(NULL, ip, whichfork); error = xfs_iread_extents(NULL, ip, whichfork);
if (error) if (error)
......
...@@ -487,10 +487,8 @@ xfs_da3_split( ...@@ -487,10 +487,8 @@ xfs_da3_split(
ASSERT(state->path.active == 0); ASSERT(state->path.active == 0);
oldblk = &state->path.blk[0]; oldblk = &state->path.blk[0];
error = xfs_da3_root_split(state, oldblk, addblk); error = xfs_da3_root_split(state, oldblk, addblk);
if (error) { if (error)
addblk->bp = NULL; goto out;
return error; /* GROT: dir is inconsistent */
}
/* /*
* Update pointers to the node which used to be block 0 and just got * Update pointers to the node which used to be block 0 and just got
...@@ -505,7 +503,10 @@ xfs_da3_split( ...@@ -505,7 +503,10 @@ xfs_da3_split(
*/ */
node = oldblk->bp->b_addr; node = oldblk->bp->b_addr;
if (node->hdr.info.forw) { if (node->hdr.info.forw) {
ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno); if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
error = -EFSCORRUPTED;
goto out;
}
node = addblk->bp->b_addr; node = addblk->bp->b_addr;
node->hdr.info.back = cpu_to_be32(oldblk->blkno); node->hdr.info.back = cpu_to_be32(oldblk->blkno);
xfs_trans_log_buf(state->args->trans, addblk->bp, xfs_trans_log_buf(state->args->trans, addblk->bp,
...@@ -514,15 +515,19 @@ xfs_da3_split( ...@@ -514,15 +515,19 @@ xfs_da3_split(
} }
node = oldblk->bp->b_addr; node = oldblk->bp->b_addr;
if (node->hdr.info.back) { if (node->hdr.info.back) {
ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno); if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
error = -EFSCORRUPTED;
goto out;
}
node = addblk->bp->b_addr; node = addblk->bp->b_addr;
node->hdr.info.forw = cpu_to_be32(oldblk->blkno); node->hdr.info.forw = cpu_to_be32(oldblk->blkno);
xfs_trans_log_buf(state->args->trans, addblk->bp, xfs_trans_log_buf(state->args->trans, addblk->bp,
XFS_DA_LOGRANGE(node, &node->hdr.info, XFS_DA_LOGRANGE(node, &node->hdr.info,
sizeof(node->hdr.info))); sizeof(node->hdr.info)));
} }
out:
addblk->bp = NULL; addblk->bp = NULL;
return 0; return error;
} }
/* /*
......
...@@ -741,7 +741,8 @@ xfs_dir2_leafn_lookup_for_entry( ...@@ -741,7 +741,8 @@ xfs_dir2_leafn_lookup_for_entry(
ents = dp->d_ops->leaf_ents_p(leaf); ents = dp->d_ops->leaf_ents_p(leaf);
xfs_dir3_leaf_check(dp, bp); xfs_dir3_leaf_check(dp, bp);
ASSERT(leafhdr.count > 0); if (leafhdr.count <= 0)
return -EFSCORRUPTED;
/* /*
* Look up the hash value in the leaf entries. * Look up the hash value in the leaf entries.
......
...@@ -429,10 +429,7 @@ xfs_log_reserve( ...@@ -429,10 +429,7 @@ xfs_log_reserve(
ASSERT(*ticp == NULL); ASSERT(*ticp == NULL);
tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent, tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
KM_SLEEP | KM_MAYFAIL); KM_SLEEP);
if (!tic)
return -ENOMEM;
*ticp = tic; *ticp = tic;
xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt xlog_grant_push_ail(log, tic->t_cnt ? tic->t_unit_res * tic->t_cnt
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment