aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_attr_leaf.c9
-rw-r--r--fs/xfs/xfs_attr_remote.h2
-rw-r--r--fs/xfs/xfs_buf_item.h18
-rw-r--r--fs/xfs/xfs_da_btree.c46
-rw-r--r--fs/xfs/xfs_da_btree.h2
-rw-r--r--fs/xfs/xfs_dir2_block.c12
-rw-r--r--fs/xfs/xfs_dir2_data.c8
-rw-r--r--fs/xfs/xfs_dir2_leaf.c26
-rw-r--r--fs/xfs/xfs_dir2_node.c15
-rw-r--r--fs/xfs/xfs_dir2_priv.h2
-rw-r--r--fs/xfs/xfs_log_recover.c254
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_buf.c17
13 files changed, 323 insertions, 90 deletions
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 287c8089b705..92cda03d1c01 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -271,8 +271,13 @@ xfs_attr3_leaf_read(
271 xfs_daddr_t mappedbno, 271 xfs_daddr_t mappedbno,
272 struct xfs_buf **bpp) 272 struct xfs_buf **bpp)
273{ 273{
274 return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, 274 int err;
275
276 err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
275 XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops); 277 XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops);
278 if (!err && tp)
279 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_ATTR_LEAF_BUF);
280 return err;
276} 281}
277 282
278/*======================================================================== 283/*========================================================================
@@ -1078,6 +1083,7 @@ xfs_attr3_leaf_to_node(
1078 goto out; 1083 goto out;
1079 1084
1080 /* copy leaf to new buffer, update identifiers */ 1085 /* copy leaf to new buffer, update identifiers */
1086 xfs_trans_buf_set_type(args->trans, bp2, XFS_BLF_ATTR_LEAF_BUF);
1081 bp2->b_ops = bp1->b_ops; 1087 bp2->b_ops = bp1->b_ops;
1082 memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp)); 1088 memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp));
1083 if (xfs_sb_version_hascrc(&mp->m_sb)) { 1089 if (xfs_sb_version_hascrc(&mp->m_sb)) {
@@ -1140,6 +1146,7 @@ xfs_attr3_leaf_create(
1140 if (error) 1146 if (error)
1141 return error; 1147 return error;
1142 bp->b_ops = &xfs_attr3_leaf_buf_ops; 1148 bp->b_ops = &xfs_attr3_leaf_buf_ops;
1149 xfs_trans_buf_set_type(args->trans, bp, XFS_BLF_ATTR_LEAF_BUF);
1143 leaf = bp->b_addr; 1150 leaf = bp->b_addr;
1144 memset(leaf, 0, XFS_LBSIZE(mp)); 1151 memset(leaf, 0, XFS_LBSIZE(mp));
1145 1152
diff --git a/fs/xfs/xfs_attr_remote.h b/fs/xfs/xfs_attr_remote.h
index 0ca8d9a1fa03..c7cca60a062a 100644
--- a/fs/xfs/xfs_attr_remote.h
+++ b/fs/xfs/xfs_attr_remote.h
@@ -37,6 +37,8 @@ struct xfs_attr3_rmt_hdr {
37 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \ 37 ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
38 sizeof(struct xfs_attr3_rmt_hdr) : 0)) 38 sizeof(struct xfs_attr3_rmt_hdr) : 0))
39 39
40extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
41
40int xfs_attr_rmtval_get(struct xfs_da_args *args); 42int xfs_attr_rmtval_get(struct xfs_da_args *args);
41int xfs_attr_rmtval_set(struct xfs_da_args *args); 43int xfs_attr_rmtval_set(struct xfs_da_args *args);
42int xfs_attr_rmtval_remove(struct xfs_da_args *args); 44int xfs_attr_rmtval_remove(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 09cab4ed1065..640adcfa4143 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -50,6 +50,14 @@ extern kmem_zone_t *xfs_buf_item_zone;
50#define XFS_BLF_AGI_BUF (1<<8) 50#define XFS_BLF_AGI_BUF (1<<8)
51#define XFS_BLF_DINO_BUF (1<<9) 51#define XFS_BLF_DINO_BUF (1<<9)
52#define XFS_BLF_SYMLINK_BUF (1<<10) 52#define XFS_BLF_SYMLINK_BUF (1<<10)
53#define XFS_BLF_DIR_BLOCK_BUF (1<<11)
54#define XFS_BLF_DIR_DATA_BUF (1<<12)
55#define XFS_BLF_DIR_FREE_BUF (1<<13)
56#define XFS_BLF_DIR_LEAF1_BUF (1<<14)
57#define XFS_BLF_DIR_LEAFN_BUF (1<<15)
58#define XFS_BLF_DA_NODE_BUF (1<<16)
59#define XFS_BLF_ATTR_LEAF_BUF (1<<17)
60#define XFS_BLF_ATTR_RMT_BUF (1<<18)
53 61
54#define XFS_BLF_TYPE_MASK \ 62#define XFS_BLF_TYPE_MASK \
55 (XFS_BLF_UDQUOT_BUF | \ 63 (XFS_BLF_UDQUOT_BUF | \
@@ -60,7 +68,15 @@ extern kmem_zone_t *xfs_buf_item_zone;
60 XFS_BLF_AGFL_BUF | \ 68 XFS_BLF_AGFL_BUF | \
61 XFS_BLF_AGI_BUF | \ 69 XFS_BLF_AGI_BUF | \
62 XFS_BLF_DINO_BUF | \ 70 XFS_BLF_DINO_BUF | \
63 XFS_BLF_SYMLINK_BUF) 71 XFS_BLF_SYMLINK_BUF | \
72 XFS_BLF_DIR_BLOCK_BUF | \
73 XFS_BLF_DIR_DATA_BUF | \
74 XFS_BLF_DIR_FREE_BUF | \
75 XFS_BLF_DIR_LEAF1_BUF | \
76 XFS_BLF_DIR_LEAFN_BUF | \
77 XFS_BLF_DA_NODE_BUF | \
78 XFS_BLF_ATTR_LEAF_BUF | \
79 XFS_BLF_ATTR_RMT_BUF)
64 80
65#define XFS_BLF_CHUNK 128 81#define XFS_BLF_CHUNK 128
66#define XFS_BLF_SHIFT 7 82#define XFS_BLF_SHIFT 7
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 779ecdcdbe02..5aebd9bd44d1 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -292,7 +292,6 @@ const struct xfs_buf_ops xfs_da3_node_buf_ops = {
292 .verify_write = xfs_da3_node_write_verify, 292 .verify_write = xfs_da3_node_write_verify,
293}; 293};
294 294
295
296int 295int
297xfs_da3_node_read( 296xfs_da3_node_read(
298 struct xfs_trans *tp, 297 struct xfs_trans *tp,
@@ -302,8 +301,35 @@ xfs_da3_node_read(
302 struct xfs_buf **bpp, 301 struct xfs_buf **bpp,
303 int which_fork) 302 int which_fork)
304{ 303{
305 return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, 304 int err;
305
306 err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
306 which_fork, &xfs_da3_node_buf_ops); 307 which_fork, &xfs_da3_node_buf_ops);
308 if (!err && tp) {
309 struct xfs_da_blkinfo *info = (*bpp)->b_addr;
310 int type;
311
312 switch (be16_to_cpu(info->magic)) {
313 case XFS_DA3_NODE_MAGIC:
314 case XFS_DA_NODE_MAGIC:
315 type = XFS_BLF_DA_NODE_BUF;
316 break;
317 case XFS_ATTR_LEAF_MAGIC:
318 case XFS_ATTR3_LEAF_MAGIC:
319 type = XFS_BLF_ATTR_LEAF_BUF;
320 break;
321 case XFS_DIR2_LEAFN_MAGIC:
322 case XFS_DIR3_LEAFN_MAGIC:
323 type = XFS_BLF_DIR_LEAFN_BUF;
324 break;
325 default:
326 type = 0;
327 ASSERT(0);
328 break;
329 }
330 xfs_trans_buf_set_type(tp, *bpp, type);
331 }
332 return err;
307} 333}
308 334
309/*======================================================================== 335/*========================================================================
@@ -334,6 +360,8 @@ xfs_da3_node_create(
334 error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork); 360 error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
335 if (error) 361 if (error)
336 return(error); 362 return(error);
363 bp->b_ops = &xfs_da3_node_buf_ops;
364 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
337 node = bp->b_addr; 365 node = bp->b_addr;
338 366
339 if (xfs_sb_version_hascrc(&mp->m_sb)) { 367 if (xfs_sb_version_hascrc(&mp->m_sb)) {
@@ -352,7 +380,6 @@ xfs_da3_node_create(
352 xfs_trans_log_buf(tp, bp, 380 xfs_trans_log_buf(tp, bp,
353 XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node))); 381 XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
354 382
355 bp->b_ops = &xfs_da3_node_buf_ops;
356 *bpp = bp; 383 *bpp = bp;
357 return(0); 384 return(0);
358} 385}
@@ -565,6 +592,12 @@ xfs_da3_root_split(
565 btree = xfs_da3_node_tree_p(oldroot); 592 btree = xfs_da3_node_tree_p(oldroot);
566 size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot); 593 size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
567 level = nodehdr.level; 594 level = nodehdr.level;
595
596 /*
597 * we are about to copy oldroot to bp, so set up the type
598 * of bp while we know exactly what it will be.
599 */
600 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
568 } else { 601 } else {
569 struct xfs_dir3_icleaf_hdr leafhdr; 602 struct xfs_dir3_icleaf_hdr leafhdr;
570 struct xfs_dir2_leaf_entry *ents; 603 struct xfs_dir2_leaf_entry *ents;
@@ -577,6 +610,12 @@ xfs_da3_root_split(
577 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); 610 leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
578 size = (int)((char *)&ents[leafhdr.count] - (char *)leaf); 611 size = (int)((char *)&ents[leafhdr.count] - (char *)leaf);
579 level = 0; 612 level = 0;
613
614 /*
615 * we are about to copy oldroot to bp, so set up the type
616 * of bp while we know exactly what it will be.
617 */
618 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
580 } 619 }
581 620
582 /* 621 /*
@@ -1092,6 +1131,7 @@ xfs_da3_root_join(
1092 */ 1131 */
1093 memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize); 1132 memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize);
1094 root_blk->bp->b_ops = bp->b_ops; 1133 root_blk->bp->b_ops = bp->b_ops;
1134 xfs_trans_buf_copy_type(root_blk->bp, bp);
1095 if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) { 1135 if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
1096 struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr; 1136 struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
1097 da3->blkno = cpu_to_be64(root_blk->bp->b_bn); 1137 da3->blkno = cpu_to_be64(root_blk->bp->b_bn);
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 0e8182c5210b..6fb3371c63cf 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -301,6 +301,8 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
301 xfs_dablk_t bno, xfs_daddr_t mappedbno, 301 xfs_dablk_t bno, xfs_daddr_t mappedbno,
302 struct xfs_buf **bpp, int which_fork); 302 struct xfs_buf **bpp, int which_fork);
303 303
304extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
305
304/* 306/*
305 * Utility routines. 307 * Utility routines.
306 */ 308 */
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index d2e445f92ffb..58816ecdbba5 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -132,20 +132,26 @@ xfs_dir3_block_read(
132 struct xfs_buf **bpp) 132 struct xfs_buf **bpp)
133{ 133{
134 struct xfs_mount *mp = dp->i_mount; 134 struct xfs_mount *mp = dp->i_mount;
135 int err;
135 136
136 return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp, 137 err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
137 XFS_DATA_FORK, &xfs_dir3_block_buf_ops); 138 XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
139 if (!err && tp)
140 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_BLOCK_BUF);
141 return err;
138} 142}
139 143
140static void 144static void
141xfs_dir3_block_init( 145xfs_dir3_block_init(
142 struct xfs_mount *mp, 146 struct xfs_mount *mp,
147 struct xfs_trans *tp,
143 struct xfs_buf *bp, 148 struct xfs_buf *bp,
144 struct xfs_inode *dp) 149 struct xfs_inode *dp)
145{ 150{
146 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; 151 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
147 152
148 bp->b_ops = &xfs_dir3_block_buf_ops; 153 bp->b_ops = &xfs_dir3_block_buf_ops;
154 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_BLOCK_BUF);
149 155
150 if (xfs_sb_version_hascrc(&mp->m_sb)) { 156 if (xfs_sb_version_hascrc(&mp->m_sb)) {
151 memset(hdr3, 0, sizeof(*hdr3)); 157 memset(hdr3, 0, sizeof(*hdr3));
@@ -1080,7 +1086,7 @@ xfs_dir2_leaf_to_block(
1080 /* 1086 /*
1081 * Start converting it to block form. 1087 * Start converting it to block form.
1082 */ 1088 */
1083 xfs_dir3_block_init(mp, dbp, dp); 1089 xfs_dir3_block_init(mp, tp, dbp, dp);
1084 1090
1085 needlog = 1; 1091 needlog = 1;
1086 needscan = 0; 1092 needscan = 0;
@@ -1209,7 +1215,7 @@ xfs_dir2_sf_to_block(
1209 kmem_free(sfp); 1215 kmem_free(sfp);
1210 return error; 1216 return error;
1211 } 1217 }
1212 xfs_dir3_block_init(mp, bp, dp); 1218 xfs_dir3_block_init(mp, tp, bp, dp);
1213 hdr = bp->b_addr; 1219 hdr = bp->b_addr;
1214 1220
1215 /* 1221 /*
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 78320df3743f..5e0c711f9af3 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -301,8 +301,13 @@ xfs_dir3_data_read(
301 xfs_daddr_t mapped_bno, 301 xfs_daddr_t mapped_bno,
302 struct xfs_buf **bpp) 302 struct xfs_buf **bpp)
303{ 303{
304 return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp, 304 int err;
305
306 err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
305 XFS_DATA_FORK, &xfs_dir3_data_buf_ops); 307 XFS_DATA_FORK, &xfs_dir3_data_buf_ops);
308 if (!err && tp)
309 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_DATA_BUF);
310 return err;
306} 311}
307 312
308int 313int
@@ -571,6 +576,7 @@ xfs_dir3_data_init(
571 if (error) 576 if (error)
572 return error; 577 return error;
573 bp->b_ops = &xfs_dir3_data_buf_ops; 578 bp->b_ops = &xfs_dir3_data_buf_ops;
579 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_DATA_BUF);
574 580
575 /* 581 /*
576 * Initialize the header. 582 * Initialize the header.
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 7352e41d2aaa..84f4c9cfe95a 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -279,7 +279,7 @@ xfs_dir3_leafn_write_verify(
279 __write_verify(bp, XFS_DIR2_LEAFN_MAGIC); 279 __write_verify(bp, XFS_DIR2_LEAFN_MAGIC);
280} 280}
281 281
282static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { 282const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
283 .verify_read = xfs_dir3_leaf1_read_verify, 283 .verify_read = xfs_dir3_leaf1_read_verify,
284 .verify_write = xfs_dir3_leaf1_write_verify, 284 .verify_write = xfs_dir3_leaf1_write_verify,
285}; 285};
@@ -297,8 +297,13 @@ xfs_dir3_leaf_read(
297 xfs_daddr_t mappedbno, 297 xfs_daddr_t mappedbno,
298 struct xfs_buf **bpp) 298 struct xfs_buf **bpp)
299{ 299{
300 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, 300 int err;
301
302 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
301 XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); 303 XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops);
304 if (!err && tp)
305 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAF1_BUF);
306 return err;
302} 307}
303 308
304int 309int
@@ -309,8 +314,13 @@ xfs_dir3_leafn_read(
309 xfs_daddr_t mappedbno, 314 xfs_daddr_t mappedbno,
310 struct xfs_buf **bpp) 315 struct xfs_buf **bpp)
311{ 316{
312 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, 317 int err;
318
319 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
313 XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); 320 XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops);
321 if (!err && tp)
322 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAFN_BUF);
323 return err;
314} 324}
315 325
316/* 326/*
@@ -319,6 +329,7 @@ xfs_dir3_leafn_read(
319static void 329static void
320xfs_dir3_leaf_init( 330xfs_dir3_leaf_init(
321 struct xfs_mount *mp, 331 struct xfs_mount *mp,
332 struct xfs_trans *tp,
322 struct xfs_buf *bp, 333 struct xfs_buf *bp,
323 xfs_ino_t owner, 334 xfs_ino_t owner,
324 __uint16_t type) 335 __uint16_t type)
@@ -353,8 +364,11 @@ xfs_dir3_leaf_init(
353 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 364 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
354 ltp->bestcount = 0; 365 ltp->bestcount = 0;
355 bp->b_ops = &xfs_dir3_leaf1_buf_ops; 366 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
356 } else 367 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAF1_BUF);
368 } else {
357 bp->b_ops = &xfs_dir3_leafn_buf_ops; 369 bp->b_ops = &xfs_dir3_leafn_buf_ops;
370 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
371 }
358} 372}
359 373
360int 374int
@@ -379,7 +393,7 @@ xfs_dir3_leaf_get_buf(
379 if (error) 393 if (error)
380 return error; 394 return error;
381 395
382 xfs_dir3_leaf_init(mp, bp, dp->i_ino, magic); 396 xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
383 xfs_dir3_leaf_log_header(tp, bp); 397 xfs_dir3_leaf_log_header(tp, bp);
384 if (magic == XFS_DIR2_LEAF1_MAGIC) 398 if (magic == XFS_DIR2_LEAF1_MAGIC)
385 xfs_dir3_leaf_log_tail(tp, bp); 399 xfs_dir3_leaf_log_tail(tp, bp);
@@ -474,6 +488,7 @@ xfs_dir2_block_to_leaf(
474 * Fix up the block header, make it a data block. 488 * Fix up the block header, make it a data block.
475 */ 489 */
476 dbp->b_ops = &xfs_dir3_data_buf_ops; 490 dbp->b_ops = &xfs_dir3_data_buf_ops;
491 xfs_trans_buf_set_type(tp, dbp, XFS_BLF_DIR_DATA_BUF);
477 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) 492 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
478 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); 493 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
479 else 494 else
@@ -2182,6 +2197,7 @@ xfs_dir2_node_to_leaf(
2182 xfs_dir3_leaf_compact(args, &leafhdr, lbp); 2197 xfs_dir3_leaf_compact(args, &leafhdr, lbp);
2183 2198
2184 lbp->b_ops = &xfs_dir3_leaf1_buf_ops; 2199 lbp->b_ops = &xfs_dir3_leaf1_buf_ops;
2200 xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAF1_BUF);
2185 leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC) 2201 leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC)
2186 ? XFS_DIR2_LEAF1_MAGIC 2202 ? XFS_DIR2_LEAF1_MAGIC
2187 : XFS_DIR3_LEAF1_MAGIC; 2203 : XFS_DIR3_LEAF1_MAGIC;
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 122449b33f5e..1806a22d5593 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -147,7 +147,7 @@ xfs_dir3_free_write_verify(
147 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF); 147 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF);
148} 148}
149 149
150static const struct xfs_buf_ops xfs_dir3_free_buf_ops = { 150const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
151 .verify_read = xfs_dir3_free_read_verify, 151 .verify_read = xfs_dir3_free_read_verify,
152 .verify_write = xfs_dir3_free_write_verify, 152 .verify_write = xfs_dir3_free_write_verify,
153}; 153};
@@ -161,8 +161,15 @@ __xfs_dir3_free_read(
161 xfs_daddr_t mappedbno, 161 xfs_daddr_t mappedbno,
162 struct xfs_buf **bpp) 162 struct xfs_buf **bpp)
163{ 163{
164 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, 164 int err;
165
166 err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
165 XFS_DATA_FORK, &xfs_dir3_free_buf_ops); 167 XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
168
169 /* try read returns without an error or *bpp if it lands in a hole */
170 if (!err && tp && *bpp)
171 xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_FREE_BUF);
172 return err;
166} 173}
167 174
168int 175int
@@ -249,6 +256,7 @@ xfs_dir3_free_get_buf(
249 if (error) 256 if (error)
250 return error; 257 return error;
251 258
259 xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_FREE_BUF);
252 bp->b_ops = &xfs_dir3_free_buf_ops; 260 bp->b_ops = &xfs_dir3_free_buf_ops;
253 261
254 /* 262 /*
@@ -396,6 +404,7 @@ xfs_dir2_leaf_to_node(
396 else 404 else
397 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); 405 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
398 lbp->b_ops = &xfs_dir3_leafn_buf_ops; 406 lbp->b_ops = &xfs_dir3_leafn_buf_ops;
407 xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAFN_BUF);
399 xfs_dir3_leaf_log_header(tp, lbp); 408 xfs_dir3_leaf_log_header(tp, lbp);
400 xfs_dir3_leaf_check(mp, lbp); 409 xfs_dir3_leaf_check(mp, lbp);
401 return 0; 410 return 0;
@@ -811,6 +820,7 @@ xfs_dir2_leafn_lookup_for_entry(
811 (char *)curbp->b_addr); 820 (char *)curbp->b_addr);
812 state->extrablk.magic = XFS_DIR2_DATA_MAGIC; 821 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
813 curbp->b_ops = &xfs_dir3_data_buf_ops; 822 curbp->b_ops = &xfs_dir3_data_buf_ops;
823 xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
814 if (cmp == XFS_CMP_EXACT) 824 if (cmp == XFS_CMP_EXACT)
815 return XFS_ERROR(EEXIST); 825 return XFS_ERROR(EEXIST);
816 } 826 }
@@ -825,6 +835,7 @@ xfs_dir2_leafn_lookup_for_entry(
825 state->extrablk.blkno = curdb; 835 state->extrablk.blkno = curdb;
826 state->extrablk.magic = XFS_DIR2_DATA_MAGIC; 836 state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
827 curbp->b_ops = &xfs_dir3_data_buf_ops; 837 curbp->b_ops = &xfs_dir3_data_buf_ops;
838 xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
828 } else { 839 } else {
829 /* If the curbp is not the CI match block, drop it */ 840 /* If the curbp is not the CI match block, drop it */
830 if (state->extrablk.bp != curbp) 841 if (state->extrablk.bp != curbp)
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 932565d6ef2a..7cf573c88aad 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -49,6 +49,7 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
49#endif 49#endif
50 50
51extern const struct xfs_buf_ops xfs_dir3_data_buf_ops; 51extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
52extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;
52 53
53extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp); 54extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
54extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp, 55extern 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,
77 xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); 78 xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
78 79
79/* xfs_dir2_leaf.c */ 80/* xfs_dir2_leaf.c */
81extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
80extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; 82extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
81 83
82extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, 84extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index d1292fd1112a..00727bc4a9b0 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -45,7 +45,14 @@
45#include "xfs_cksum.h" 45#include "xfs_cksum.h"
46#include "xfs_trace.h" 46#include "xfs_trace.h"
47#include "xfs_icache.h" 47#include "xfs_icache.h"
48
49/* Need all the magic numbers and buffer ops structures from these headers */
48#include "xfs_symlink.h" 50#include "xfs_symlink.h"
51#include "xfs_da_btree.h"
52#include "xfs_dir2_format.h"
53#include "xfs_dir2_priv.h"
54#include "xfs_attr_leaf.h"
55#include "xfs_attr_remote.h"
49 56
50STATIC int 57STATIC int
51xlog_find_zeroed( 58xlog_find_zeroed(
@@ -1860,81 +1867,30 @@ xlog_recover_do_inode_buffer(
1860} 1867}
1861 1868
1862/* 1869/*
1863 * Perform a 'normal' buffer recovery. Each logged region of the 1870 * Validate the recovered buffer is of the correct type and attach the
1864 * buffer should be copied over the corresponding region in the 1871 * appropriate buffer operations to them for writeback. Magic numbers are in a
1865 * given buffer. The bitmap in the buf log format structure indicates 1872 * few places:
1866 * where to place the logged data. 1873 * the first 16 bits of the buffer (inode buffer, dquot buffer),
1874 * the first 32 bits of the buffer (most blocks),
1875 * inside a struct xfs_da_blkinfo at the start of the buffer.
1867 */ 1876 */
1868STATIC void 1877static void
1869xlog_recover_do_reg_buffer( 1878xlog_recovery_validate_buf_type(
1870 struct xfs_mount *mp, 1879 struct xfs_mount *mp,
1871 xlog_recover_item_t *item,
1872 struct xfs_buf *bp, 1880 struct xfs_buf *bp,
1873 xfs_buf_log_format_t *buf_f) 1881 xfs_buf_log_format_t *buf_f)
1874{ 1882{
1875 int i; 1883 struct xfs_da_blkinfo *info = bp->b_addr;
1876 int bit; 1884 __uint32_t magic32;
1877 int nbits; 1885 __uint16_t magic16;
1878 int error; 1886 __uint16_t magicda;
1879 1887
1880 trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f); 1888 magic32 = be32_to_cpu(*(__be32 *)bp->b_addr);
1881 1889 magic16 = be16_to_cpu(*(__be16*)bp->b_addr);
1882 bit = 0; 1890 magicda = be16_to_cpu(info->magic);
1883 i = 1; /* 0 is the buf format structure */
1884 while (1) {
1885 bit = xfs_next_bit(buf_f->blf_data_map,
1886 buf_f->blf_map_size, bit);
1887 if (bit == -1)
1888 break;
1889 nbits = xfs_contig_bits(buf_f->blf_data_map,
1890 buf_f->blf_map_size, bit);
1891 ASSERT(nbits > 0);
1892 ASSERT(item->ri_buf[i].i_addr != NULL);
1893 ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0);
1894 ASSERT(BBTOB(bp->b_io_length) >=
1895 ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT));
1896
1897 /*
1898 * Do a sanity check if this is a dquot buffer. Just checking
1899 * the first dquot in the buffer should do. XXXThis is
1900 * probably a good thing to do for other buf types also.
1901 */
1902 error = 0;
1903 if (buf_f->blf_flags &
1904 (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
1905 if (item->ri_buf[i].i_addr == NULL) {
1906 xfs_alert(mp,
1907 "XFS: NULL dquot in %s.", __func__);
1908 goto next;
1909 }
1910 if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
1911 xfs_alert(mp,
1912 "XFS: dquot too small (%d) in %s.",
1913 item->ri_buf[i].i_len, __func__);
1914 goto next;
1915 }
1916 error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
1917 -1, 0, XFS_QMOPT_DOWARN,
1918 "dquot_buf_recover");
1919 if (error)
1920 goto next;
1921 }
1922
1923 memcpy(xfs_buf_offset(bp,
1924 (uint)bit << XFS_BLF_SHIFT), /* dest */
1925 item->ri_buf[i].i_addr, /* source */
1926 nbits<<XFS_BLF_SHIFT); /* length */
1927 next:
1928 i++;
1929 bit += nbits;
1930 }
1931
1932 /* Shouldn't be any more regions */
1933 ASSERT(i == item->ri_total);
1934
1935 switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) { 1891 switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) {
1936 case XFS_BLF_BTREE_BUF: 1892 case XFS_BLF_BTREE_BUF:
1937 switch (be32_to_cpu(*(__be32 *)bp->b_addr)) { 1893 switch (magic32) {
1938 case XFS_ABTB_CRC_MAGIC: 1894 case XFS_ABTB_CRC_MAGIC:
1939 case XFS_ABTC_CRC_MAGIC: 1895 case XFS_ABTC_CRC_MAGIC:
1940 case XFS_ABTB_MAGIC: 1896 case XFS_ABTB_MAGIC:
@@ -1956,7 +1912,7 @@ xlog_recover_do_reg_buffer(
1956 } 1912 }
1957 break; 1913 break;
1958 case XFS_BLF_AGF_BUF: 1914 case XFS_BLF_AGF_BUF:
1959 if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGF_MAGIC)) { 1915 if (magic32 != XFS_AGF_MAGIC) {
1960 xfs_warn(mp, "Bad AGF block magic!"); 1916 xfs_warn(mp, "Bad AGF block magic!");
1961 ASSERT(0); 1917 ASSERT(0);
1962 break; 1918 break;
@@ -1966,7 +1922,7 @@ xlog_recover_do_reg_buffer(
1966 case XFS_BLF_AGFL_BUF: 1922 case XFS_BLF_AGFL_BUF:
1967 if (!xfs_sb_version_hascrc(&mp->m_sb)) 1923 if (!xfs_sb_version_hascrc(&mp->m_sb))
1968 break; 1924 break;
1969 if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGFL_MAGIC)) { 1925 if (magic32 != XFS_AGFL_MAGIC) {
1970 xfs_warn(mp, "Bad AGFL block magic!"); 1926 xfs_warn(mp, "Bad AGFL block magic!");
1971 ASSERT(0); 1927 ASSERT(0);
1972 break; 1928 break;
@@ -1974,7 +1930,7 @@ xlog_recover_do_reg_buffer(
1974 bp->b_ops = &xfs_agfl_buf_ops; 1930 bp->b_ops = &xfs_agfl_buf_ops;
1975 break; 1931 break;
1976 case XFS_BLF_AGI_BUF: 1932 case XFS_BLF_AGI_BUF:
1977 if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) { 1933 if (magic32 != XFS_AGI_MAGIC) {
1978 xfs_warn(mp, "Bad AGI block magic!"); 1934 xfs_warn(mp, "Bad AGI block magic!");
1979 ASSERT(0); 1935 ASSERT(0);
1980 break; 1936 break;
@@ -1984,7 +1940,7 @@ xlog_recover_do_reg_buffer(
1984 case XFS_BLF_UDQUOT_BUF: 1940 case XFS_BLF_UDQUOT_BUF:
1985 case XFS_BLF_PDQUOT_BUF: 1941 case XFS_BLF_PDQUOT_BUF:
1986 case XFS_BLF_GDQUOT_BUF: 1942 case XFS_BLF_GDQUOT_BUF:
1987 if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DQUOT_MAGIC)) { 1943 if (magic16 != XFS_DQUOT_MAGIC) {
1988 xfs_warn(mp, "Bad DQUOT block magic!"); 1944 xfs_warn(mp, "Bad DQUOT block magic!");
1989 ASSERT(0); 1945 ASSERT(0);
1990 break; 1946 break;
@@ -1996,7 +1952,7 @@ xlog_recover_do_reg_buffer(
1996 * we get here with inode allocation buffers, not buffers that 1952 * we get here with inode allocation buffers, not buffers that
1997 * track unlinked list changes. 1953 * track unlinked list changes.
1998 */ 1954 */
1999 if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) { 1955 if (magic16 != XFS_DINODE_MAGIC) {
2000 xfs_warn(mp, "Bad INODE block magic!"); 1956 xfs_warn(mp, "Bad INODE block magic!");
2001 ASSERT(0); 1957 ASSERT(0);
2002 break; 1958 break;
@@ -2004,19 +1960,169 @@ xlog_recover_do_reg_buffer(
2004 bp->b_ops = &xfs_inode_buf_ops; 1960 bp->b_ops = &xfs_inode_buf_ops;
2005 break; 1961 break;
2006 case XFS_BLF_SYMLINK_BUF: 1962 case XFS_BLF_SYMLINK_BUF:
2007 if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_SYMLINK_MAGIC)) { 1963 if (magic32 != XFS_SYMLINK_MAGIC) {
2008 xfs_warn(mp, "Bad symlink block magic!"); 1964 xfs_warn(mp, "Bad symlink block magic!");
2009 ASSERT(0); 1965 ASSERT(0);
2010 break; 1966 break;
2011 } 1967 }
2012 bp->b_ops = &xfs_symlink_buf_ops; 1968 bp->b_ops = &xfs_symlink_buf_ops;
2013 break; 1969 break;
1970 case XFS_BLF_DIR_BLOCK_BUF:
1971 if (magic32 != XFS_DIR2_BLOCK_MAGIC &&
1972 magic32 != XFS_DIR3_BLOCK_MAGIC) {
1973 xfs_warn(mp, "Bad dir block magic!");
1974 ASSERT(0);
1975 break;
1976 }
1977 bp->b_ops = &xfs_dir3_block_buf_ops;
1978 break;
1979 case XFS_BLF_DIR_DATA_BUF:
1980 if (magic32 != XFS_DIR2_DATA_MAGIC &&
1981 magic32 != XFS_DIR3_DATA_MAGIC) {
1982 xfs_warn(mp, "Bad dir data magic!");
1983 ASSERT(0);
1984 break;
1985 }
1986 bp->b_ops = &xfs_dir3_data_buf_ops;
1987 break;
1988 case XFS_BLF_DIR_FREE_BUF:
1989 if (magic32 != XFS_DIR2_FREE_MAGIC &&
1990 magic32 != XFS_DIR3_FREE_MAGIC) {
1991 xfs_warn(mp, "Bad dir3 free magic!");
1992 ASSERT(0);
1993 break;
1994 }
1995 bp->b_ops = &xfs_dir3_free_buf_ops;
1996 break;
1997 case XFS_BLF_DIR_LEAF1_BUF:
1998 if (magicda != XFS_DIR2_LEAF1_MAGIC &&
1999 magicda != XFS_DIR3_LEAF1_MAGIC) {
2000 xfs_warn(mp, "Bad dir leaf1 magic!");
2001 ASSERT(0);
2002 break;
2003 }
2004 bp->b_ops = &xfs_dir3_leaf1_buf_ops;
2005 break;
2006 case XFS_BLF_DIR_LEAFN_BUF:
2007 if (magicda != XFS_DIR2_LEAFN_MAGIC &&
2008 magicda != XFS_DIR3_LEAFN_MAGIC) {
2009 xfs_warn(mp, "Bad dir leafn magic!");
2010 ASSERT(0);
2011 break;
2012 }
2013 bp->b_ops = &xfs_dir3_leafn_buf_ops;
2014 break;
2015 case XFS_BLF_DA_NODE_BUF:
2016 if (magicda != XFS_DA_NODE_MAGIC &&
2017 magicda != XFS_DA3_NODE_MAGIC) {
2018 xfs_warn(mp, "Bad da node magic!");
2019 ASSERT(0);
2020 break;
2021 }
2022 bp->b_ops = &xfs_da3_node_buf_ops;
2023 break;
2024 case XFS_BLF_ATTR_LEAF_BUF:
2025 if (magicda != XFS_ATTR_LEAF_MAGIC &&
2026 magicda != XFS_ATTR3_LEAF_MAGIC) {
2027 xfs_warn(mp, "Bad attr leaf magic!");
2028 ASSERT(0);
2029 break;
2030 }
2031 bp->b_ops = &xfs_attr3_leaf_buf_ops;
2032 break;
2033 case XFS_BLF_ATTR_RMT_BUF:
2034 if (!xfs_sb_version_hascrc(&mp->m_sb))
2035 break;
2036 if (magicda != XFS_ATTR3_RMT_MAGIC) {
2037 xfs_warn(mp, "Bad attr remote magic!");
2038 ASSERT(0);
2039 break;
2040 }
2041 bp->b_ops = &xfs_attr3_rmt_buf_ops;
2042 break;
2014 default: 2043 default:
2015 break; 2044 break;
2016 } 2045 }
2017} 2046}
2018 2047
2019/* 2048/*
2049 * Perform a 'normal' buffer recovery. Each logged region of the
2050 * buffer should be copied over the corresponding region in the
2051 * given buffer. The bitmap in the buf log format structure indicates
2052 * where to place the logged data.
2053 */
2054STATIC void
2055xlog_recover_do_reg_buffer(
2056 struct xfs_mount *mp,
2057 xlog_recover_item_t *item,
2058 struct xfs_buf *bp,
2059 xfs_buf_log_format_t *buf_f)
2060{
2061 int i;
2062 int bit;
2063 int nbits;
2064 int error;
2065
2066 trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f);
2067
2068 bit = 0;
2069 i = 1; /* 0 is the buf format structure */
2070 while (1) {
2071 bit = xfs_next_bit(buf_f->blf_data_map,
2072 buf_f->blf_map_size, bit);
2073 if (bit == -1)
2074 break;
2075 nbits = xfs_contig_bits(buf_f->blf_data_map,
2076 buf_f->blf_map_size, bit);
2077 ASSERT(nbits > 0);
2078 ASSERT(item->ri_buf[i].i_addr != NULL);
2079 ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0);
2080 ASSERT(BBTOB(bp->b_io_length) >=
2081 ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT));
2082
2083 /*
2084 * Do a sanity check if this is a dquot buffer. Just checking
2085 * the first dquot in the buffer should do. XXXThis is
2086 * probably a good thing to do for other buf types also.
2087 */
2088 error = 0;
2089 if (buf_f->blf_flags &
2090 (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
2091 if (item->ri_buf[i].i_addr == NULL) {
2092 xfs_alert(mp,
2093 "XFS: NULL dquot in %s.", __func__);
2094 goto next;
2095 }
2096 if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
2097 xfs_alert(mp,
2098 "XFS: dquot too small (%d) in %s.",
2099 item->ri_buf[i].i_len, __func__);
2100 goto next;
2101 }
2102 error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
2103 -1, 0, XFS_QMOPT_DOWARN,
2104 "dquot_buf_recover");
2105 if (error)
2106 goto next;
2107 }
2108
2109 memcpy(xfs_buf_offset(bp,
2110 (uint)bit << XFS_BLF_SHIFT), /* dest */
2111 item->ri_buf[i].i_addr, /* source */
2112 nbits<<XFS_BLF_SHIFT); /* length */
2113 next:
2114 i++;
2115 bit += nbits;
2116 }
2117
2118 /* Shouldn't be any more regions */
2119 ASSERT(i == item->ri_total);
2120
2121 xlog_recovery_validate_buf_type(mp, bp, buf_f);
2122
2123}
2124
2125/*
2020 * Do some primitive error checking on ondisk dquot data structures. 2126 * Do some primitive error checking on ondisk dquot data structures.
2021 */ 2127 */
2022int 2128int
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 1b04fe59c603..fa78a3f87c6e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -507,6 +507,8 @@ void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
507void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); 507void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
508void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *, 508void xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *,
509 uint); 509 uint);
510void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp,
511 struct xfs_buf *src_bp);
510void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int); 512void xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
511void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); 513void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
512void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); 514void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 8a0f6af51206..40871bf607f0 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -768,6 +768,9 @@ xfs_trans_buf_set_type(
768{ 768{
769 struct xfs_buf_log_item *bip = bp->b_fspriv; 769 struct xfs_buf_log_item *bip = bp->b_fspriv;
770 770
771 if (!tp)
772 return;
773
771 ASSERT(bp->b_transp == tp); 774 ASSERT(bp->b_transp == tp);
772 ASSERT(bip != NULL); 775 ASSERT(bip != NULL);
773 ASSERT(atomic_read(&bip->bli_refcount) > 0); 776 ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -777,6 +780,20 @@ xfs_trans_buf_set_type(
777 bip->__bli_format.blf_flags |= type; 780 bip->__bli_format.blf_flags |= type;
778} 781}
779 782
783void
784xfs_trans_buf_copy_type(
785 struct xfs_buf *dst_bp,
786 struct xfs_buf *src_bp)
787{
788 struct xfs_buf_log_item *sbip = src_bp->b_fspriv;
789 struct xfs_buf_log_item *dbip = dst_bp->b_fspriv;
790 uint type;
791
792 type = sbip->__bli_format.blf_flags & XFS_BLF_TYPE_MASK;
793 dbip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK;
794 dbip->__bli_format.blf_flags |= type;
795}
796
780/* 797/*
781 * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of 798 * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of
782 * dquots. However, unlike in inode buffer recovery, dquot buffers get 799 * dquots. However, unlike in inode buffer recovery, dquot buffers get