xfs: add buffer types to directory and attribute buffers

Add buffer types to the buffer log items so that log recovery can
validate the buffers and calculate CRCs correctly after the buffers
are recovered.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
Dave Chinner 2013-04-03 16:11:29 +11:00 коммит произвёл Ben Myers
Родитель d2e448d5fd
Коммит d75afeb3d3
13 изменённых файлов: 331 добавлений и 98 удалений

Просмотреть файл

@ -271,8 +271,13 @@ xfs_attr3_leaf_read(
xfs_daddr_t mappedbno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, int err;
err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops);
if (!err && tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_ATTR_LEAF_BUF);
return err;
} }
/*======================================================================== /*========================================================================
@ -1078,6 +1083,7 @@ xfs_attr3_leaf_to_node(
goto out; goto out;
/* copy leaf to new buffer, update identifiers */ /* copy leaf to new buffer, update identifiers */
xfs_trans_buf_set_type(args->trans, bp2, XFS_BLF_ATTR_LEAF_BUF);
bp2->b_ops = bp1->b_ops; bp2->b_ops = bp1->b_ops;
memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp)); memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp));
if (xfs_sb_version_hascrc(&mp->m_sb)) { if (xfs_sb_version_hascrc(&mp->m_sb)) {
@ -1140,6 +1146,7 @@ xfs_attr3_leaf_create(
if (error) if (error)
return error; return error;
bp->b_ops = &xfs_attr3_leaf_buf_ops; bp->b_ops = &xfs_attr3_leaf_buf_ops;
xfs_trans_buf_set_type(args->trans, bp, XFS_BLF_ATTR_LEAF_BUF);
leaf = bp->b_addr; leaf = bp->b_addr;
memset(leaf, 0, XFS_LBSIZE(mp)); memset(leaf, 0, XFS_LBSIZE(mp));

Просмотреть файл

@ -37,6 +37,8 @@ struct xfs_attr3_rmt_hdr {
((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
sizeof(struct xfs_attr3_rmt_hdr) : 0)) sizeof(struct xfs_attr3_rmt_hdr) : 0))
extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
int xfs_attr_rmtval_get(struct xfs_da_args *args); int xfs_attr_rmtval_get(struct xfs_da_args *args);
int xfs_attr_rmtval_set(struct xfs_da_args *args); int xfs_attr_rmtval_set(struct xfs_da_args *args);
int xfs_attr_rmtval_remove(struct xfs_da_args *args); int xfs_attr_rmtval_remove(struct xfs_da_args *args);

Просмотреть файл

@ -50,6 +50,14 @@ extern kmem_zone_t *xfs_buf_item_zone;
#define XFS_BLF_AGI_BUF (1<<8) #define XFS_BLF_AGI_BUF (1<<8)
#define XFS_BLF_DINO_BUF (1<<9) #define XFS_BLF_DINO_BUF (1<<9)
#define XFS_BLF_SYMLINK_BUF (1<<10) #define XFS_BLF_SYMLINK_BUF (1<<10)
#define XFS_BLF_DIR_BLOCK_BUF (1<<11)
#define XFS_BLF_DIR_DATA_BUF (1<<12)
#define XFS_BLF_DIR_FREE_BUF (1<<13)
#define XFS_BLF_DIR_LEAF1_BUF (1<<14)
#define XFS_BLF_DIR_LEAFN_BUF (1<<15)
#define XFS_BLF_DA_NODE_BUF (1<<16)
#define XFS_BLF_ATTR_LEAF_BUF (1<<17)
#define XFS_BLF_ATTR_RMT_BUF (1<<18)
#define XFS_BLF_TYPE_MASK \ #define XFS_BLF_TYPE_MASK \
(XFS_BLF_UDQUOT_BUF | \ (XFS_BLF_UDQUOT_BUF | \
@ -60,7 +68,15 @@ extern kmem_zone_t *xfs_buf_item_zone;
XFS_BLF_AGFL_BUF | \ XFS_BLF_AGFL_BUF | \
XFS_BLF_AGI_BUF | \ XFS_BLF_AGI_BUF | \
XFS_BLF_DINO_BUF | \ XFS_BLF_DINO_BUF | \
XFS_BLF_SYMLINK_BUF) XFS_BLF_SYMLINK_BUF | \
XFS_BLF_DIR_BLOCK_BUF | \
XFS_BLF_DIR_DATA_BUF | \
XFS_BLF_DIR_FREE_BUF | \
XFS_BLF_DIR_LEAF1_BUF | \
XFS_BLF_DIR_LEAFN_BUF | \
XFS_BLF_DA_NODE_BUF | \
XFS_BLF_ATTR_LEAF_BUF | \
XFS_BLF_ATTR_RMT_BUF)
#define XFS_BLF_CHUNK 128 #define XFS_BLF_CHUNK 128
#define XFS_BLF_SHIFT 7 #define XFS_BLF_SHIFT 7

Просмотреть файл

@ -292,7 +292,6 @@ const struct xfs_buf_ops xfs_da3_node_buf_ops = {
.verify_write = xfs_da3_node_write_verify, .verify_write = xfs_da3_node_write_verify,
}; };
int int
xfs_da3_node_read( xfs_da3_node_read(
struct xfs_trans *tp, struct xfs_trans *tp,
@ -302,8 +301,35 @@ xfs_da3_node_read(
struct xfs_buf **bpp, struct xfs_buf **bpp,
int which_fork) int which_fork)
{ {
return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, int err;
err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
which_fork, &xfs_da3_node_buf_ops); which_fork, &xfs_da3_node_buf_ops);
if (!err && tp) {
struct xfs_da_blkinfo *info = (*bpp)->b_addr;
int type;
switch (be16_to_cpu(info->magic)) {
case XFS_DA3_NODE_MAGIC:
case XFS_DA_NODE_MAGIC:
type = XFS_BLF_DA_NODE_BUF;
break;
case XFS_ATTR_LEAF_MAGIC:
case XFS_ATTR3_LEAF_MAGIC:
type = XFS_BLF_ATTR_LEAF_BUF;
break;
case XFS_DIR2_LEAFN_MAGIC:
case XFS_DIR3_LEAFN_MAGIC:
type = XFS_BLF_DIR_LEAFN_BUF;
break;
default:
type = 0;
ASSERT(0);
break;
}
xfs_trans_buf_set_type(tp, *bpp, type);
}
return err;
} }
/*======================================================================== /*========================================================================
@ -334,6 +360,8 @@ xfs_da3_node_create(
error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork); error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
if (error) if (error)
return(error); return(error);
bp->b_ops = &xfs_da3_node_buf_ops;
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
node = bp->b_addr; node = bp->b_addr;
if (xfs_sb_version_hascrc(&mp->m_sb)) { if (xfs_sb_version_hascrc(&mp->m_sb)) {
@ -352,7 +380,6 @@ xfs_da3_node_create(
xfs_trans_log_buf(tp, bp, xfs_trans_log_buf(tp, bp,
XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
bp->b_ops = &xfs_da3_node_buf_ops;
*bpp = bp; *bpp = bp;
return(0); return(0);
} }
@ -565,6 +592,12 @@ xfs_da3_root_split(
btree = xfs_da3_node_tree_p(oldroot); btree = xfs_da3_node_tree_p(oldroot);
size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot); size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
level = nodehdr.level; level = nodehdr.level;
/*
* we are about to copy oldroot to bp, so set up the type
* of bp while we know exactly what it will be.
*/
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
} else { } else {
struct xfs_dir3_icleaf_hdr leafhdr; struct xfs_dir3_icleaf_hdr leafhdr;
struct xfs_dir2_leaf_entry *ents; struct xfs_dir2_leaf_entry *ents;
@ -577,6 +610,12 @@ xfs_da3_root_split(
leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
size = (int)((char *)&ents[leafhdr.count] - (char *)leaf); size = (int)((char *)&ents[leafhdr.count] - (char *)leaf);
level = 0; level = 0;
/*
* we are about to copy oldroot to bp, so set up the type
* of bp while we know exactly what it will be.
*/
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
} }
/* /*
@ -1092,6 +1131,7 @@ xfs_da3_root_join(
*/ */
memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize); memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize);
root_blk->bp->b_ops = bp->b_ops; root_blk->bp->b_ops = bp->b_ops;
xfs_trans_buf_copy_type(root_blk->bp, bp);
if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) { if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr; struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
da3->blkno = cpu_to_be64(root_blk->bp->b_bn); da3->blkno = cpu_to_be64(root_blk->bp->b_bn);

Просмотреть файл

@ -301,6 +301,8 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno, xfs_dablk_t bno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp, int which_fork); struct xfs_buf **bpp, int which_fork);
extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
/* /*
* Utility routines. * Utility routines.
*/ */

Просмотреть файл

@ -132,20 +132,26 @@ xfs_dir3_block_read(
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
struct xfs_mount *mp = dp->i_mount; struct xfs_mount *mp = dp->i_mount;
int err;
return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp, err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
XFS_DATA_FORK, &xfs_dir3_block_buf_ops); XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
if (!err && tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_BLOCK_BUF);
return err;
} }
static void static void
xfs_dir3_block_init( xfs_dir3_block_init(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_buf *bp, struct xfs_buf *bp,
struct xfs_inode *dp) struct xfs_inode *dp)
{ {
struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
bp->b_ops = &xfs_dir3_block_buf_ops; bp->b_ops = &xfs_dir3_block_buf_ops;
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_BLOCK_BUF);
if (xfs_sb_version_hascrc(&mp->m_sb)) { if (xfs_sb_version_hascrc(&mp->m_sb)) {
memset(hdr3, 0, sizeof(*hdr3)); memset(hdr3, 0, sizeof(*hdr3));
@ -1080,7 +1086,7 @@ xfs_dir2_leaf_to_block(
/* /*
* Start converting it to block form. * Start converting it to block form.
*/ */
xfs_dir3_block_init(mp, dbp, dp); xfs_dir3_block_init(mp, tp, dbp, dp);
needlog = 1; needlog = 1;
needscan = 0; needscan = 0;
@ -1209,7 +1215,7 @@ xfs_dir2_sf_to_block(
kmem_free(sfp); kmem_free(sfp);
return error; return error;
} }
xfs_dir3_block_init(mp, bp, dp); xfs_dir3_block_init(mp, tp, bp, dp);
hdr = bp->b_addr; hdr = bp->b_addr;
/* /*

Просмотреть файл

@ -301,8 +301,13 @@ xfs_dir3_data_read(
xfs_daddr_t mapped_bno, xfs_daddr_t mapped_bno,
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, int err;
err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
XFS_DATA_FORK, &xfs_dir3_data_buf_ops); XFS_DATA_FORK, &xfs_dir3_data_buf_ops);
if (!err && tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_DATA_BUF);
return err;
} }
int int
@ -571,6 +576,7 @@ xfs_dir3_data_init(
if (error) if (error)
return error; return error;
bp->b_ops = &xfs_dir3_data_buf_ops; bp->b_ops = &xfs_dir3_data_buf_ops;
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_DATA_BUF);
/* /*
* Initialize the header. * Initialize the header.

Просмотреть файл

@ -279,7 +279,7 @@ xfs_dir3_leafn_write_verify(
__write_verify(bp, XFS_DIR2_LEAFN_MAGIC); __write_verify(bp, XFS_DIR2_LEAFN_MAGIC);
} }
static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
.verify_read = xfs_dir3_leaf1_read_verify, .verify_read = xfs_dir3_leaf1_read_verify,
.verify_write = xfs_dir3_leaf1_write_verify, .verify_write = xfs_dir3_leaf1_write_verify,
}; };
@ -297,8 +297,13 @@ xfs_dir3_leaf_read(
xfs_daddr_t mappedbno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, int err;
err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops);
if (!err && tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAF1_BUF);
return err;
} }
int int
@ -309,8 +314,13 @@ xfs_dir3_leafn_read(
xfs_daddr_t mappedbno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, int err;
err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops);
if (!err && tp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAFN_BUF);
return err;
} }
/* /*
@ -319,6 +329,7 @@ xfs_dir3_leafn_read(
static void static void
xfs_dir3_leaf_init( xfs_dir3_leaf_init(
struct xfs_mount *mp, struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_buf *bp, struct xfs_buf *bp,
xfs_ino_t owner, xfs_ino_t owner,
__uint16_t type) __uint16_t type)
@ -353,8 +364,11 @@ xfs_dir3_leaf_init(
ltp = xfs_dir2_leaf_tail_p(mp, leaf); ltp = xfs_dir2_leaf_tail_p(mp, leaf);
ltp->bestcount = 0; ltp->bestcount = 0;
bp->b_ops = &xfs_dir3_leaf1_buf_ops; bp->b_ops = &xfs_dir3_leaf1_buf_ops;
} else xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAF1_BUF);
} else {
bp->b_ops = &xfs_dir3_leafn_buf_ops; bp->b_ops = &xfs_dir3_leafn_buf_ops;
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
}
} }
int int
@ -379,7 +393,7 @@ xfs_dir3_leaf_get_buf(
if (error) if (error)
return error; return error;
xfs_dir3_leaf_init(mp, bp, dp->i_ino, magic); xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
xfs_dir3_leaf_log_header(tp, bp); xfs_dir3_leaf_log_header(tp, bp);
if (magic == XFS_DIR2_LEAF1_MAGIC) if (magic == XFS_DIR2_LEAF1_MAGIC)
xfs_dir3_leaf_log_tail(tp, bp); xfs_dir3_leaf_log_tail(tp, bp);
@ -474,6 +488,7 @@ xfs_dir2_block_to_leaf(
* Fix up the block header, make it a data block. * Fix up the block header, make it a data block.
*/ */
dbp->b_ops = &xfs_dir3_data_buf_ops; dbp->b_ops = &xfs_dir3_data_buf_ops;
xfs_trans_buf_set_type(tp, dbp, XFS_BLF_DIR_DATA_BUF);
if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
else else
@ -2182,6 +2197,7 @@ xfs_dir2_node_to_leaf(
xfs_dir3_leaf_compact(args, &leafhdr, lbp); xfs_dir3_leaf_compact(args, &leafhdr, lbp);
lbp->b_ops = &xfs_dir3_leaf1_buf_ops; lbp->b_ops = &xfs_dir3_leaf1_buf_ops;
xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAF1_BUF);
leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC) leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC)
? XFS_DIR2_LEAF1_MAGIC ? XFS_DIR2_LEAF1_MAGIC
: XFS_DIR3_LEAF1_MAGIC; : XFS_DIR3_LEAF1_MAGIC;

Просмотреть файл

@ -147,7 +147,7 @@ xfs_dir3_free_write_verify(
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF); xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF);
} }
static const struct xfs_buf_ops xfs_dir3_free_buf_ops = { const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
.verify_read = xfs_dir3_free_read_verify, .verify_read = xfs_dir3_free_read_verify,
.verify_write = xfs_dir3_free_write_verify, .verify_write = xfs_dir3_free_write_verify,
}; };
@ -161,8 +161,15 @@ __xfs_dir3_free_read(
xfs_daddr_t mappedbno, xfs_daddr_t mappedbno,
struct xfs_buf **bpp) struct xfs_buf **bpp)
{ {
return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, int err;
err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
XFS_DATA_FORK, &xfs_dir3_free_buf_ops); XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
/* try read returns without an error or *bpp if it lands in a hole */
if (!err && tp && *bpp)
xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_FREE_BUF);
return err;
} }
int int
@ -249,6 +256,7 @@ xfs_dir3_free_get_buf(
if (error) if (error)
return error; return error;
xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_FREE_BUF);
bp->b_ops = &xfs_dir3_free_buf_ops; bp->b_ops = &xfs_dir3_free_buf_ops;
/* /*
@ -396,6 +404,7 @@ xfs_dir2_leaf_to_node(
else else
leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
lbp->b_ops = &xfs_dir3_leafn_buf_ops; lbp->b_ops = &xfs_dir3_leafn_buf_ops;
xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAFN_BUF);
xfs_dir3_leaf_log_header(tp, lbp); xfs_dir3_leaf_log_header(tp, lbp);
xfs_dir3_leaf_check(mp, lbp); xfs_dir3_leaf_check(mp, lbp);
return 0; return 0;
@ -811,6 +820,7 @@ xfs_dir2_leafn_lookup_for_entry(
(char *)curbp->b_addr); (char *)curbp->b_addr);
state->extrablk.magic = XFS_DIR2_DATA_MAGIC; state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
curbp->b_ops = &xfs_dir3_data_buf_ops; curbp->b_ops = &xfs_dir3_data_buf_ops;
xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
if (cmp == XFS_CMP_EXACT) if (cmp == XFS_CMP_EXACT)
return XFS_ERROR(EEXIST); return XFS_ERROR(EEXIST);
} }
@ -825,6 +835,7 @@ xfs_dir2_leafn_lookup_for_entry(
state->extrablk.blkno = curdb; state->extrablk.blkno = curdb;
state->extrablk.magic = XFS_DIR2_DATA_MAGIC; state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
curbp->b_ops = &xfs_dir3_data_buf_ops; curbp->b_ops = &xfs_dir3_data_buf_ops;
xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
} else { } else {
/* If the curbp is not the CI match block, drop it */ /* If the curbp is not the CI match block, drop it */
if (state->extrablk.bp != curbp) if (state->extrablk.bp != curbp)

Просмотреть файл

@ -49,6 +49,7 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
#endif #endif
extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;
extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
@ -77,6 +78,7 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
/* xfs_dir2_leaf.c */ /* xfs_dir2_leaf.c */
extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,

Просмотреть файл

@ -45,7 +45,14 @@
#include "xfs_cksum.h" #include "xfs_cksum.h"
#include "xfs_trace.h" #include "xfs_trace.h"
#include "xfs_icache.h" #include "xfs_icache.h"
/* Need all the magic numbers and buffer ops structures from these headers */
#include "xfs_symlink.h" #include "xfs_symlink.h"
#include "xfs_da_btree.h"
#include "xfs_dir2_format.h"
#include "xfs_dir2_priv.h"
#include "xfs_attr_leaf.h"
#include "xfs_attr_remote.h"
STATIC int STATIC int
xlog_find_zeroed( xlog_find_zeroed(
@ -1859,6 +1866,185 @@ xlog_recover_do_inode_buffer(
return 0; return 0;
} }
/*
* Validate the recovered buffer is of the correct type and attach the
* appropriate buffer operations to them for writeback. Magic numbers are in a
* few places:
* the first 16 bits of the buffer (inode buffer, dquot buffer),
* the first 32 bits of the buffer (most blocks),
* inside a struct xfs_da_blkinfo at the start of the buffer.
*/
static void
xlog_recovery_validate_buf_type(
struct xfs_mount *mp,
struct xfs_buf *bp,
xfs_buf_log_format_t *buf_f)
{
struct xfs_da_blkinfo *info = bp->b_addr;
__uint32_t magic32;
__uint16_t magic16;
__uint16_t magicda;
magic32 = be32_to_cpu(*(__be32 *)bp->b_addr);
magic16 = be16_to_cpu(*(__be16*)bp->b_addr);
magicda = be16_to_cpu(info->magic);
switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) {
case XFS_BLF_BTREE_BUF:
switch (magic32) {
case XFS_ABTB_CRC_MAGIC:
case XFS_ABTC_CRC_MAGIC:
case XFS_ABTB_MAGIC:
case XFS_ABTC_MAGIC:
bp->b_ops = &xfs_allocbt_buf_ops;
break;
case XFS_IBT_CRC_MAGIC:
case XFS_IBT_MAGIC:
bp->b_ops = &xfs_inobt_buf_ops;
break;
case XFS_BMAP_CRC_MAGIC:
case XFS_BMAP_MAGIC:
bp->b_ops = &xfs_bmbt_buf_ops;
break;
default:
xfs_warn(mp, "Bad btree block magic!");
ASSERT(0);
break;
}
break;
case XFS_BLF_AGF_BUF:
if (magic32 != XFS_AGF_MAGIC) {
xfs_warn(mp, "Bad AGF block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agf_buf_ops;
break;
case XFS_BLF_AGFL_BUF:
if (!xfs_sb_version_hascrc(&mp->m_sb))
break;
if (magic32 != XFS_AGFL_MAGIC) {
xfs_warn(mp, "Bad AGFL block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agfl_buf_ops;
break;
case XFS_BLF_AGI_BUF:
if (magic32 != XFS_AGI_MAGIC) {
xfs_warn(mp, "Bad AGI block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agi_buf_ops;
break;
case XFS_BLF_UDQUOT_BUF:
case XFS_BLF_PDQUOT_BUF:
case XFS_BLF_GDQUOT_BUF:
if (magic16 != XFS_DQUOT_MAGIC) {
xfs_warn(mp, "Bad DQUOT block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dquot_buf_ops;
break;
case XFS_BLF_DINO_BUF:
/*
* we get here with inode allocation buffers, not buffers that
* track unlinked list changes.
*/
if (magic16 != XFS_DINODE_MAGIC) {
xfs_warn(mp, "Bad INODE block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_inode_buf_ops;
break;
case XFS_BLF_SYMLINK_BUF:
if (magic32 != XFS_SYMLINK_MAGIC) {
xfs_warn(mp, "Bad symlink block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_symlink_buf_ops;
break;
case XFS_BLF_DIR_BLOCK_BUF:
if (magic32 != XFS_DIR2_BLOCK_MAGIC &&
magic32 != XFS_DIR3_BLOCK_MAGIC) {
xfs_warn(mp, "Bad dir block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dir3_block_buf_ops;
break;
case XFS_BLF_DIR_DATA_BUF:
if (magic32 != XFS_DIR2_DATA_MAGIC &&
magic32 != XFS_DIR3_DATA_MAGIC) {
xfs_warn(mp, "Bad dir data magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dir3_data_buf_ops;
break;
case XFS_BLF_DIR_FREE_BUF:
if (magic32 != XFS_DIR2_FREE_MAGIC &&
magic32 != XFS_DIR3_FREE_MAGIC) {
xfs_warn(mp, "Bad dir3 free magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dir3_free_buf_ops;
break;
case XFS_BLF_DIR_LEAF1_BUF:
if (magicda != XFS_DIR2_LEAF1_MAGIC &&
magicda != XFS_DIR3_LEAF1_MAGIC) {
xfs_warn(mp, "Bad dir leaf1 magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dir3_leaf1_buf_ops;
break;
case XFS_BLF_DIR_LEAFN_BUF:
if (magicda != XFS_DIR2_LEAFN_MAGIC &&
magicda != XFS_DIR3_LEAFN_MAGIC) {
xfs_warn(mp, "Bad dir leafn magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dir3_leafn_buf_ops;
break;
case XFS_BLF_DA_NODE_BUF:
if (magicda != XFS_DA_NODE_MAGIC &&
magicda != XFS_DA3_NODE_MAGIC) {
xfs_warn(mp, "Bad da node magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_da3_node_buf_ops;
break;
case XFS_BLF_ATTR_LEAF_BUF:
if (magicda != XFS_ATTR_LEAF_MAGIC &&
magicda != XFS_ATTR3_LEAF_MAGIC) {
xfs_warn(mp, "Bad attr leaf magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_attr3_leaf_buf_ops;
break;
case XFS_BLF_ATTR_RMT_BUF:
if (!xfs_sb_version_hascrc(&mp->m_sb))
break;
if (magicda != XFS_ATTR3_RMT_MAGIC) {
xfs_warn(mp, "Bad attr remote magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_attr3_rmt_buf_ops;
break;
default:
break;
}
}
/* /*
* Perform a 'normal' buffer recovery. Each logged region of the * Perform a 'normal' buffer recovery. Each logged region of the
* buffer should be copied over the corresponding region in the * buffer should be copied over the corresponding region in the
@ -1932,88 +2118,8 @@ xlog_recover_do_reg_buffer(
/* Shouldn't be any more regions */ /* Shouldn't be any more regions */
ASSERT(i == item->ri_total); ASSERT(i == item->ri_total);
switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) { xlog_recovery_validate_buf_type(mp, bp, buf_f);
case XFS_BLF_BTREE_BUF:
switch (be32_to_cpu(*(__be32 *)bp->b_addr)) {
case XFS_ABTB_CRC_MAGIC:
case XFS_ABTC_CRC_MAGIC:
case XFS_ABTB_MAGIC:
case XFS_ABTC_MAGIC:
bp->b_ops = &xfs_allocbt_buf_ops;
break;
case XFS_IBT_CRC_MAGIC:
case XFS_IBT_MAGIC:
bp->b_ops = &xfs_inobt_buf_ops;
break;
case XFS_BMAP_CRC_MAGIC:
case XFS_BMAP_MAGIC:
bp->b_ops = &xfs_bmbt_buf_ops;
break;
default:
xfs_warn(mp, "Bad btree block magic!");
ASSERT(0);
break;
}
break;
case XFS_BLF_AGF_BUF:
if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGF_MAGIC)) {
xfs_warn(mp, "Bad AGF block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agf_buf_ops;
break;
case XFS_BLF_AGFL_BUF:
if (!xfs_sb_version_hascrc(&mp->m_sb))
break;
if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGFL_MAGIC)) {
xfs_warn(mp, "Bad AGFL block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agfl_buf_ops;
break;
case XFS_BLF_AGI_BUF:
if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) {
xfs_warn(mp, "Bad AGI block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agi_buf_ops;
break;
case XFS_BLF_UDQUOT_BUF:
case XFS_BLF_PDQUOT_BUF:
case XFS_BLF_GDQUOT_BUF:
if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DQUOT_MAGIC)) {
xfs_warn(mp, "Bad DQUOT block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_dquot_buf_ops;
break;
case XFS_BLF_DINO_BUF:
/*
* we get here with inode allocation buffers, not buffers that
* track unlinked list changes.
*/
if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) {
xfs_warn(mp, "Bad INODE block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_inode_buf_ops;
break;
case XFS_BLF_SYMLINK_BUF:
if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_SYMLINK_MAGIC)) {
xfs_warn(mp, "Bad symlink block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_symlink_buf_ops;
break;
default:
break;
}
} }
/* /*

Просмотреть файл

@ -507,6 +507,8 @@ void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *,
uint); uint);
void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp,
struct xfs_buf *src_bp);
void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);

Просмотреть файл

@ -768,6 +768,9 @@ xfs_trans_buf_set_type(
{ {
struct xfs_buf_log_item *bip = bp->b_fspriv; struct xfs_buf_log_item *bip = bp->b_fspriv;
if (!tp)
return;
ASSERT(bp->b_transp == tp); ASSERT(bp->b_transp == tp);
ASSERT(bip != NULL); ASSERT(bip != NULL);
ASSERT(atomic_read(&bip->bli_refcount) > 0); ASSERT(atomic_read(&bip->bli_refcount) > 0);
@ -777,6 +780,20 @@ xfs_trans_buf_set_type(
bip->__bli_format.blf_flags |= type; bip->__bli_format.blf_flags |= type;
} }
void
xfs_trans_buf_copy_type(
struct xfs_buf *dst_bp,
struct xfs_buf *src_bp)
{
struct xfs_buf_log_item *sbip = src_bp->b_fspriv;
struct xfs_buf_log_item *dbip = dst_bp->b_fspriv;
uint type;
type = sbip->__bli_format.blf_flags & XFS_BLF_TYPE_MASK;
dbip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK;
dbip->__bli_format.blf_flags |= type;
}
/* /*
* Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of
* dquots. However, unlike in inode buffer recovery, dquot buffers get * dquots. However, unlike in inode buffer recovery, dquot buffers get