mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
xfs: set and validate dir/attr block owners [v30.3 06/16]
There are a couple of significant changes that need to be made to the directory and xattr code before we can support online repairs of those data structures. The first change is because online repair is designed to use libxfs to create a replacement dir/xattr structure in a temporary file, and use atomic extent swapping to commit the corrected structure. To avoid the performance hit of walking every block of the new structure to rewrite the owner number before the swap, we instead change libxfs to allow callers of the dir and xattr code the ability to set an explicit owner number to be written into the header fields of any new blocks that are created. For regular operation this will be the directory inode number. The second change is to update the dir/xattr code to actually *check* the owner number in each block that is read off the disk, since we don't currently do that. This has been running on the djcloud for months with no problems. Enjoy! Signed-off-by: Darrick J. Wong <djwong@kernel.org> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQ2qTKExjcn+O1o2YRKO3ySh0YRpgUCZh23UwAKCRBKO3ySh0YR po6LAQD4r4tzS1xMNW/ynLntzLNiYukkjI8uGpHw1tPpwmskKQD8Dw+bmGQPjUUR v62p5rUNcinvgxwdJwBcsOERGlVkIww= =6MPB -----END PGP SIGNATURE----- Merge tag 'dirattr-validate-owners-6.10_2024-04-15' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux into xfs-6.10-mergeA xfs: set and validate dir/attr block owners There are a couple of significant changes that need to be made to the directory and xattr code before we can support online repairs of those data structures. The first change is because online repair is designed to use libxfs to create a replacement dir/xattr structure in a temporary file, and use atomic extent swapping to commit the corrected structure. To avoid the performance hit of walking every block of the new structure to rewrite the owner number before the swap, we instead change libxfs to allow callers of the dir and xattr code the ability to set an explicit owner number to be written into the header fields of any new blocks that are created. For regular operation this will be the directory inode number. The second change is to update the dir/xattr code to actually *check* the owner number in each block that is read off the disk, since we don't currently do that. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org> * tag 'dirattr-validate-owners-6.10_2024-04-15' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux: xfs: validate explicit directory free block owners xfs: validate explicit directory block buffer owners xfs: validate explicit directory data buffer owners xfs: validate directory leaf buffer owners xfs: validate dabtree node buffer owners xfs: validate attr remote value buffer owners xfs: validate attr leaf buffer owners xfs: reduce indenting in xfs_attr_node_list xfs: use the xfs_da_args owner field to set new dir/attr block owner xfs: add an explicit owner field to xfs_da_args
This commit is contained in:
commit
fb1f7c662c
@ -264,6 +264,8 @@ xfs_attr_get(
|
||||
if (xfs_is_shutdown(args->dp->i_mount))
|
||||
return -EIO;
|
||||
|
||||
if (!args->owner)
|
||||
args->owner = args->dp->i_ino;
|
||||
args->geo = args->dp->i_mount->m_attr_geo;
|
||||
args->whichfork = XFS_ATTR_FORK;
|
||||
args->hashval = xfs_da_hashname(args->name, args->namelen);
|
||||
@ -647,8 +649,8 @@ xfs_attr_leaf_remove_attr(
|
||||
int forkoff;
|
||||
int error;
|
||||
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
|
||||
&bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
|
||||
args->blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -679,7 +681,7 @@ xfs_attr_leaf_shrink(
|
||||
if (!xfs_attr_is_leaf(dp))
|
||||
return 0;
|
||||
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -937,6 +939,8 @@ xfs_attr_set(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!args->owner)
|
||||
args->owner = args->dp->i_ino;
|
||||
args->geo = mp->m_attr_geo;
|
||||
args->whichfork = XFS_ATTR_FORK;
|
||||
args->hashval = xfs_da_hashname(args->name, args->namelen);
|
||||
@ -1154,7 +1158,7 @@ xfs_attr_leaf_try_add(
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -1202,7 +1206,7 @@ xfs_attr_leaf_hasname(
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner, 0, bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -388,6 +388,27 @@ xfs_attr3_leaf_verify(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xfs_failaddr_t
|
||||
xfs_attr3_leaf_header_check(
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_attr3_leafblock *hdr3 = bp->b_addr;
|
||||
|
||||
if (hdr3->hdr.info.hdr.magic !=
|
||||
cpu_to_be16(XFS_ATTR3_LEAF_MAGIC))
|
||||
return __this_address;
|
||||
|
||||
if (be64_to_cpu(hdr3->hdr.info.owner) != owner)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_attr3_leaf_write_verify(
|
||||
struct xfs_buf *bp)
|
||||
@ -448,16 +469,30 @@ int
|
||||
xfs_attr3_leaf_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t bno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_failaddr_t fa;
|
||||
int err;
|
||||
|
||||
err = xfs_da_read_buf(tp, dp, bno, 0, bpp, XFS_ATTR_FORK,
|
||||
&xfs_attr3_leaf_buf_ops);
|
||||
if (!err && tp && *bpp)
|
||||
if (err || !(*bpp))
|
||||
return err;
|
||||
|
||||
fa = xfs_attr3_leaf_header_check(*bpp, owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
*bpp = NULL;
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (tp)
|
||||
xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_ATTR_LEAF_BUF);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*========================================================================
|
||||
@ -904,6 +939,7 @@ xfs_attr_shortform_to_leaf(
|
||||
nargs.whichfork = XFS_ATTR_FORK;
|
||||
nargs.trans = args->trans;
|
||||
nargs.op_flags = XFS_DA_OP_OKNOENT;
|
||||
nargs.owner = args->owner;
|
||||
|
||||
sfe = xfs_attr_sf_firstentry(sf);
|
||||
for (i = 0; i < sf->count; i++) {
|
||||
@ -1106,6 +1142,7 @@ xfs_attr3_leaf_to_shortform(
|
||||
nargs.whichfork = XFS_ATTR_FORK;
|
||||
nargs.trans = args->trans;
|
||||
nargs.op_flags = XFS_DA_OP_OKNOENT;
|
||||
nargs.owner = args->owner;
|
||||
|
||||
for (i = 0; i < ichdr.count; entry++, i++) {
|
||||
if (entry->flags & XFS_ATTR_INCOMPLETE)
|
||||
@ -1158,7 +1195,7 @@ xfs_attr3_leaf_to_node(
|
||||
error = xfs_da_grow_inode(args, &blkno);
|
||||
if (error)
|
||||
goto out;
|
||||
error = xfs_attr3_leaf_read(args->trans, dp, 0, &bp1);
|
||||
error = xfs_attr3_leaf_read(args->trans, dp, args->owner, 0, &bp1);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
@ -1237,7 +1274,7 @@ xfs_attr3_leaf_create(
|
||||
ichdr.magic = XFS_ATTR3_LEAF_MAGIC;
|
||||
|
||||
hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
hdr3->owner = cpu_to_be64(dp->i_ino);
|
||||
hdr3->owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
|
||||
|
||||
ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr);
|
||||
@ -1993,7 +2030,7 @@ xfs_attr3_leaf_toosmall(
|
||||
if (blkno == 0)
|
||||
continue;
|
||||
error = xfs_attr3_leaf_read(state->args->trans, state->args->dp,
|
||||
blkno, &bp);
|
||||
state->args->owner, blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -2715,7 +2752,8 @@ xfs_attr3_leaf_clearflag(
|
||||
/*
|
||||
* Set up the operation.
|
||||
*/
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
|
||||
args->blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -2779,7 +2817,8 @@ xfs_attr3_leaf_setflag(
|
||||
/*
|
||||
* Set up the operation.
|
||||
*/
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
|
||||
args->blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -2838,7 +2877,8 @@ xfs_attr3_leaf_flipflags(
|
||||
/*
|
||||
* Read the block containing the "old" attr
|
||||
*/
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp1);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
|
||||
args->blkno, &bp1);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -2846,8 +2886,8 @@ xfs_attr3_leaf_flipflags(
|
||||
* Read the block containing the "new" attr, if it is different
|
||||
*/
|
||||
if (args->blkno2 != args->blkno) {
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno2,
|
||||
&bp2);
|
||||
error = xfs_attr3_leaf_read(args->trans, args->dp, args->owner,
|
||||
args->blkno2, &bp2);
|
||||
if (error)
|
||||
return error;
|
||||
} else {
|
||||
|
@ -98,12 +98,14 @@ int xfs_attr_leaf_order(struct xfs_buf *leaf1_bp,
|
||||
struct xfs_buf *leaf2_bp);
|
||||
int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int *local);
|
||||
int xfs_attr3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_dablk_t bno, struct xfs_buf **bpp);
|
||||
xfs_ino_t owner, xfs_dablk_t bno, struct xfs_buf **bpp);
|
||||
void xfs_attr3_leaf_hdr_from_disk(struct xfs_da_geometry *geo,
|
||||
struct xfs_attr3_icleaf_hdr *to,
|
||||
struct xfs_attr_leafblock *from);
|
||||
void xfs_attr3_leaf_hdr_to_disk(struct xfs_da_geometry *geo,
|
||||
struct xfs_attr_leafblock *to,
|
||||
struct xfs_attr3_icleaf_hdr *from);
|
||||
xfs_failaddr_t xfs_attr3_leaf_header_check(struct xfs_buf *bp,
|
||||
xfs_ino_t owner);
|
||||
|
||||
#endif /* __XFS_ATTR_LEAF_H__ */
|
||||
|
@ -280,12 +280,12 @@ xfs_attr_rmtval_copyout(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_buf *bp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
int *offset,
|
||||
int *valuelen,
|
||||
uint8_t **dst)
|
||||
{
|
||||
char *src = bp->b_addr;
|
||||
xfs_ino_t ino = dp->i_ino;
|
||||
xfs_daddr_t bno = xfs_buf_daddr(bp);
|
||||
int len = BBTOB(bp->b_length);
|
||||
int blksize = mp->m_attr_geo->blksize;
|
||||
@ -299,11 +299,11 @@ xfs_attr_rmtval_copyout(
|
||||
byte_cnt = min(*valuelen, byte_cnt);
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
if (xfs_attr3_rmt_hdr_ok(src, ino, *offset,
|
||||
if (xfs_attr3_rmt_hdr_ok(src, owner, *offset,
|
||||
byte_cnt, bno)) {
|
||||
xfs_alert(mp,
|
||||
"remote attribute header mismatch bno/off/len/owner (0x%llx/0x%x/Ox%x/0x%llx)",
|
||||
bno, *offset, byte_cnt, ino);
|
||||
bno, *offset, byte_cnt, owner);
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
@ -427,8 +427,7 @@ xfs_attr_rmtval_get(
|
||||
return error;
|
||||
|
||||
error = xfs_attr_rmtval_copyout(mp, bp, args->dp,
|
||||
&offset, &valuelen,
|
||||
&dst);
|
||||
args->owner, &offset, &valuelen, &dst);
|
||||
xfs_buf_relse(bp);
|
||||
if (error)
|
||||
return error;
|
||||
@ -522,8 +521,8 @@ xfs_attr_rmtval_set_value(
|
||||
return error;
|
||||
bp->b_ops = &xfs_attr3_rmt_buf_ops;
|
||||
|
||||
xfs_attr_rmtval_copyin(mp, bp, args->dp->i_ino, &offset,
|
||||
&valuelen, &src);
|
||||
xfs_attr_rmtval_copyin(mp, bp, args->owner, &offset, &valuelen,
|
||||
&src);
|
||||
|
||||
error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */
|
||||
xfs_buf_relse(bp);
|
||||
|
@ -976,6 +976,7 @@ xfs_bmap_add_attrfork_local(
|
||||
dargs.total = dargs.geo->fsbcount;
|
||||
dargs.whichfork = XFS_DATA_FORK;
|
||||
dargs.trans = tp;
|
||||
dargs.owner = ip->i_ino;
|
||||
return xfs_dir2_sf_to_block(&dargs);
|
||||
}
|
||||
|
||||
|
@ -252,6 +252,51 @@ xfs_da3_node_verify(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xfs_failaddr_t
|
||||
xfs_da3_node_header_check(
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_da3_blkinfo *hdr3 = bp->b_addr;
|
||||
|
||||
if (hdr3->hdr.magic != cpu_to_be16(XFS_DA3_NODE_MAGIC))
|
||||
return __this_address;
|
||||
|
||||
if (be64_to_cpu(hdr3->owner) != owner)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xfs_failaddr_t
|
||||
xfs_da3_header_check(
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
struct xfs_da_blkinfo *hdr = bp->b_addr;
|
||||
|
||||
if (!xfs_has_crc(mp))
|
||||
return NULL;
|
||||
|
||||
switch (hdr->magic) {
|
||||
case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC):
|
||||
return xfs_attr3_leaf_header_check(bp, owner);
|
||||
case cpu_to_be16(XFS_DA3_NODE_MAGIC):
|
||||
return xfs_da3_node_header_check(bp, owner);
|
||||
case cpu_to_be16(XFS_DIR3_LEAF1_MAGIC):
|
||||
case cpu_to_be16(XFS_DIR3_LEAFN_MAGIC):
|
||||
return xfs_dir3_leaf_header_check(bp, owner);
|
||||
}
|
||||
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_da3_node_write_verify(
|
||||
struct xfs_buf *bp)
|
||||
@ -486,7 +531,7 @@ xfs_da3_node_create(
|
||||
memset(hdr3, 0, sizeof(struct xfs_da3_node_hdr));
|
||||
ichdr.magic = XFS_DA3_NODE_MAGIC;
|
||||
hdr3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
hdr3->info.owner = cpu_to_be64(args->dp->i_ino);
|
||||
hdr3->info.owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid);
|
||||
} else {
|
||||
ichdr.magic = XFS_DA_NODE_MAGIC;
|
||||
@ -1199,6 +1244,7 @@ xfs_da3_root_join(
|
||||
struct xfs_da3_icnode_hdr oldroothdr;
|
||||
int error;
|
||||
struct xfs_inode *dp = state->args->dp;
|
||||
xfs_failaddr_t fa;
|
||||
|
||||
trace_xfs_da_root_join(state->args);
|
||||
|
||||
@ -1225,6 +1271,13 @@ xfs_da3_root_join(
|
||||
error = xfs_da3_node_read(args->trans, dp, child, &bp, args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
xfs_da_blkinfo_onlychild_validate(bp->b_addr, oldroothdr.level);
|
||||
|
||||
/*
|
||||
@ -1259,6 +1312,7 @@ xfs_da3_node_toosmall(
|
||||
struct xfs_da_blkinfo *info;
|
||||
xfs_dablk_t blkno;
|
||||
struct xfs_buf *bp;
|
||||
xfs_failaddr_t fa;
|
||||
struct xfs_da3_icnode_hdr nodehdr;
|
||||
int count;
|
||||
int forward;
|
||||
@ -1333,6 +1387,13 @@ xfs_da3_node_toosmall(
|
||||
state->args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_node_header_check(bp, state->args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(state->args->trans, bp);
|
||||
xfs_da_mark_sick(state->args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
node = bp->b_addr;
|
||||
xfs_da3_node_hdr_from_disk(dp->i_mount, &thdr, node);
|
||||
@ -1591,6 +1652,7 @@ xfs_da3_node_lookup_int(
|
||||
struct xfs_da_node_entry *btree;
|
||||
struct xfs_da3_icnode_hdr nodehdr;
|
||||
struct xfs_da_args *args;
|
||||
xfs_failaddr_t fa;
|
||||
xfs_dablk_t blkno;
|
||||
xfs_dahash_t hashval;
|
||||
xfs_dahash_t btreehashval;
|
||||
@ -1629,6 +1691,12 @@ xfs_da3_node_lookup_int(
|
||||
|
||||
if (magic == XFS_ATTR_LEAF_MAGIC ||
|
||||
magic == XFS_ATTR3_LEAF_MAGIC) {
|
||||
fa = xfs_attr3_leaf_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
blk->magic = XFS_ATTR_LEAF_MAGIC;
|
||||
blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
|
||||
break;
|
||||
@ -1636,6 +1704,12 @@ xfs_da3_node_lookup_int(
|
||||
|
||||
if (magic == XFS_DIR2_LEAFN_MAGIC ||
|
||||
magic == XFS_DIR3_LEAFN_MAGIC) {
|
||||
fa = xfs_dir3_leaf_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
blk->magic = XFS_DIR2_LEAFN_MAGIC;
|
||||
blk->hashval = xfs_dir2_leaf_lasthash(args->dp,
|
||||
blk->bp, NULL);
|
||||
@ -1648,6 +1722,13 @@ xfs_da3_node_lookup_int(
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
fa = xfs_da3_node_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
blk->magic = XFS_DA_NODE_MAGIC;
|
||||
|
||||
/*
|
||||
@ -1820,6 +1901,7 @@ xfs_da3_blk_link(
|
||||
struct xfs_da_blkinfo *tmp_info;
|
||||
struct xfs_da_args *args;
|
||||
struct xfs_buf *bp;
|
||||
xfs_failaddr_t fa;
|
||||
int before = 0;
|
||||
int error;
|
||||
struct xfs_inode *dp = state->args->dp;
|
||||
@ -1863,6 +1945,13 @@ xfs_da3_blk_link(
|
||||
&bp, args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
tmp_info = bp->b_addr;
|
||||
ASSERT(tmp_info->magic == old_info->magic);
|
||||
@ -1884,6 +1973,13 @@ xfs_da3_blk_link(
|
||||
&bp, args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
tmp_info = bp->b_addr;
|
||||
ASSERT(tmp_info->magic == old_info->magic);
|
||||
@ -1913,6 +2009,7 @@ xfs_da3_blk_unlink(
|
||||
struct xfs_da_blkinfo *tmp_info;
|
||||
struct xfs_da_args *args;
|
||||
struct xfs_buf *bp;
|
||||
xfs_failaddr_t fa;
|
||||
int error;
|
||||
|
||||
/*
|
||||
@ -1943,6 +2040,13 @@ xfs_da3_blk_unlink(
|
||||
&bp, args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
tmp_info = bp->b_addr;
|
||||
ASSERT(tmp_info->magic == save_info->magic);
|
||||
@ -1960,6 +2064,13 @@ xfs_da3_blk_unlink(
|
||||
&bp, args->whichfork);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(args->trans, bp);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
ASSERT(bp != NULL);
|
||||
tmp_info = bp->b_addr;
|
||||
ASSERT(tmp_info->magic == save_info->magic);
|
||||
@ -1996,6 +2107,7 @@ xfs_da3_path_shift(
|
||||
struct xfs_da_node_entry *btree;
|
||||
struct xfs_da3_icnode_hdr nodehdr;
|
||||
struct xfs_buf *bp;
|
||||
xfs_failaddr_t fa;
|
||||
xfs_dablk_t blkno = 0;
|
||||
int level;
|
||||
int error;
|
||||
@ -2074,6 +2186,12 @@ xfs_da3_path_shift(
|
||||
switch (be16_to_cpu(info->magic)) {
|
||||
case XFS_DA_NODE_MAGIC:
|
||||
case XFS_DA3_NODE_MAGIC:
|
||||
fa = xfs_da3_node_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
blk->magic = XFS_DA_NODE_MAGIC;
|
||||
xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr,
|
||||
bp->b_addr);
|
||||
@ -2087,6 +2205,12 @@ xfs_da3_path_shift(
|
||||
break;
|
||||
case XFS_ATTR_LEAF_MAGIC:
|
||||
case XFS_ATTR3_LEAF_MAGIC:
|
||||
fa = xfs_attr3_leaf_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
blk->magic = XFS_ATTR_LEAF_MAGIC;
|
||||
ASSERT(level == path->active-1);
|
||||
blk->index = 0;
|
||||
@ -2094,6 +2218,12 @@ xfs_da3_path_shift(
|
||||
break;
|
||||
case XFS_DIR2_LEAFN_MAGIC:
|
||||
case XFS_DIR3_LEAFN_MAGIC:
|
||||
fa = xfs_dir3_leaf_header_check(blk->bp, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(blk->bp, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
blk->magic = XFS_DIR2_LEAFN_MAGIC;
|
||||
ASSERT(level == path->active-1);
|
||||
blk->index = 0;
|
||||
@ -2290,6 +2420,7 @@ xfs_da3_swap_lastblock(
|
||||
struct xfs_buf *last_buf;
|
||||
struct xfs_buf *sib_buf;
|
||||
struct xfs_buf *par_buf;
|
||||
xfs_failaddr_t fa;
|
||||
xfs_dahash_t dead_hash;
|
||||
xfs_fileoff_t lastoff;
|
||||
xfs_dablk_t dead_blkno;
|
||||
@ -2326,6 +2457,14 @@ xfs_da3_swap_lastblock(
|
||||
error = xfs_da3_node_read(tp, dp, last_blkno, &last_buf, w);
|
||||
if (error)
|
||||
return error;
|
||||
fa = xfs_da3_header_check(last_buf, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(last_buf, fa);
|
||||
xfs_trans_brelse(tp, last_buf);
|
||||
xfs_da_mark_sick(args);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the last block into the dead buffer and log it.
|
||||
*/
|
||||
@ -2364,6 +2503,13 @@ xfs_da3_swap_lastblock(
|
||||
error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w);
|
||||
if (error)
|
||||
goto done;
|
||||
fa = xfs_da3_header_check(sib_buf, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(sib_buf, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
error = -EFSCORRUPTED;
|
||||
goto done;
|
||||
}
|
||||
sib_info = sib_buf->b_addr;
|
||||
if (XFS_IS_CORRUPT(mp,
|
||||
be32_to_cpu(sib_info->forw) != last_blkno ||
|
||||
@ -2385,6 +2531,13 @@ xfs_da3_swap_lastblock(
|
||||
error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w);
|
||||
if (error)
|
||||
goto done;
|
||||
fa = xfs_da3_header_check(sib_buf, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(sib_buf, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
error = -EFSCORRUPTED;
|
||||
goto done;
|
||||
}
|
||||
sib_info = sib_buf->b_addr;
|
||||
if (XFS_IS_CORRUPT(mp,
|
||||
be32_to_cpu(sib_info->back) != last_blkno ||
|
||||
@ -2408,6 +2561,13 @@ xfs_da3_swap_lastblock(
|
||||
error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w);
|
||||
if (error)
|
||||
goto done;
|
||||
fa = xfs_da3_node_header_check(par_buf, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(par_buf, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
error = -EFSCORRUPTED;
|
||||
goto done;
|
||||
}
|
||||
par_node = par_buf->b_addr;
|
||||
xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node);
|
||||
if (XFS_IS_CORRUPT(mp,
|
||||
@ -2457,6 +2617,13 @@ xfs_da3_swap_lastblock(
|
||||
error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w);
|
||||
if (error)
|
||||
goto done;
|
||||
fa = xfs_da3_node_header_check(par_buf, args->owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(par_buf, fa);
|
||||
xfs_da_mark_sick(args);
|
||||
error = -EFSCORRUPTED;
|
||||
goto done;
|
||||
}
|
||||
par_node = par_buf->b_addr;
|
||||
xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node);
|
||||
if (XFS_IS_CORRUPT(mp, par_hdr.level != level)) {
|
||||
|
@ -79,6 +79,7 @@ typedef struct xfs_da_args {
|
||||
int rmtvaluelen2; /* remote attr value length in bytes */
|
||||
uint32_t op_flags; /* operation flags */
|
||||
enum xfs_dacmp cmpresult; /* name compare result for lookups */
|
||||
xfs_ino_t owner; /* inode that owns the dir/attr data */
|
||||
} xfs_da_args_t;
|
||||
|
||||
/*
|
||||
@ -235,6 +236,8 @@ void xfs_da3_node_hdr_from_disk(struct xfs_mount *mp,
|
||||
struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from);
|
||||
void xfs_da3_node_hdr_to_disk(struct xfs_mount *mp,
|
||||
struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from);
|
||||
xfs_failaddr_t xfs_da3_header_check(struct xfs_buf *bp, xfs_ino_t owner);
|
||||
xfs_failaddr_t xfs_da3_node_header_check(struct xfs_buf *bp, xfs_ino_t owner);
|
||||
|
||||
extern struct kmem_cache *xfs_da_state_cache;
|
||||
|
||||
|
@ -250,6 +250,7 @@ xfs_dir_init(
|
||||
args->geo = dp->i_mount->m_dir_geo;
|
||||
args->dp = dp;
|
||||
args->trans = tp;
|
||||
args->owner = dp->i_ino;
|
||||
error = xfs_dir2_sf_create(args, pdp->i_ino);
|
||||
kfree(args);
|
||||
return error;
|
||||
@ -295,6 +296,7 @@ xfs_dir_createname(
|
||||
args->whichfork = XFS_DATA_FORK;
|
||||
args->trans = tp;
|
||||
args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
|
||||
args->owner = dp->i_ino;
|
||||
if (!inum)
|
||||
args->op_flags |= XFS_DA_OP_JUSTCHECK;
|
||||
|
||||
@ -383,6 +385,7 @@ xfs_dir_lookup(
|
||||
args->whichfork = XFS_DATA_FORK;
|
||||
args->trans = tp;
|
||||
args->op_flags = XFS_DA_OP_OKNOENT;
|
||||
args->owner = dp->i_ino;
|
||||
if (ci_name)
|
||||
args->op_flags |= XFS_DA_OP_CILOOKUP;
|
||||
|
||||
@ -456,6 +459,7 @@ xfs_dir_removename(
|
||||
args->total = total;
|
||||
args->whichfork = XFS_DATA_FORK;
|
||||
args->trans = tp;
|
||||
args->owner = dp->i_ino;
|
||||
|
||||
if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
|
||||
rval = xfs_dir2_sf_removename(args);
|
||||
@ -517,6 +521,7 @@ xfs_dir_replace(
|
||||
args->total = total;
|
||||
args->whichfork = XFS_DATA_FORK;
|
||||
args->trans = tp;
|
||||
args->owner = dp->i_ino;
|
||||
|
||||
if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
|
||||
rval = xfs_dir2_sf_replace(args);
|
||||
|
@ -101,6 +101,10 @@ extern struct xfs_dir2_data_free *xfs_dir2_data_freefind(
|
||||
|
||||
extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
|
||||
|
||||
xfs_failaddr_t xfs_dir3_leaf_header_check(struct xfs_buf *bp, xfs_ino_t owner);
|
||||
xfs_failaddr_t xfs_dir3_data_header_check(struct xfs_buf *bp, xfs_ino_t owner);
|
||||
xfs_failaddr_t xfs_dir3_block_header_check(struct xfs_buf *bp, xfs_ino_t owner);
|
||||
|
||||
extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;
|
||||
extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
|
||||
extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
|
||||
|
@ -115,17 +115,20 @@ const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
|
||||
.verify_struct = xfs_dir3_block_verify,
|
||||
};
|
||||
|
||||
static xfs_failaddr_t
|
||||
xfs_failaddr_t
|
||||
xfs_dir3_block_header_check(
|
||||
struct xfs_inode *dp,
|
||||
struct xfs_buf *bp)
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
|
||||
|
||||
if (be64_to_cpu(hdr3->owner) != dp->i_ino)
|
||||
if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
|
||||
return __this_address;
|
||||
|
||||
if (be64_to_cpu(hdr3->owner) != owner)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
@ -136,6 +139,7 @@ int
|
||||
xfs_dir3_block_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
@ -148,7 +152,7 @@ xfs_dir3_block_read(
|
||||
return err;
|
||||
|
||||
/* Check things that we can't do in the verifier. */
|
||||
fa = xfs_dir3_block_header_check(dp, *bpp);
|
||||
fa = xfs_dir3_block_header_check(*bpp, owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
@ -163,12 +167,13 @@ xfs_dir3_block_read(
|
||||
|
||||
static void
|
||||
xfs_dir3_block_init(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_buf *bp,
|
||||
struct xfs_inode *dp)
|
||||
struct xfs_da_args *args,
|
||||
struct xfs_buf *bp)
|
||||
{
|
||||
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
|
||||
struct xfs_trans *tp = args->trans;
|
||||
struct xfs_inode *dp = args->dp;
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
|
||||
|
||||
bp->b_ops = &xfs_dir3_block_buf_ops;
|
||||
xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF);
|
||||
@ -177,7 +182,7 @@ xfs_dir3_block_init(
|
||||
memset(hdr3, 0, sizeof(*hdr3));
|
||||
hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
|
||||
hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
hdr3->owner = cpu_to_be64(dp->i_ino);
|
||||
hdr3->owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
|
||||
return;
|
||||
|
||||
@ -382,7 +387,7 @@ xfs_dir2_block_addname(
|
||||
tp = args->trans;
|
||||
|
||||
/* Read the (one and only) directory block into bp. */
|
||||
error = xfs_dir3_block_read(tp, dp, &bp);
|
||||
error = xfs_dir3_block_read(tp, dp, args->owner, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -697,7 +702,7 @@ xfs_dir2_block_lookup_int(
|
||||
dp = args->dp;
|
||||
tp = args->trans;
|
||||
|
||||
error = xfs_dir3_block_read(tp, dp, &bp);
|
||||
error = xfs_dir3_block_read(tp, dp, args->owner, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -981,7 +986,8 @@ xfs_dir2_leaf_to_block(
|
||||
* Read the data block if we don't already have it, give up if it fails.
|
||||
*/
|
||||
if (!dbp) {
|
||||
error = xfs_dir3_data_read(tp, dp, args->geo->datablk, 0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
args->geo->datablk, 0, &dbp);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -1009,7 +1015,7 @@ xfs_dir2_leaf_to_block(
|
||||
/*
|
||||
* Start converting it to block form.
|
||||
*/
|
||||
xfs_dir3_block_init(mp, tp, dbp, dp);
|
||||
xfs_dir3_block_init(args, dbp);
|
||||
|
||||
needlog = 1;
|
||||
needscan = 0;
|
||||
@ -1129,7 +1135,7 @@ xfs_dir2_sf_to_block(
|
||||
error = xfs_dir3_data_init(args, blkno, &bp);
|
||||
if (error)
|
||||
goto out_free;
|
||||
xfs_dir3_block_init(mp, tp, bp, dp);
|
||||
xfs_dir3_block_init(args, bp);
|
||||
hdr = bp->b_addr;
|
||||
|
||||
/*
|
||||
@ -1169,7 +1175,7 @@ xfs_dir2_sf_to_block(
|
||||
* Create entry for .
|
||||
*/
|
||||
dep = bp->b_addr + offset;
|
||||
dep->inumber = cpu_to_be64(dp->i_ino);
|
||||
dep->inumber = cpu_to_be64(args->owner);
|
||||
dep->namelen = 1;
|
||||
dep->name[0] = '.';
|
||||
xfs_dir2_data_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
|
||||
|
@ -395,17 +395,20 @@ static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
|
||||
.verify_write = xfs_dir3_data_write_verify,
|
||||
};
|
||||
|
||||
static xfs_failaddr_t
|
||||
xfs_failaddr_t
|
||||
xfs_dir3_data_header_check(
|
||||
struct xfs_inode *dp,
|
||||
struct xfs_buf *bp)
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_dir3_data_hdr *hdr3 = bp->b_addr;
|
||||
|
||||
if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino)
|
||||
if (hdr3->hdr.magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC))
|
||||
return __this_address;
|
||||
|
||||
if (be64_to_cpu(hdr3->hdr.owner) != owner)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
@ -416,6 +419,7 @@ int
|
||||
xfs_dir3_data_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t bno,
|
||||
unsigned int flags,
|
||||
struct xfs_buf **bpp)
|
||||
@ -429,7 +433,7 @@ xfs_dir3_data_read(
|
||||
return err;
|
||||
|
||||
/* Check things that we can't do in the verifier. */
|
||||
fa = xfs_dir3_data_header_check(dp, *bpp);
|
||||
fa = xfs_dir3_data_header_check(*bpp, owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
@ -725,7 +729,7 @@ xfs_dir3_data_init(
|
||||
memset(hdr3, 0, sizeof(*hdr3));
|
||||
hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
|
||||
hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
hdr3->owner = cpu_to_be64(dp->i_ino);
|
||||
hdr3->owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid);
|
||||
|
||||
} else
|
||||
|
@ -208,6 +208,29 @@ xfs_dir3_leaf_verify(
|
||||
return xfs_dir3_leaf_check_int(mp, &leafhdr, bp->b_addr, true);
|
||||
}
|
||||
|
||||
xfs_failaddr_t
|
||||
xfs_dir3_leaf_header_check(
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner)
|
||||
{
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
|
||||
if (xfs_has_crc(mp)) {
|
||||
struct xfs_dir3_leaf *hdr3 = bp->b_addr;
|
||||
|
||||
if (hdr3->hdr.info.hdr.magic !=
|
||||
cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) &&
|
||||
hdr3->hdr.info.hdr.magic !=
|
||||
cpu_to_be16(XFS_DIR3_LEAFN_MAGIC))
|
||||
return __this_address;
|
||||
|
||||
if (be64_to_cpu(hdr3->hdr.info.owner) != owner)
|
||||
return __this_address;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_dir3_leaf_read_verify(
|
||||
struct xfs_buf *bp)
|
||||
@ -271,32 +294,60 @@ int
|
||||
xfs_dir3_leaf_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_failaddr_t fa;
|
||||
int err;
|
||||
|
||||
err = xfs_da_read_buf(tp, dp, fbno, 0, bpp, XFS_DATA_FORK,
|
||||
&xfs_dir3_leaf1_buf_ops);
|
||||
if (!err && tp && *bpp)
|
||||
if (err || !(*bpp))
|
||||
return err;
|
||||
|
||||
fa = xfs_dir3_leaf_header_check(*bpp, owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
*bpp = NULL;
|
||||
xfs_dirattr_mark_sick(dp, XFS_DATA_FORK);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (tp)
|
||||
xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAF1_BUF);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xfs_dir3_leafn_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
xfs_failaddr_t fa;
|
||||
int err;
|
||||
|
||||
err = xfs_da_read_buf(tp, dp, fbno, 0, bpp, XFS_DATA_FORK,
|
||||
&xfs_dir3_leafn_buf_ops);
|
||||
if (!err && tp && *bpp)
|
||||
if (err || !(*bpp))
|
||||
return err;
|
||||
|
||||
fa = xfs_dir3_leaf_header_check(*bpp, owner);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
*bpp = NULL;
|
||||
xfs_dirattr_mark_sick(dp, XFS_DATA_FORK);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (tp)
|
||||
xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_LEAFN_BUF);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -304,12 +355,12 @@ xfs_dir3_leafn_read(
|
||||
*/
|
||||
static void
|
||||
xfs_dir3_leaf_init(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_da_args *args,
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner,
|
||||
uint16_t type)
|
||||
{
|
||||
struct xfs_mount *mp = args->dp->i_mount;
|
||||
struct xfs_trans *tp = args->trans;
|
||||
struct xfs_dir2_leaf *leaf = bp->b_addr;
|
||||
|
||||
ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC);
|
||||
@ -323,7 +374,7 @@ xfs_dir3_leaf_init(
|
||||
? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)
|
||||
: cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
|
||||
leaf3->info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
leaf3->info.owner = cpu_to_be64(owner);
|
||||
leaf3->info.owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid);
|
||||
} else {
|
||||
memset(leaf, 0, sizeof(*leaf));
|
||||
@ -356,7 +407,6 @@ xfs_dir3_leaf_get_buf(
|
||||
{
|
||||
struct xfs_inode *dp = args->dp;
|
||||
struct xfs_trans *tp = args->trans;
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_buf *bp;
|
||||
int error;
|
||||
|
||||
@ -369,7 +419,7 @@ xfs_dir3_leaf_get_buf(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
|
||||
xfs_dir3_leaf_init(args, bp, magic);
|
||||
xfs_dir3_leaf_log_header(args, bp);
|
||||
if (magic == XFS_DIR2_LEAF1_MAGIC)
|
||||
xfs_dir3_leaf_log_tail(args, bp);
|
||||
@ -647,7 +697,8 @@ xfs_dir2_leaf_addname(
|
||||
|
||||
trace_xfs_dir2_leaf_addname(args);
|
||||
|
||||
error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, &lbp);
|
||||
error = xfs_dir3_leaf_read(tp, dp, args->owner, args->geo->leafblk,
|
||||
&lbp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -834,9 +885,9 @@ xfs_dir2_leaf_addname(
|
||||
* Already had space in some data block.
|
||||
* Just read that one in.
|
||||
*/
|
||||
error = xfs_dir3_data_read(tp, dp,
|
||||
xfs_dir2_db_to_da(args->geo, use_block),
|
||||
0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, use_block), 0,
|
||||
&dbp);
|
||||
if (error) {
|
||||
xfs_trans_brelse(tp, lbp);
|
||||
return error;
|
||||
@ -1238,7 +1289,8 @@ xfs_dir2_leaf_lookup_int(
|
||||
tp = args->trans;
|
||||
mp = dp->i_mount;
|
||||
|
||||
error = xfs_dir3_leaf_read(tp, dp, args->geo->leafblk, &lbp);
|
||||
error = xfs_dir3_leaf_read(tp, dp, args->owner, args->geo->leafblk,
|
||||
&lbp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -1276,9 +1328,9 @@ xfs_dir2_leaf_lookup_int(
|
||||
if (newdb != curdb) {
|
||||
if (dbp)
|
||||
xfs_trans_brelse(tp, dbp);
|
||||
error = xfs_dir3_data_read(tp, dp,
|
||||
xfs_dir2_db_to_da(args->geo, newdb),
|
||||
0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, newdb), 0,
|
||||
&dbp);
|
||||
if (error) {
|
||||
xfs_trans_brelse(tp, lbp);
|
||||
return error;
|
||||
@ -1318,9 +1370,9 @@ xfs_dir2_leaf_lookup_int(
|
||||
ASSERT(cidb != -1);
|
||||
if (cidb != curdb) {
|
||||
xfs_trans_brelse(tp, dbp);
|
||||
error = xfs_dir3_data_read(tp, dp,
|
||||
xfs_dir2_db_to_da(args->geo, cidb),
|
||||
0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, cidb), 0,
|
||||
&dbp);
|
||||
if (error) {
|
||||
xfs_trans_brelse(tp, lbp);
|
||||
return error;
|
||||
@ -1614,7 +1666,8 @@ xfs_dir2_leaf_trim_data(
|
||||
/*
|
||||
* Read the offending data block. We need its buffer.
|
||||
*/
|
||||
error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(geo, db), 0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(geo, db), 0, &dbp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -1753,7 +1806,8 @@ xfs_dir2_node_to_leaf(
|
||||
/*
|
||||
* Read the freespace block.
|
||||
*/
|
||||
error = xfs_dir2_free_read(tp, dp, args->geo->freeblk, &fbp);
|
||||
error = xfs_dir2_free_read(tp, dp, args->owner, args->geo->freeblk,
|
||||
&fbp);
|
||||
if (error)
|
||||
return error;
|
||||
xfs_dir2_free_hdr_from_disk(mp, &freehdr, fbp->b_addr);
|
||||
|
@ -175,11 +175,11 @@ const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
|
||||
/* Everything ok in the free block header? */
|
||||
static xfs_failaddr_t
|
||||
xfs_dir3_free_header_check(
|
||||
struct xfs_inode *dp,
|
||||
xfs_dablk_t fbno,
|
||||
struct xfs_buf *bp)
|
||||
struct xfs_buf *bp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno)
|
||||
{
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_mount *mp = bp->b_mount;
|
||||
int maxbests = mp->m_dir_geo->free_max_bests;
|
||||
unsigned int firstdb;
|
||||
|
||||
@ -195,7 +195,7 @@ xfs_dir3_free_header_check(
|
||||
return __this_address;
|
||||
if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused))
|
||||
return __this_address;
|
||||
if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino)
|
||||
if (be64_to_cpu(hdr3->hdr.owner) != owner)
|
||||
return __this_address;
|
||||
} else {
|
||||
struct xfs_dir2_free_hdr *hdr = bp->b_addr;
|
||||
@ -214,6 +214,7 @@ static int
|
||||
__xfs_dir3_free_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno,
|
||||
unsigned int flags,
|
||||
struct xfs_buf **bpp)
|
||||
@ -227,7 +228,7 @@ __xfs_dir3_free_read(
|
||||
return err;
|
||||
|
||||
/* Check things that we can't do in the verifier. */
|
||||
fa = xfs_dir3_free_header_check(dp, fbno, *bpp);
|
||||
fa = xfs_dir3_free_header_check(*bpp, owner, fbno);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(*bpp, fa);
|
||||
xfs_trans_brelse(tp, *bpp);
|
||||
@ -299,20 +300,23 @@ int
|
||||
xfs_dir2_free_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
return __xfs_dir3_free_read(tp, dp, fbno, 0, bpp);
|
||||
return __xfs_dir3_free_read(tp, dp, owner, fbno, 0, bpp);
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_dir2_free_try_read(
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_inode *dp,
|
||||
xfs_ino_t owner,
|
||||
xfs_dablk_t fbno,
|
||||
struct xfs_buf **bpp)
|
||||
{
|
||||
return __xfs_dir3_free_read(tp, dp, fbno, XFS_DABUF_MAP_HOLE_OK, bpp);
|
||||
return __xfs_dir3_free_read(tp, dp, owner, fbno, XFS_DABUF_MAP_HOLE_OK,
|
||||
bpp);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -349,7 +353,7 @@ xfs_dir3_free_get_buf(
|
||||
hdr.magic = XFS_DIR3_FREE_MAGIC;
|
||||
|
||||
hdr3->hdr.blkno = cpu_to_be64(xfs_buf_daddr(bp));
|
||||
hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
|
||||
hdr3->hdr.owner = cpu_to_be64(args->owner);
|
||||
uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid);
|
||||
} else
|
||||
hdr.magic = XFS_DIR2_FREE_MAGIC;
|
||||
@ -717,7 +721,7 @@ xfs_dir2_leafn_lookup_for_addname(
|
||||
if (curbp)
|
||||
xfs_trans_brelse(tp, curbp);
|
||||
|
||||
error = xfs_dir2_free_read(tp, dp,
|
||||
error = xfs_dir2_free_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo,
|
||||
newfdb),
|
||||
&curbp);
|
||||
@ -863,7 +867,7 @@ xfs_dir2_leafn_lookup_for_entry(
|
||||
ASSERT(state->extravalid);
|
||||
curbp = state->extrablk.bp;
|
||||
} else {
|
||||
error = xfs_dir3_data_read(tp, dp,
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo,
|
||||
newdb),
|
||||
0, &curbp);
|
||||
@ -1356,8 +1360,8 @@ xfs_dir2_leafn_remove(
|
||||
* read in the free block.
|
||||
*/
|
||||
fdb = xfs_dir2_db_to_fdb(geo, db);
|
||||
error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(geo, fdb),
|
||||
&fbp);
|
||||
error = xfs_dir2_free_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(geo, fdb), &fbp);
|
||||
if (error)
|
||||
return error;
|
||||
free = fbp->b_addr;
|
||||
@ -1562,7 +1566,8 @@ xfs_dir2_leafn_toosmall(
|
||||
/*
|
||||
* Read the sibling leaf block.
|
||||
*/
|
||||
error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, &bp);
|
||||
error = xfs_dir3_leafn_read(state->args->trans, dp,
|
||||
state->args->owner, blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -1715,7 +1720,7 @@ xfs_dir2_node_add_datablk(
|
||||
* that was just allocated.
|
||||
*/
|
||||
fbno = xfs_dir2_db_to_fdb(args->geo, *dbno);
|
||||
error = xfs_dir2_free_try_read(tp, dp,
|
||||
error = xfs_dir2_free_try_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, fbno), &fbp);
|
||||
if (error)
|
||||
return error;
|
||||
@ -1862,7 +1867,7 @@ xfs_dir2_node_find_freeblk(
|
||||
* so this might not succeed. This should be really rare, so
|
||||
* there's no reason to avoid it.
|
||||
*/
|
||||
error = xfs_dir2_free_try_read(tp, dp,
|
||||
error = xfs_dir2_free_try_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, fbno),
|
||||
&fbp);
|
||||
if (error)
|
||||
@ -1948,9 +1953,8 @@ xfs_dir2_node_addname_int(
|
||||
&freehdr, &findex);
|
||||
} else {
|
||||
/* Read the data block in. */
|
||||
error = xfs_dir3_data_read(tp, dp,
|
||||
xfs_dir2_db_to_da(args->geo, dbno),
|
||||
0, &dbp);
|
||||
error = xfs_dir3_data_read(tp, dp, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, dbno), 0, &dbp);
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
@ -2302,7 +2306,7 @@ xfs_dir2_node_trim_free(
|
||||
/*
|
||||
* Read the freespace block.
|
||||
*/
|
||||
error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
|
||||
error = xfs_dir2_free_try_read(tp, dp, args->owner, fo, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
/*
|
||||
|
@ -50,8 +50,8 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
|
||||
|
||||
|
||||
/* xfs_dir2_block.c */
|
||||
extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
struct xfs_buf **bpp);
|
||||
int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_ino_t owner, struct xfs_buf **bpp);
|
||||
extern int xfs_dir2_block_addname(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
|
||||
@ -78,7 +78,8 @@ extern void xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
|
||||
extern xfs_failaddr_t __xfs_dir3_data_check(struct xfs_inode *dp,
|
||||
struct xfs_buf *bp);
|
||||
int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_dablk_t bno, unsigned int flags, struct xfs_buf **bpp);
|
||||
xfs_ino_t owner, xfs_dablk_t bno, unsigned int flags,
|
||||
struct xfs_buf **bpp);
|
||||
int xfs_dir3_data_readahead(struct xfs_inode *dp, xfs_dablk_t bno,
|
||||
unsigned int flags);
|
||||
|
||||
@ -95,9 +96,9 @@ void xfs_dir2_leaf_hdr_from_disk(struct xfs_mount *mp,
|
||||
void xfs_dir2_leaf_hdr_to_disk(struct xfs_mount *mp, struct xfs_dir2_leaf *to,
|
||||
struct xfs_dir3_icleaf_hdr *from);
|
||||
int xfs_dir3_leaf_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
|
||||
struct xfs_buf *dbp);
|
||||
extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
|
||||
@ -154,8 +155,8 @@ extern int xfs_dir2_node_removename(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_node_replace(struct xfs_da_args *args);
|
||||
extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
|
||||
int *rvalp);
|
||||
extern int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp,
|
||||
xfs_ino_t owner, xfs_dablk_t fbno, struct xfs_buf **bpp);
|
||||
|
||||
/* xfs_dir2_sf.c */
|
||||
xfs_ino_t xfs_dir2_sf_get_ino(struct xfs_mount *mp, struct xfs_dir2_sf_hdr *hdr,
|
||||
|
@ -429,6 +429,7 @@ xfs_exchmaps_attr_to_sf(
|
||||
.geo = tp->t_mountp->m_attr_geo,
|
||||
.whichfork = XFS_ATTR_FORK,
|
||||
.trans = tp,
|
||||
.owner = xmi->xmi_ip2->i_ino,
|
||||
};
|
||||
struct xfs_buf *bp;
|
||||
int forkoff;
|
||||
@ -437,7 +438,8 @@ xfs_exchmaps_attr_to_sf(
|
||||
if (!xfs_attr_is_leaf(xmi->xmi_ip2))
|
||||
return 0;
|
||||
|
||||
error = xfs_attr3_leaf_read(tp, xmi->xmi_ip2, 0, &bp);
|
||||
error = xfs_attr3_leaf_read(tp, xmi->xmi_ip2, xmi->xmi_ip2->i_ino, 0,
|
||||
&bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -459,6 +461,7 @@ xfs_exchmaps_dir_to_sf(
|
||||
.geo = tp->t_mountp->m_dir_geo,
|
||||
.whichfork = XFS_DATA_FORK,
|
||||
.trans = tp,
|
||||
.owner = xmi->xmi_ip2->i_ino,
|
||||
};
|
||||
struct xfs_dir2_sf_hdr sfh;
|
||||
struct xfs_buf *bp;
|
||||
@ -473,7 +476,7 @@ xfs_exchmaps_dir_to_sf(
|
||||
if (!isblock)
|
||||
return 0;
|
||||
|
||||
error = xfs_dir3_block_read(tp, xmi->xmi_ip2, &bp);
|
||||
error = xfs_dir3_block_read(tp, xmi->xmi_ip2, xmi->xmi_ip2->i_ino, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -169,6 +169,7 @@ xchk_xattr_listent(
|
||||
.hashval = xfs_da_hashname(name, namelen),
|
||||
.trans = context->tp,
|
||||
.valuelen = valuelen,
|
||||
.owner = context->dp->i_ino,
|
||||
};
|
||||
struct xchk_xattr_buf *ab;
|
||||
struct xchk_xattr *sx;
|
||||
|
@ -320,6 +320,7 @@ xchk_da_btree_block(
|
||||
struct xfs_da3_blkinfo *hdr3;
|
||||
struct xfs_da_args *dargs = &ds->dargs;
|
||||
struct xfs_inode *ip = ds->dargs.dp;
|
||||
xfs_failaddr_t fa;
|
||||
xfs_ino_t owner;
|
||||
int *pmaxrecs;
|
||||
struct xfs_da3_icnode_hdr nodehdr;
|
||||
@ -442,6 +443,12 @@ xchk_da_btree_block(
|
||||
goto out_freebp;
|
||||
}
|
||||
|
||||
fa = xfs_da3_header_check(blk->bp, dargs->owner);
|
||||
if (fa) {
|
||||
xchk_da_set_corrupt(ds, level);
|
||||
goto out_freebp;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've been handed a block that is below the dabtree root, does
|
||||
* its hashval match what the parent block expected to see?
|
||||
@ -494,6 +501,7 @@ xchk_da_btree(
|
||||
ds->dargs.whichfork = whichfork;
|
||||
ds->dargs.trans = sc->tp;
|
||||
ds->dargs.op_flags = XFS_DA_OP_OKNOENT;
|
||||
ds->dargs.owner = sc->ip->i_ino;
|
||||
ds->state = xfs_da_state_alloc(&ds->dargs);
|
||||
ds->sc = sc;
|
||||
ds->private = private;
|
||||
|
@ -196,8 +196,8 @@ xchk_dir_rec(
|
||||
xchk_da_set_corrupt(ds, level);
|
||||
goto out;
|
||||
}
|
||||
error = xfs_dir3_data_read(ds->dargs.trans, dp, rec_bno,
|
||||
XFS_DABUF_MAP_HOLE_OK, &bp);
|
||||
error = xfs_dir3_data_read(ds->dargs.trans, dp, ds->dargs.owner,
|
||||
rec_bno, XFS_DABUF_MAP_HOLE_OK, &bp);
|
||||
if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno,
|
||||
&error))
|
||||
goto out;
|
||||
@ -315,10 +315,11 @@ xchk_directory_data_bestfree(
|
||||
/* dir block format */
|
||||
if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET))
|
||||
xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk);
|
||||
error = xfs_dir3_block_read(sc->tp, sc->ip, &bp);
|
||||
error = xfs_dir3_block_read(sc->tp, sc->ip, sc->ip->i_ino, &bp);
|
||||
} else {
|
||||
/* dir data format */
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip, lblk, 0, &bp);
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip, sc->ip->i_ino, lblk,
|
||||
0, &bp);
|
||||
}
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
|
||||
goto out;
|
||||
@ -470,7 +471,7 @@ xchk_directory_leaf1_bestfree(
|
||||
int error;
|
||||
|
||||
/* Read the free space block. */
|
||||
error = xfs_dir3_leaf_read(sc->tp, sc->ip, lblk, &bp);
|
||||
error = xfs_dir3_leaf_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
|
||||
return error;
|
||||
xchk_buffer_recheck(sc, bp);
|
||||
@ -531,10 +532,9 @@ xchk_directory_leaf1_bestfree(
|
||||
/* Check all the bestfree entries. */
|
||||
for (i = 0; i < bestcount; i++, bestp++) {
|
||||
best = be16_to_cpu(*bestp);
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip,
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
|
||||
xfs_dir2_db_to_da(args->geo, i),
|
||||
XFS_DABUF_MAP_HOLE_OK,
|
||||
&dbp);
|
||||
XFS_DABUF_MAP_HOLE_OK, &dbp);
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
|
||||
&error))
|
||||
break;
|
||||
@ -577,7 +577,7 @@ xchk_directory_free_bestfree(
|
||||
int error;
|
||||
|
||||
/* Read the free space block */
|
||||
error = xfs_dir2_free_read(sc->tp, sc->ip, lblk, &bp);
|
||||
error = xfs_dir2_free_read(sc->tp, sc->ip, sc->ip->i_ino, lblk, &bp);
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error))
|
||||
return error;
|
||||
xchk_buffer_recheck(sc, bp);
|
||||
@ -597,7 +597,7 @@ xchk_directory_free_bestfree(
|
||||
stale++;
|
||||
continue;
|
||||
}
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip,
|
||||
error = xfs_dir3_data_read(sc->tp, sc->ip, args->owner,
|
||||
(freehdr.firstdb + i) * args->geo->fsbcount,
|
||||
0, &dbp);
|
||||
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk,
|
||||
@ -621,10 +621,11 @@ xchk_directory_blocks(
|
||||
{
|
||||
struct xfs_bmbt_irec got;
|
||||
struct xfs_da_args args = {
|
||||
.dp = sc ->ip,
|
||||
.dp = sc->ip,
|
||||
.whichfork = XFS_DATA_FORK,
|
||||
.geo = sc->mp->m_dir_geo,
|
||||
.trans = sc->tp,
|
||||
.owner = sc->ip->i_ino,
|
||||
};
|
||||
struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
|
||||
struct xfs_mount *mp = sc->mp;
|
||||
|
@ -99,7 +99,7 @@ xchk_dir_walk_block(
|
||||
unsigned int off, next_off, end;
|
||||
int error;
|
||||
|
||||
error = xfs_dir3_block_read(sc->tp, dp, &bp);
|
||||
error = xfs_dir3_block_read(sc->tp, dp, dp->i_ino, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -175,7 +175,7 @@ xchk_read_leaf_dir_buf(
|
||||
if (new_off > *curoff)
|
||||
*curoff = new_off;
|
||||
|
||||
return xfs_dir3_data_read(tp, dp, map.br_startoff, 0, bpp);
|
||||
return xfs_dir3_data_read(tp, dp, dp->i_ino, map.br_startoff, 0, bpp);
|
||||
}
|
||||
|
||||
/* Call a function for every entry in a leaf directory. */
|
||||
@ -273,6 +273,7 @@ xchk_dir_walk(
|
||||
.dp = dp,
|
||||
.geo = dp->i_mount->m_dir_geo,
|
||||
.trans = sc->tp,
|
||||
.owner = dp->i_ino,
|
||||
};
|
||||
bool isblock;
|
||||
int error;
|
||||
@ -324,6 +325,7 @@ xchk_dir_lookup(
|
||||
.hashval = xfs_dir2_hashname(dp->i_mount, name),
|
||||
.whichfork = XFS_DATA_FORK,
|
||||
.op_flags = XFS_DA_OP_OKNOENT,
|
||||
.owner = dp->i_ino,
|
||||
};
|
||||
bool isblock, isleaf;
|
||||
int error;
|
||||
|
@ -540,6 +540,7 @@ xfs_attri_recover_work(
|
||||
args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
|
||||
args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
|
||||
XFS_DA_OP_LOGGED;
|
||||
args->owner = args->dp->i_ino;
|
||||
|
||||
ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
|
||||
|
||||
|
@ -214,6 +214,7 @@ xfs_attr_node_list_lookup(
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
struct xfs_trans *tp = context->tp;
|
||||
struct xfs_buf *bp;
|
||||
xfs_failaddr_t fa;
|
||||
int i;
|
||||
int error = 0;
|
||||
unsigned int expected_level = 0;
|
||||
@ -238,6 +239,10 @@ xfs_attr_node_list_lookup(
|
||||
goto out_corruptbuf;
|
||||
}
|
||||
|
||||
fa = xfs_da3_node_header_check(bp, dp->i_ino);
|
||||
if (fa)
|
||||
goto out_corruptbuf;
|
||||
|
||||
xfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
|
||||
|
||||
/* Tree taller than we can handle; bail out! */
|
||||
@ -273,6 +278,12 @@ xfs_attr_node_list_lookup(
|
||||
}
|
||||
}
|
||||
|
||||
fa = xfs_attr3_leaf_header_check(bp, dp->i_ino);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
goto out_releasebuf;
|
||||
}
|
||||
|
||||
if (expected_level != 0)
|
||||
goto out_corruptbuf;
|
||||
|
||||
@ -281,6 +292,7 @@ xfs_attr_node_list_lookup(
|
||||
|
||||
out_corruptbuf:
|
||||
xfs_buf_mark_corrupt(bp);
|
||||
out_releasebuf:
|
||||
xfs_trans_brelse(tp, bp);
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
return -EFSCORRUPTED;
|
||||
@ -297,6 +309,7 @@ xfs_attr_node_list(
|
||||
struct xfs_buf *bp;
|
||||
struct xfs_inode *dp = context->dp;
|
||||
struct xfs_mount *mp = dp->i_mount;
|
||||
xfs_failaddr_t fa;
|
||||
int error = 0;
|
||||
|
||||
trace_xfs_attr_node_list(context);
|
||||
@ -310,46 +323,60 @@ xfs_attr_node_list(
|
||||
*/
|
||||
bp = NULL;
|
||||
if (cursor->blkno > 0) {
|
||||
struct xfs_attr_leaf_entry *entries;
|
||||
|
||||
error = xfs_da3_node_read(context->tp, dp, cursor->blkno, &bp,
|
||||
XFS_ATTR_FORK);
|
||||
if (xfs_metadata_is_sick(error))
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
if ((error != 0) && (error != -EFSCORRUPTED))
|
||||
if (error != 0 && error != -EFSCORRUPTED)
|
||||
return error;
|
||||
if (bp) {
|
||||
struct xfs_attr_leaf_entry *entries;
|
||||
if (!bp)
|
||||
goto need_lookup;
|
||||
|
||||
node = bp->b_addr;
|
||||
switch (be16_to_cpu(node->hdr.info.magic)) {
|
||||
case XFS_DA_NODE_MAGIC:
|
||||
case XFS_DA3_NODE_MAGIC:
|
||||
node = bp->b_addr;
|
||||
switch (be16_to_cpu(node->hdr.info.magic)) {
|
||||
case XFS_DA_NODE_MAGIC:
|
||||
case XFS_DA3_NODE_MAGIC:
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
fa = xfs_da3_node_header_check(bp, dp->i_ino);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
}
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
break;
|
||||
case XFS_ATTR_LEAF_MAGIC:
|
||||
case XFS_ATTR3_LEAF_MAGIC:
|
||||
leaf = bp->b_addr;
|
||||
fa = xfs_attr3_leaf_header_check(bp, dp->i_ino);
|
||||
if (fa) {
|
||||
__xfs_buf_mark_corrupt(bp, fa);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
|
||||
bp = NULL;
|
||||
break;
|
||||
}
|
||||
xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
|
||||
&leafhdr, leaf);
|
||||
entries = xfs_attr3_leaf_entryp(leaf);
|
||||
if (cursor->hashval > be32_to_cpu(
|
||||
entries[leafhdr.count - 1].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
break;
|
||||
case XFS_ATTR_LEAF_MAGIC:
|
||||
case XFS_ATTR3_LEAF_MAGIC:
|
||||
leaf = bp->b_addr;
|
||||
xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
|
||||
&leafhdr, leaf);
|
||||
entries = xfs_attr3_leaf_entryp(leaf);
|
||||
if (cursor->hashval > be32_to_cpu(
|
||||
entries[leafhdr.count - 1].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
} else if (cursor->hashval <= be32_to_cpu(
|
||||
entries[0].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} else if (cursor->hashval <= be32_to_cpu(
|
||||
entries[0].hashval)) {
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
trace_xfs_attr_list_wrong_blk(context);
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
bp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,6 +386,7 @@ xfs_attr_node_list(
|
||||
* Note that start of node block is same as start of leaf block.
|
||||
*/
|
||||
if (bp == NULL) {
|
||||
need_lookup:
|
||||
error = xfs_attr_node_list_lookup(context, cursor, &bp);
|
||||
if (error || !bp)
|
||||
return error;
|
||||
@ -380,8 +408,8 @@ xfs_attr_node_list(
|
||||
break;
|
||||
cursor->blkno = leafhdr.forw;
|
||||
xfs_trans_brelse(context->tp, bp);
|
||||
error = xfs_attr3_leaf_read(context->tp, dp, cursor->blkno,
|
||||
&bp);
|
||||
error = xfs_attr3_leaf_read(context->tp, dp, dp->i_ino,
|
||||
cursor->blkno, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -501,7 +529,8 @@ xfs_attr_leaf_list(
|
||||
trace_xfs_attr_leaf_list(context);
|
||||
|
||||
context->cursor.blkno = 0;
|
||||
error = xfs_attr3_leaf_read(context->tp, context->dp, 0, &bp);
|
||||
error = xfs_attr3_leaf_read(context->tp, context->dp,
|
||||
context->dp->i_ino, 0, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -157,7 +157,7 @@ xfs_dir2_block_getdents(
|
||||
if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk)
|
||||
return 0;
|
||||
|
||||
error = xfs_dir3_block_read(args->trans, dp, &bp);
|
||||
error = xfs_dir3_block_read(args->trans, dp, args->owner, &bp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -282,7 +282,8 @@ xfs_dir2_leaf_readbuf(
|
||||
new_off = xfs_dir2_da_to_byte(geo, map.br_startoff);
|
||||
if (new_off > *cur_off)
|
||||
*cur_off = new_off;
|
||||
error = xfs_dir3_data_read(args->trans, dp, map.br_startoff, 0, &bp);
|
||||
error = xfs_dir3_data_read(args->trans, dp, args->owner,
|
||||
map.br_startoff, 0, &bp);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
@ -532,6 +533,7 @@ xfs_readdir(
|
||||
args.dp = dp;
|
||||
args.geo = dp->i_mount->m_dir_geo;
|
||||
args.trans = tp;
|
||||
args.owner = dp->i_ino;
|
||||
|
||||
if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
|
||||
return xfs_dir2_sf_getdents(&args, ctx);
|
||||
|
@ -1931,6 +1931,7 @@ DECLARE_EVENT_CLASS(xfs_da_class,
|
||||
__field(xfs_dahash_t, hashval)
|
||||
__field(xfs_ino_t, inumber)
|
||||
__field(uint32_t, op_flags)
|
||||
__field(xfs_ino_t, owner)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->dev = VFS_I(args->dp)->i_sb->s_dev;
|
||||
@ -1941,9 +1942,10 @@ DECLARE_EVENT_CLASS(xfs_da_class,
|
||||
__entry->hashval = args->hashval;
|
||||
__entry->inumber = args->inumber;
|
||||
__entry->op_flags = args->op_flags;
|
||||
__entry->owner = args->owner;
|
||||
),
|
||||
TP_printk("dev %d:%d ino 0x%llx name %.*s namelen %d hashval 0x%x "
|
||||
"inumber 0x%llx op_flags %s",
|
||||
"inumber 0x%llx op_flags %s owner 0x%llx",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->ino,
|
||||
__entry->namelen,
|
||||
@ -1951,7 +1953,8 @@ DECLARE_EVENT_CLASS(xfs_da_class,
|
||||
__entry->namelen,
|
||||
__entry->hashval,
|
||||
__entry->inumber,
|
||||
__print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS))
|
||||
__print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS),
|
||||
__entry->owner)
|
||||
)
|
||||
|
||||
#define DEFINE_DIR2_EVENT(name) \
|
||||
|
Loading…
Reference in New Issue
Block a user