mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	xfs: always log corruption errors
Make sure we log something to dmesg whenever we return -EFSCORRUPTED up the call stack. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
		
							parent
							
								
									d243b89a61
								
							
						
					
					
						commit
						a5155b870d
					
				
					 25 changed files with 179 additions and 45 deletions
				
			
		| 
						 | 
					@ -702,8 +702,10 @@ xfs_alloc_update_counters(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xfs_trans_agblocks_delta(tp, len);
 | 
						xfs_trans_agblocks_delta(tp, len);
 | 
				
			||||||
	if (unlikely(be32_to_cpu(agf->agf_freeblks) >
 | 
						if (unlikely(be32_to_cpu(agf->agf_freeblks) >
 | 
				
			||||||
		     be32_to_cpu(agf->agf_length)))
 | 
							     be32_to_cpu(agf->agf_length))) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(agbp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
 | 
						xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1048,6 +1050,7 @@ xfs_alloc_ag_vextent_small(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno);
 | 
							bp = xfs_btree_get_bufs(args->mp, args->tp, args->agno, fbno);
 | 
				
			||||||
		if (!bp) {
 | 
							if (!bp) {
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->mp);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2215,8 +2218,10 @@ xfs_free_agfl_block(
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno);
 | 
						bp = xfs_btree_get_bufs(tp->t_mountp, tp, agno, agbno);
 | 
				
			||||||
	if (!bp)
 | 
						if (!bp) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	xfs_trans_binval(tp, bp);
 | 
						xfs_trans_binval(tp, bp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2346,8 +2346,10 @@ xfs_attr3_leaf_lookup_int(
 | 
				
			||||||
	leaf = bp->b_addr;
 | 
						leaf = bp->b_addr;
 | 
				
			||||||
	xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
 | 
						xfs_attr3_leaf_hdr_from_disk(args->geo, &ichdr, leaf);
 | 
				
			||||||
	entries = xfs_attr3_leaf_entryp(leaf);
 | 
						entries = xfs_attr3_leaf_entryp(leaf);
 | 
				
			||||||
	if (ichdr.count >= args->geo->blksize / 8)
 | 
						if (ichdr.count >= args->geo->blksize / 8) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Binary search.  (note: small blocks will skip this loop)
 | 
						 * Binary search.  (note: small blocks will skip this loop)
 | 
				
			||||||
| 
						 | 
					@ -2363,10 +2365,14 @@ xfs_attr3_leaf_lookup_int(
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count)))
 | 
						if (!(probe >= 0 && (!ichdr.count || probe < ichdr.count))) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval))
 | 
						}
 | 
				
			||||||
 | 
						if (!(span <= 4 || be32_to_cpu(entry->hashval) == hashval)) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Since we may have duplicate hashval's, find the first matching
 | 
						 * Since we may have duplicate hashval's, find the first matching
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -730,6 +730,7 @@ xfs_bmap_extents_to_btree(
 | 
				
			||||||
	xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
 | 
						xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, 1L);
 | 
				
			||||||
	abp = xfs_btree_get_bufl(mp, tp, args.fsbno);
 | 
						abp = xfs_btree_get_bufl(mp, tp, args.fsbno);
 | 
				
			||||||
	if (!abp) {
 | 
						if (!abp) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		goto out_unreserve_dquot;
 | 
							goto out_unreserve_dquot;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1085,6 +1086,7 @@ xfs_bmap_add_attrfork(
 | 
				
			||||||
	if (XFS_IFORK_Q(ip))
 | 
						if (XFS_IFORK_Q(ip))
 | 
				
			||||||
		goto trans_cancel;
 | 
							goto trans_cancel;
 | 
				
			||||||
	if (ip->i_d.di_anextents != 0) {
 | 
						if (ip->i_d.di_anextents != 0) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		goto trans_cancel;
 | 
							goto trans_cancel;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1338,6 +1340,7 @@ xfs_bmap_last_before(
 | 
				
			||||||
	case XFS_DINODE_FMT_EXTENTS:
 | 
						case XFS_DINODE_FMT_EXTENTS:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 | 
							ASSERT(0);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1438,8 +1441,10 @@ xfs_bmap_last_offset(
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 | 
						if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
 | 
				
			||||||
	    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)
 | 
						    XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) {
 | 
				
			||||||
 | 
							ASSERT(0);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
 | 
						error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty);
 | 
				
			||||||
	if (error || is_empty)
 | 
						if (error || is_empty)
 | 
				
			||||||
| 
						 | 
					@ -5830,6 +5835,7 @@ xfs_bmap_insert_extents(
 | 
				
			||||||
				del_cursor);
 | 
									del_cursor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (stop_fsb >= got.br_startoff + got.br_blockcount) {
 | 
						if (stop_fsb >= got.br_startoff + got.br_blockcount) {
 | 
				
			||||||
 | 
							ASSERT(0);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		goto del_cursor;
 | 
							goto del_cursor;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1820,6 +1820,7 @@ xfs_btree_lookup_get_block(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_bad:
 | 
					out_bad:
 | 
				
			||||||
	*blkp = NULL;
 | 
						*blkp = NULL;
 | 
				
			||||||
 | 
						xfs_buf_corruption_error(bp);
 | 
				
			||||||
	xfs_trans_brelse(cur->bc_tp, bp);
 | 
						xfs_trans_brelse(cur->bc_tp, bp);
 | 
				
			||||||
	return -EFSCORRUPTED;
 | 
						return -EFSCORRUPTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1867,8 +1868,10 @@ xfs_btree_lookup(
 | 
				
			||||||
	XFS_BTREE_STATS_INC(cur, lookup);
 | 
						XFS_BTREE_STATS_INC(cur, lookup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* No such thing as a zero-level tree. */
 | 
						/* No such thing as a zero-level tree. */
 | 
				
			||||||
	if (cur->bc_nlevels == 0)
 | 
						if (cur->bc_nlevels == 0) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	block = NULL;
 | 
						block = NULL;
 | 
				
			||||||
	keyno = 0;
 | 
						keyno = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -504,6 +504,7 @@ xfs_da3_split(
 | 
				
			||||||
	node = oldblk->bp->b_addr;
 | 
						node = oldblk->bp->b_addr;
 | 
				
			||||||
	if (node->hdr.info.forw) {
 | 
						if (node->hdr.info.forw) {
 | 
				
			||||||
		if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
 | 
							if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) {
 | 
				
			||||||
 | 
								xfs_buf_corruption_error(oldblk->bp);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -516,6 +517,7 @@ xfs_da3_split(
 | 
				
			||||||
	node = oldblk->bp->b_addr;
 | 
						node = oldblk->bp->b_addr;
 | 
				
			||||||
	if (node->hdr.info.back) {
 | 
						if (node->hdr.info.back) {
 | 
				
			||||||
		if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
 | 
							if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) {
 | 
				
			||||||
 | 
								xfs_buf_corruption_error(oldblk->bp);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -1541,8 +1543,10 @@ xfs_da3_node_lookup_int(
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC)
 | 
							if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) {
 | 
				
			||||||
 | 
								xfs_buf_corruption_error(blk->bp);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		blk->magic = XFS_DA_NODE_MAGIC;
 | 
							blk->magic = XFS_DA_NODE_MAGIC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1554,15 +1558,18 @@ xfs_da3_node_lookup_int(
 | 
				
			||||||
		btree = dp->d_ops->node_tree_p(node);
 | 
							btree = dp->d_ops->node_tree_p(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Tree taller than we can handle; bail out! */
 | 
							/* Tree taller than we can handle; bail out! */
 | 
				
			||||||
		if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
 | 
							if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) {
 | 
				
			||||||
 | 
								xfs_buf_corruption_error(blk->bp);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* Check the level from the root. */
 | 
							/* Check the level from the root. */
 | 
				
			||||||
		if (blkno == args->geo->leafblk)
 | 
							if (blkno == args->geo->leafblk)
 | 
				
			||||||
			expected_level = nodehdr.level - 1;
 | 
								expected_level = nodehdr.level - 1;
 | 
				
			||||||
		else if (expected_level != nodehdr.level)
 | 
							else if (expected_level != nodehdr.level) {
 | 
				
			||||||
 | 
								xfs_buf_corruption_error(blk->bp);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		else
 | 
							} else
 | 
				
			||||||
			expected_level--;
 | 
								expected_level--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		max = nodehdr.count;
 | 
							max = nodehdr.count;
 | 
				
			||||||
| 
						 | 
					@ -1612,12 +1619,17 @@ xfs_da3_node_lookup_int(
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* We can't point back to the root. */
 | 
							/* We can't point back to the root. */
 | 
				
			||||||
		if (blkno == args->geo->leafblk)
 | 
							if (blkno == args->geo->leafblk) {
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
 | 
				
			||||||
 | 
										dp->i_mount);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (expected_level != 0)
 | 
						if (expected_level != 0) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, dp->i_mount);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * A leaf block that ends in the hashval that we are interested in
 | 
						 * A leaf block that ends in the hashval that we are interested in
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -600,8 +600,10 @@ xfs_dir2_isblock(
 | 
				
			||||||
	if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
 | 
						if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
 | 
				
			||||||
		return rval;
 | 
							return rval;
 | 
				
			||||||
	rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
 | 
						rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
 | 
				
			||||||
	if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
 | 
						if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	*vp = rval;
 | 
						*vp = rval;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1343,8 +1343,10 @@ xfs_dir2_leaf_removename(
 | 
				
			||||||
	oldbest = be16_to_cpu(bf[0].length);
 | 
						oldbest = be16_to_cpu(bf[0].length);
 | 
				
			||||||
	ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 | 
						ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 | 
				
			||||||
	bestsp = xfs_dir2_leaf_bests_p(ltp);
 | 
						bestsp = xfs_dir2_leaf_bests_p(ltp);
 | 
				
			||||||
	if (be16_to_cpu(bestsp[db]) != oldbest)
 | 
						if (be16_to_cpu(bestsp[db]) != oldbest) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(lbp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Mark the former data entry unused.
 | 
						 * Mark the former data entry unused.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -373,8 +373,10 @@ xfs_dir2_leaf_to_node(
 | 
				
			||||||
	leaf = lbp->b_addr;
 | 
						leaf = lbp->b_addr;
 | 
				
			||||||
	ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 | 
						ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
 | 
				
			||||||
	if (be32_to_cpu(ltp->bestcount) >
 | 
						if (be32_to_cpu(ltp->bestcount) >
 | 
				
			||||||
				(uint)dp->i_d.di_size / args->geo->blksize)
 | 
									(uint)dp->i_d.di_size / args->geo->blksize) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(lbp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Copy freespace entries from the leaf block to the new block.
 | 
						 * Copy freespace entries from the leaf block to the new block.
 | 
				
			||||||
| 
						 | 
					@ -445,8 +447,10 @@ xfs_dir2_leafn_add(
 | 
				
			||||||
	 * Quick check just to make sure we are not going to index
 | 
						 * Quick check just to make sure we are not going to index
 | 
				
			||||||
	 * into other peoples memory
 | 
						 * into other peoples memory
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (index < 0)
 | 
						if (index < 0) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If there are already the maximum number of leaf entries in
 | 
						 * If there are already the maximum number of leaf entries in
 | 
				
			||||||
| 
						 | 
					@ -739,8 +743,10 @@ 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);
 | 
				
			||||||
	if (leafhdr.count <= 0)
 | 
						if (leafhdr.count <= 0) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Look up the hash value in the leaf entries.
 | 
						 * Look up the hash value in the leaf entries.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,11 +75,15 @@ xfs_iformat_fork(
 | 
				
			||||||
			error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
 | 
								error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
 | 
								xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
 | 
				
			||||||
 | 
										dip, sizeof(*dip), __this_address);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 | 
							xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
 | 
				
			||||||
 | 
									sizeof(*dip), __this_address);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
| 
						 | 
					@ -110,6 +114,8 @@ xfs_iformat_fork(
 | 
				
			||||||
		error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
 | 
							error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 | 
							xfs_inode_verifier_error(ip, error, __func__, dip,
 | 
				
			||||||
 | 
									sizeof(*dip), __this_address);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1591,8 +1591,10 @@ xfs_refcount_recover_extent(
 | 
				
			||||||
	struct list_head		*debris = priv;
 | 
						struct list_head		*debris = priv;
 | 
				
			||||||
	struct xfs_refcount_recovery	*rr;
 | 
						struct xfs_refcount_recovery	*rr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (be32_to_cpu(rec->refc.rc_refcount) != 1)
 | 
						if (be32_to_cpu(rec->refc.rc_refcount) != 1) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, cur->bc_mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);
 | 
						rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);
 | 
				
			||||||
	xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);
 | 
						xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@
 | 
				
			||||||
#include "xfs_bmap.h"
 | 
					#include "xfs_bmap.h"
 | 
				
			||||||
#include "xfs_trans.h"
 | 
					#include "xfs_trans.h"
 | 
				
			||||||
#include "xfs_rtalloc.h"
 | 
					#include "xfs_rtalloc.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Realtime allocator bitmap functions shared with userspace.
 | 
					 * Realtime allocator bitmap functions shared with userspace.
 | 
				
			||||||
| 
						 | 
					@ -70,8 +70,10 @@ xfs_rtbuf_get(
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (nmap == 0 || !xfs_bmap_is_real_extent(&map))
 | 
						if (nmap == 0 || !xfs_bmap_is_real_extent(&map)) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT(map.br_startblock != NULLFSBLOCK);
 | 
						ASSERT(map.br_startblock != NULLFSBLOCK);
 | 
				
			||||||
	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 | 
						error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@
 | 
				
			||||||
#include "xfs_inode.h"
 | 
					#include "xfs_inode.h"
 | 
				
			||||||
#include "xfs_attr.h"
 | 
					#include "xfs_attr.h"
 | 
				
			||||||
#include "xfs_trace.h"
 | 
					#include "xfs_trace.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
#include <linux/posix_acl_xattr.h>
 | 
					#include <linux/posix_acl_xattr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +24,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STATIC struct posix_acl *
 | 
					STATIC struct posix_acl *
 | 
				
			||||||
xfs_acl_from_disk(
 | 
					xfs_acl_from_disk(
 | 
				
			||||||
 | 
						struct xfs_mount	*mp,
 | 
				
			||||||
	const struct xfs_acl	*aclp,
 | 
						const struct xfs_acl	*aclp,
 | 
				
			||||||
	int			len,
 | 
						int			len,
 | 
				
			||||||
	int			max_entries)
 | 
						int			max_entries)
 | 
				
			||||||
| 
						 | 
					@ -32,11 +34,18 @@ xfs_acl_from_disk(
 | 
				
			||||||
	const struct xfs_acl_entry *ace;
 | 
						const struct xfs_acl_entry *ace;
 | 
				
			||||||
	unsigned int count, i;
 | 
						unsigned int count, i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len < sizeof(*aclp))
 | 
						if (len < sizeof(*aclp)) {
 | 
				
			||||||
 | 
							XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
 | 
				
			||||||
 | 
									len);
 | 
				
			||||||
		return ERR_PTR(-EFSCORRUPTED);
 | 
							return ERR_PTR(-EFSCORRUPTED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	count = be32_to_cpu(aclp->acl_cnt);
 | 
						count = be32_to_cpu(aclp->acl_cnt);
 | 
				
			||||||
	if (count > max_entries || XFS_ACL_SIZE(count) != len)
 | 
						if (count > max_entries || XFS_ACL_SIZE(count) != len) {
 | 
				
			||||||
 | 
							XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, aclp,
 | 
				
			||||||
 | 
									len);
 | 
				
			||||||
		return ERR_PTR(-EFSCORRUPTED);
 | 
							return ERR_PTR(-EFSCORRUPTED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	acl = posix_acl_alloc(count, GFP_KERNEL);
 | 
						acl = posix_acl_alloc(count, GFP_KERNEL);
 | 
				
			||||||
	if (!acl)
 | 
						if (!acl)
 | 
				
			||||||
| 
						 | 
					@ -145,7 +154,7 @@ xfs_get_acl(struct inode *inode, int type)
 | 
				
			||||||
		if (error != -ENOATTR)
 | 
							if (error != -ENOATTR)
 | 
				
			||||||
			acl = ERR_PTR(error);
 | 
								acl = ERR_PTR(error);
 | 
				
			||||||
	} else  {
 | 
						} else  {
 | 
				
			||||||
		acl = xfs_acl_from_disk(xfs_acl, len,
 | 
							acl = xfs_acl_from_disk(ip->i_mount, xfs_acl, len,
 | 
				
			||||||
					XFS_ACL_MAX_ENTRIES(ip->i_mount));
 | 
										XFS_ACL_MAX_ENTRIES(ip->i_mount));
 | 
				
			||||||
		kmem_free(xfs_acl);
 | 
							kmem_free(xfs_acl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@
 | 
				
			||||||
#include "xfs_attr_leaf.h"
 | 
					#include "xfs_attr_leaf.h"
 | 
				
			||||||
#include "xfs_quota.h"
 | 
					#include "xfs_quota.h"
 | 
				
			||||||
#include "xfs_dir2.h"
 | 
					#include "xfs_dir2.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Look at all the extents for this logical region,
 | 
					 * Look at all the extents for this logical region,
 | 
				
			||||||
| 
						 | 
					@ -209,6 +210,7 @@ xfs_attr3_node_inactive(
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (level > XFS_DA_NODE_MAXDEPTH) {
 | 
						if (level > XFS_DA_NODE_MAXDEPTH) {
 | 
				
			||||||
		xfs_trans_brelse(*trans, bp);	/* no locks for later trans */
 | 
							xfs_trans_brelse(*trans, bp);	/* no locks for later trans */
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,8 +260,9 @@ xfs_attr3_node_inactive(
 | 
				
			||||||
			error = xfs_attr3_leaf_inactive(trans, dp, child_bp);
 | 
								error = xfs_attr3_leaf_inactive(trans, dp, child_bp);
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								xfs_buf_corruption_error(child_bp);
 | 
				
			||||||
			xfs_trans_brelse(*trans, child_bp);
 | 
								xfs_trans_brelse(*trans, child_bp);
 | 
				
			||||||
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (error)
 | 
							if (error)
 | 
				
			||||||
| 
						 | 
					@ -342,6 +345,7 @@ xfs_attr3_root_inactive(
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(bp);
 | 
				
			||||||
		xfs_trans_brelse(*trans, bp);
 | 
							xfs_trans_brelse(*trans, bp);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -269,9 +269,11 @@ xfs_attr_node_list_lookup(
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* We can't point back to the root. */
 | 
							/* We can't point back to the root. */
 | 
				
			||||||
		if (cursor->blkno == 0)
 | 
							if (cursor->blkno == 0) {
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (expected_level != 0)
 | 
						if (expected_level != 0)
 | 
				
			||||||
		goto out_corruptbuf;
 | 
							goto out_corruptbuf;
 | 
				
			||||||
| 
						 | 
					@ -280,6 +282,7 @@ xfs_attr_node_list_lookup(
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_corruptbuf:
 | 
					out_corruptbuf:
 | 
				
			||||||
 | 
						xfs_buf_corruption_error(bp);
 | 
				
			||||||
	xfs_trans_brelse(tp, bp);
 | 
						xfs_trans_brelse(tp, bp);
 | 
				
			||||||
	return -EFSCORRUPTED;
 | 
						return -EFSCORRUPTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
#include "xfs_icache.h"
 | 
					#include "xfs_icache.h"
 | 
				
			||||||
#include "xfs_bmap_btree.h"
 | 
					#include "xfs_bmap_btree.h"
 | 
				
			||||||
#include "xfs_trans_space.h"
 | 
					#include "xfs_trans_space.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kmem_zone_t	*xfs_bui_zone;
 | 
					kmem_zone_t	*xfs_bui_zone;
 | 
				
			||||||
kmem_zone_t	*xfs_bud_zone;
 | 
					kmem_zone_t	*xfs_bud_zone;
 | 
				
			||||||
| 
						 | 
					@ -525,6 +525,7 @@ xfs_bui_recover(
 | 
				
			||||||
		type = bui_type;
 | 
							type = bui_type;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		goto err_inode;
 | 
							goto err_inode;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -341,6 +341,27 @@ xfs_corruption_error(
 | 
				
			||||||
	xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
 | 
						xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Complain about the kinds of metadata corruption that we can't detect from a
 | 
				
			||||||
 | 
					 * verifier, such as incorrect inter-block relationship data.  Does not set
 | 
				
			||||||
 | 
					 * bp->b_error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					xfs_buf_corruption_error(
 | 
				
			||||||
 | 
						struct xfs_buf		*bp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct xfs_mount	*mp = bp->b_mount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfs_alert_tag(mp, XFS_PTAG_VERIFIER_ERROR,
 | 
				
			||||||
 | 
							  "Metadata corruption detected at %pS, %s block 0x%llx",
 | 
				
			||||||
 | 
							  __return_address, bp->b_ops->name, bp->b_bn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xfs_alert(mp, "Unmount and run xfs_repair");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xfs_error_level >= XFS_ERRLEVEL_HIGH)
 | 
				
			||||||
 | 
							xfs_stack_trace();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Warnings specifically for verifier errors.  Differentiate CRC vs. invalid
 | 
					 * Warnings specifically for verifier errors.  Differentiate CRC vs. invalid
 | 
				
			||||||
 * values, and omit the stack trace unless the error level is tuned high.
 | 
					 * values, and omit the stack trace unless the error level is tuned high.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ extern void xfs_corruption_error(const char *tag, int level,
 | 
				
			||||||
			struct xfs_mount *mp, const void *buf, size_t bufsize,
 | 
								struct xfs_mount *mp, const void *buf, size_t bufsize,
 | 
				
			||||||
			const char *filename, int linenum,
 | 
								const char *filename, int linenum,
 | 
				
			||||||
			xfs_failaddr_t failaddr);
 | 
								xfs_failaddr_t failaddr);
 | 
				
			||||||
 | 
					void xfs_buf_corruption_error(struct xfs_buf *bp);
 | 
				
			||||||
extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error,
 | 
					extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error,
 | 
				
			||||||
			const char *name, const void *buf, size_t bufsz,
 | 
								const char *name, const void *buf, size_t bufsz,
 | 
				
			||||||
			xfs_failaddr_t failaddr);
 | 
								xfs_failaddr_t failaddr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
#include "xfs_alloc.h"
 | 
					#include "xfs_alloc.h"
 | 
				
			||||||
#include "xfs_bmap.h"
 | 
					#include "xfs_bmap.h"
 | 
				
			||||||
#include "xfs_trace.h"
 | 
					#include "xfs_trace.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kmem_zone_t	*xfs_efi_zone;
 | 
					kmem_zone_t	*xfs_efi_zone;
 | 
				
			||||||
kmem_zone_t	*xfs_efd_zone;
 | 
					kmem_zone_t	*xfs_efd_zone;
 | 
				
			||||||
| 
						 | 
					@ -228,6 +228,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
	return -EFSCORRUPTED;
 | 
						return -EFSCORRUPTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2136,8 +2136,10 @@ xfs_iunlink_update_bucket(
 | 
				
			||||||
	 * passed in because either we're adding or removing ourselves from the
 | 
						 * passed in because either we're adding or removing ourselves from the
 | 
				
			||||||
	 * head of the list.
 | 
						 * head of the list.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (old_value == new_agino)
 | 
						if (old_value == new_agino) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(agibp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino);
 | 
						agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino);
 | 
				
			||||||
	offset = offsetof(struct xfs_agi, agi_unlinked) +
 | 
						offset = offsetof(struct xfs_agi, agi_unlinked) +
 | 
				
			||||||
| 
						 | 
					@ -2200,6 +2202,8 @@ xfs_iunlink_update_inode(
 | 
				
			||||||
	/* Make sure the old pointer isn't garbage. */
 | 
						/* Make sure the old pointer isn't garbage. */
 | 
				
			||||||
	old_value = be32_to_cpu(dip->di_next_unlinked);
 | 
						old_value = be32_to_cpu(dip->di_next_unlinked);
 | 
				
			||||||
	if (!xfs_verify_agino_or_null(mp, agno, old_value)) {
 | 
						if (!xfs_verify_agino_or_null(mp, agno, old_value)) {
 | 
				
			||||||
 | 
							xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
 | 
				
			||||||
 | 
									sizeof(*dip), __this_address);
 | 
				
			||||||
		error = -EFSCORRUPTED;
 | 
							error = -EFSCORRUPTED;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -2211,8 +2215,11 @@ xfs_iunlink_update_inode(
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	*old_next_agino = old_value;
 | 
						*old_next_agino = old_value;
 | 
				
			||||||
	if (old_value == next_agino) {
 | 
						if (old_value == next_agino) {
 | 
				
			||||||
		if (next_agino != NULLAGINO)
 | 
							if (next_agino != NULLAGINO) {
 | 
				
			||||||
 | 
								xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
 | 
				
			||||||
 | 
										dip, sizeof(*dip), __this_address);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2263,8 +2270,10 @@ xfs_iunlink(
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
 | 
						next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
 | 
				
			||||||
	if (next_agino == agino ||
 | 
						if (next_agino == agino ||
 | 
				
			||||||
	    !xfs_verify_agino_or_null(mp, agno, next_agino))
 | 
						    !xfs_verify_agino_or_null(mp, agno, next_agino)) {
 | 
				
			||||||
 | 
							xfs_buf_corruption_error(agibp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (next_agino != NULLAGINO) {
 | 
						if (next_agino != NULLAGINO) {
 | 
				
			||||||
		struct xfs_perag	*pag;
 | 
							struct xfs_perag	*pag;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,6 +17,7 @@
 | 
				
			||||||
#include "xfs_trans_priv.h"
 | 
					#include "xfs_trans_priv.h"
 | 
				
			||||||
#include "xfs_buf_item.h"
 | 
					#include "xfs_buf_item.h"
 | 
				
			||||||
#include "xfs_log.h"
 | 
					#include "xfs_log.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/iversion.h>
 | 
					#include <linux/iversion.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -828,8 +829,10 @@ xfs_inode_item_format_convert(
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct xfs_inode_log_format_32	*in_f32 = buf->i_addr;
 | 
						struct xfs_inode_log_format_32	*in_f32 = buf->i_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buf->i_len != sizeof(*in_f32))
 | 
						if (buf->i_len != sizeof(*in_f32)) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	in_f->ilf_type = in_f32->ilf_type;
 | 
						in_f->ilf_type = in_f32->ilf_type;
 | 
				
			||||||
	in_f->ilf_size = in_f32->ilf_size;
 | 
						in_f->ilf_size = in_f32->ilf_size;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@
 | 
				
			||||||
#include "xfs_symlink.h"
 | 
					#include "xfs_symlink.h"
 | 
				
			||||||
#include "xfs_dir2.h"
 | 
					#include "xfs_dir2.h"
 | 
				
			||||||
#include "xfs_iomap.h"
 | 
					#include "xfs_iomap.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <linux/xattr.h>
 | 
					#include <linux/xattr.h>
 | 
				
			||||||
#include <linux/posix_acl.h>
 | 
					#include <linux/posix_acl.h>
 | 
				
			||||||
| 
						 | 
					@ -470,17 +471,20 @@ xfs_vn_get_link_inline(
 | 
				
			||||||
	struct inode		*inode,
 | 
						struct inode		*inode,
 | 
				
			||||||
	struct delayed_call	*done)
 | 
						struct delayed_call	*done)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct xfs_inode	*ip = XFS_I(inode);
 | 
				
			||||||
	char			*link;
 | 
						char			*link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE);
 | 
						ASSERT(ip->i_df.if_flags & XFS_IFINLINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if
 | 
						 * The VFS crashes on a NULL pointer, so return -EFSCORRUPTED if
 | 
				
			||||||
	 * if_data is junk.
 | 
						 * if_data is junk.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	link = XFS_I(inode)->i_df.if_u1.if_data;
 | 
						link = ip->i_df.if_u1.if_data;
 | 
				
			||||||
	if (!link)
 | 
						if (!link) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, ip->i_mount);
 | 
				
			||||||
		return ERR_PTR(-EFSCORRUPTED);
 | 
							return ERR_PTR(-EFSCORRUPTED);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return link;
 | 
						return link;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3537,6 +3537,7 @@ xfs_cui_copy_format(
 | 
				
			||||||
		memcpy(dst_cui_fmt, src_cui_fmt, len);
 | 
							memcpy(dst_cui_fmt, src_cui_fmt, len);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
	return -EFSCORRUPTED;
 | 
						return -EFSCORRUPTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3601,8 +3602,10 @@ xlog_recover_cud_pass2(
 | 
				
			||||||
	struct xfs_ail			*ailp = log->l_ailp;
 | 
						struct xfs_ail			*ailp = log->l_ailp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cud_formatp = item->ri_buf[0].i_addr;
 | 
						cud_formatp = item->ri_buf[0].i_addr;
 | 
				
			||||||
	if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format))
 | 
						if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	cui_id = cud_formatp->cud_cui_id;
 | 
						cui_id = cud_formatp->cud_cui_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -3654,6 +3657,7 @@ xfs_bui_copy_format(
 | 
				
			||||||
		memcpy(dst_bui_fmt, src_bui_fmt, len);
 | 
							memcpy(dst_bui_fmt, src_bui_fmt, len);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
	return -EFSCORRUPTED;
 | 
						return -EFSCORRUPTED;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3677,8 +3681,10 @@ xlog_recover_bui_pass2(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bui_formatp = item->ri_buf[0].i_addr;
 | 
						bui_formatp = item->ri_buf[0].i_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
 | 
						if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	buip = xfs_bui_init(mp);
 | 
						buip = xfs_bui_init(mp);
 | 
				
			||||||
	error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
 | 
						error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
 | 
				
			||||||
	if (error) {
 | 
						if (error) {
 | 
				
			||||||
| 
						 | 
					@ -3720,8 +3726,10 @@ xlog_recover_bud_pass2(
 | 
				
			||||||
	struct xfs_ail			*ailp = log->l_ailp;
 | 
						struct xfs_ail			*ailp = log->l_ailp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bud_formatp = item->ri_buf[0].i_addr;
 | 
						bud_formatp = item->ri_buf[0].i_addr;
 | 
				
			||||||
	if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format))
 | 
						if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	bui_id = bud_formatp->bud_bui_id;
 | 
						bui_id = bud_formatp->bud_bui_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -5172,9 +5180,11 @@ xlog_recover_process(
 | 
				
			||||||
		 * If the filesystem is CRC enabled, this mismatch becomes a
 | 
							 * If the filesystem is CRC enabled, this mismatch becomes a
 | 
				
			||||||
		 * fatal log corruption failure.
 | 
							 * fatal log corruption failure.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (xfs_sb_version_hascrc(&log->l_mp->m_sb))
 | 
							if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
 | 
				
			||||||
			return -EFSCORRUPTED;
 | 
								return -EFSCORRUPTED;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xlog_unpack_data(rhead, dp, log);
 | 
						xlog_unpack_data(rhead, dp, log);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5296,9 +5306,12 @@ xlog_do_recovery_pass(
 | 
				
			||||||
		"invalid iclog size (%d bytes), using lsunit (%d bytes)",
 | 
							"invalid iclog size (%d bytes), using lsunit (%d bytes)",
 | 
				
			||||||
					 h_size, log->l_mp->m_logbsize);
 | 
										 h_size, log->l_mp->m_logbsize);
 | 
				
			||||||
				h_size = log->l_mp->m_logbsize;
 | 
									h_size = log->l_mp->m_logbsize;
 | 
				
			||||||
			} else
 | 
								} else {
 | 
				
			||||||
 | 
									XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
 | 
				
			||||||
 | 
											log->l_mp);
 | 
				
			||||||
				return -EFSCORRUPTED;
 | 
									return -EFSCORRUPTED;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) &&
 | 
							if ((be32_to_cpu(rhead->h_version) & XLOG_VERSION_2) &&
 | 
				
			||||||
		    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
 | 
							    (h_size > XLOG_HEADER_CYCLE_SIZE)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@
 | 
				
			||||||
#include "xfs_qm.h"
 | 
					#include "xfs_qm.h"
 | 
				
			||||||
#include "xfs_trace.h"
 | 
					#include "xfs_trace.h"
 | 
				
			||||||
#include "xfs_icache.h"
 | 
					#include "xfs_icache.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * The global quota manager. There is only one of these for the entire
 | 
					 * The global quota manager. There is only one of these for the entire
 | 
				
			||||||
| 
						 | 
					@ -754,11 +755,19 @@ xfs_qm_qino_alloc(
 | 
				
			||||||
		if ((flags & XFS_QMOPT_PQUOTA) &&
 | 
							if ((flags & XFS_QMOPT_PQUOTA) &&
 | 
				
			||||||
			     (mp->m_sb.sb_gquotino != NULLFSINO)) {
 | 
								     (mp->m_sb.sb_gquotino != NULLFSINO)) {
 | 
				
			||||||
			ino = mp->m_sb.sb_gquotino;
 | 
								ino = mp->m_sb.sb_gquotino;
 | 
				
			||||||
			ASSERT(mp->m_sb.sb_pquotino == NULLFSINO);
 | 
								if (mp->m_sb.sb_pquotino != NULLFSINO) {
 | 
				
			||||||
 | 
									XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
 | 
				
			||||||
 | 
											mp);
 | 
				
			||||||
 | 
									return -EFSCORRUPTED;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} else if ((flags & XFS_QMOPT_GQUOTA) &&
 | 
							} else if ((flags & XFS_QMOPT_GQUOTA) &&
 | 
				
			||||||
			     (mp->m_sb.sb_pquotino != NULLFSINO)) {
 | 
								     (mp->m_sb.sb_pquotino != NULLFSINO)) {
 | 
				
			||||||
			ino = mp->m_sb.sb_pquotino;
 | 
								ino = mp->m_sb.sb_pquotino;
 | 
				
			||||||
			ASSERT(mp->m_sb.sb_gquotino == NULLFSINO);
 | 
								if (mp->m_sb.sb_gquotino != NULLFSINO) {
 | 
				
			||||||
 | 
									XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW,
 | 
				
			||||||
 | 
											mp);
 | 
				
			||||||
 | 
									return -EFSCORRUPTED;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (ino != NULLFSINO) {
 | 
							if (ino != NULLFSINO) {
 | 
				
			||||||
			error = xfs_iget(mp, NULL, ino, 0, 0, ip);
 | 
								error = xfs_iget(mp, NULL, ino, 0, 0, ip);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
#include "xfs_refcount_item.h"
 | 
					#include "xfs_refcount_item.h"
 | 
				
			||||||
#include "xfs_log.h"
 | 
					#include "xfs_log.h"
 | 
				
			||||||
#include "xfs_refcount.h"
 | 
					#include "xfs_refcount.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kmem_zone_t	*xfs_cui_zone;
 | 
					kmem_zone_t	*xfs_cui_zone;
 | 
				
			||||||
kmem_zone_t	*xfs_cud_zone;
 | 
					kmem_zone_t	*xfs_cud_zone;
 | 
				
			||||||
| 
						 | 
					@ -536,6 +536,7 @@ xfs_cui_recover(
 | 
				
			||||||
			type = refc_type;
 | 
								type = refc_type;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			goto abort_error;
 | 
								goto abort_error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@
 | 
				
			||||||
#include "xfs_rmap_item.h"
 | 
					#include "xfs_rmap_item.h"
 | 
				
			||||||
#include "xfs_log.h"
 | 
					#include "xfs_log.h"
 | 
				
			||||||
#include "xfs_rmap.h"
 | 
					#include "xfs_rmap.h"
 | 
				
			||||||
 | 
					#include "xfs_error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kmem_zone_t	*xfs_rui_zone;
 | 
					kmem_zone_t	*xfs_rui_zone;
 | 
				
			||||||
kmem_zone_t	*xfs_rud_zone;
 | 
					kmem_zone_t	*xfs_rud_zone;
 | 
				
			||||||
| 
						 | 
					@ -171,8 +171,10 @@ xfs_rui_copy_format(
 | 
				
			||||||
	src_rui_fmt = buf->i_addr;
 | 
						src_rui_fmt = buf->i_addr;
 | 
				
			||||||
	len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents);
 | 
						len = xfs_rui_log_format_sizeof(src_rui_fmt->rui_nextents);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (buf->i_len != len)
 | 
						if (buf->i_len != len) {
 | 
				
			||||||
 | 
							XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
		return -EFSCORRUPTED;
 | 
							return -EFSCORRUPTED;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(dst_rui_fmt, src_rui_fmt, len);
 | 
						memcpy(dst_rui_fmt, src_rui_fmt, len);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -581,6 +583,7 @@ xfs_rui_recover(
 | 
				
			||||||
			type = XFS_RMAP_FREE;
 | 
								type = XFS_RMAP_FREE;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
 | 
								XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, NULL);
 | 
				
			||||||
			error = -EFSCORRUPTED;
 | 
								error = -EFSCORRUPTED;
 | 
				
			||||||
			goto abort_error;
 | 
								goto abort_error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue