.. | .. |
---|
12 | 12 | #include "xfs_trans_resv.h" |
---|
13 | 13 | #include "xfs_bit.h" |
---|
14 | 14 | #include "xfs_mount.h" |
---|
15 | | -#include "xfs_da_format.h" |
---|
16 | | -#include "xfs_da_btree.h" |
---|
| 15 | +#include "xfs_inode.h" |
---|
17 | 16 | #include "xfs_dir2.h" |
---|
18 | 17 | #include "xfs_dir2_priv.h" |
---|
19 | | -#include "xfs_inode.h" |
---|
20 | 18 | #include "xfs_trans.h" |
---|
21 | | -#include "xfs_inode_item.h" |
---|
22 | | -#include "xfs_alloc.h" |
---|
23 | 19 | #include "xfs_bmap.h" |
---|
24 | | -#include "xfs_attr.h" |
---|
25 | 20 | #include "xfs_attr_leaf.h" |
---|
26 | 21 | #include "xfs_error.h" |
---|
27 | 22 | #include "xfs_trace.h" |
---|
28 | | -#include "xfs_cksum.h" |
---|
29 | 23 | #include "xfs_buf_item.h" |
---|
30 | 24 | #include "xfs_log.h" |
---|
31 | 25 | |
---|
.. | .. |
---|
84 | 78 | * Allocate a dir-state structure. |
---|
85 | 79 | * We don't put them on the stack since they're large. |
---|
86 | 80 | */ |
---|
87 | | -xfs_da_state_t * |
---|
88 | | -xfs_da_state_alloc(void) |
---|
| 81 | +struct xfs_da_state * |
---|
| 82 | +xfs_da_state_alloc( |
---|
| 83 | + struct xfs_da_args *args) |
---|
89 | 84 | { |
---|
90 | | - return kmem_zone_zalloc(xfs_da_state_zone, KM_NOFS); |
---|
| 85 | + struct xfs_da_state *state; |
---|
| 86 | + |
---|
| 87 | + state = kmem_cache_zalloc(xfs_da_state_zone, GFP_NOFS | __GFP_NOFAIL); |
---|
| 88 | + state->args = args; |
---|
| 89 | + state->mp = args->dp->i_mount; |
---|
| 90 | + return state; |
---|
91 | 91 | } |
---|
92 | 92 | |
---|
93 | 93 | /* |
---|
.. | .. |
---|
113 | 113 | #ifdef DEBUG |
---|
114 | 114 | memset((char *)state, 0, sizeof(*state)); |
---|
115 | 115 | #endif /* DEBUG */ |
---|
116 | | - kmem_zone_free(xfs_da_state_zone, state); |
---|
| 116 | + kmem_cache_free(xfs_da_state_zone, state); |
---|
| 117 | +} |
---|
| 118 | + |
---|
| 119 | +static inline int xfs_dabuf_nfsb(struct xfs_mount *mp, int whichfork) |
---|
| 120 | +{ |
---|
| 121 | + if (whichfork == XFS_DATA_FORK) |
---|
| 122 | + return mp->m_dir_geo->fsbcount; |
---|
| 123 | + return mp->m_attr_geo->fsbcount; |
---|
| 124 | +} |
---|
| 125 | + |
---|
| 126 | +void |
---|
| 127 | +xfs_da3_node_hdr_from_disk( |
---|
| 128 | + struct xfs_mount *mp, |
---|
| 129 | + struct xfs_da3_icnode_hdr *to, |
---|
| 130 | + struct xfs_da_intnode *from) |
---|
| 131 | +{ |
---|
| 132 | + if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
| 133 | + struct xfs_da3_intnode *from3 = (struct xfs_da3_intnode *)from; |
---|
| 134 | + |
---|
| 135 | + to->forw = be32_to_cpu(from3->hdr.info.hdr.forw); |
---|
| 136 | + to->back = be32_to_cpu(from3->hdr.info.hdr.back); |
---|
| 137 | + to->magic = be16_to_cpu(from3->hdr.info.hdr.magic); |
---|
| 138 | + to->count = be16_to_cpu(from3->hdr.__count); |
---|
| 139 | + to->level = be16_to_cpu(from3->hdr.__level); |
---|
| 140 | + to->btree = from3->__btree; |
---|
| 141 | + ASSERT(to->magic == XFS_DA3_NODE_MAGIC); |
---|
| 142 | + } else { |
---|
| 143 | + to->forw = be32_to_cpu(from->hdr.info.forw); |
---|
| 144 | + to->back = be32_to_cpu(from->hdr.info.back); |
---|
| 145 | + to->magic = be16_to_cpu(from->hdr.info.magic); |
---|
| 146 | + to->count = be16_to_cpu(from->hdr.__count); |
---|
| 147 | + to->level = be16_to_cpu(from->hdr.__level); |
---|
| 148 | + to->btree = from->__btree; |
---|
| 149 | + ASSERT(to->magic == XFS_DA_NODE_MAGIC); |
---|
| 150 | + } |
---|
| 151 | +} |
---|
| 152 | + |
---|
| 153 | +void |
---|
| 154 | +xfs_da3_node_hdr_to_disk( |
---|
| 155 | + struct xfs_mount *mp, |
---|
| 156 | + struct xfs_da_intnode *to, |
---|
| 157 | + struct xfs_da3_icnode_hdr *from) |
---|
| 158 | +{ |
---|
| 159 | + if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
| 160 | + struct xfs_da3_intnode *to3 = (struct xfs_da3_intnode *)to; |
---|
| 161 | + |
---|
| 162 | + ASSERT(from->magic == XFS_DA3_NODE_MAGIC); |
---|
| 163 | + to3->hdr.info.hdr.forw = cpu_to_be32(from->forw); |
---|
| 164 | + to3->hdr.info.hdr.back = cpu_to_be32(from->back); |
---|
| 165 | + to3->hdr.info.hdr.magic = cpu_to_be16(from->magic); |
---|
| 166 | + to3->hdr.__count = cpu_to_be16(from->count); |
---|
| 167 | + to3->hdr.__level = cpu_to_be16(from->level); |
---|
| 168 | + } else { |
---|
| 169 | + ASSERT(from->magic == XFS_DA_NODE_MAGIC); |
---|
| 170 | + to->hdr.info.forw = cpu_to_be32(from->forw); |
---|
| 171 | + to->hdr.info.back = cpu_to_be32(from->back); |
---|
| 172 | + to->hdr.info.magic = cpu_to_be16(from->magic); |
---|
| 173 | + to->hdr.__count = cpu_to_be16(from->count); |
---|
| 174 | + to->hdr.__level = cpu_to_be16(from->level); |
---|
| 175 | + } |
---|
| 176 | +} |
---|
| 177 | + |
---|
| 178 | +/* |
---|
| 179 | + * Verify an xfs_da3_blkinfo structure. Note that the da3 fields are only |
---|
| 180 | + * accessible on v5 filesystems. This header format is common across da node, |
---|
| 181 | + * attr leaf and dir leaf blocks. |
---|
| 182 | + */ |
---|
| 183 | +xfs_failaddr_t |
---|
| 184 | +xfs_da3_blkinfo_verify( |
---|
| 185 | + struct xfs_buf *bp, |
---|
| 186 | + struct xfs_da3_blkinfo *hdr3) |
---|
| 187 | +{ |
---|
| 188 | + struct xfs_mount *mp = bp->b_mount; |
---|
| 189 | + struct xfs_da_blkinfo *hdr = &hdr3->hdr; |
---|
| 190 | + |
---|
| 191 | + if (!xfs_verify_magic16(bp, hdr->magic)) |
---|
| 192 | + return __this_address; |
---|
| 193 | + |
---|
| 194 | + if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
| 195 | + if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
---|
| 196 | + return __this_address; |
---|
| 197 | + if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
---|
| 198 | + return __this_address; |
---|
| 199 | + if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) |
---|
| 200 | + return __this_address; |
---|
| 201 | + } |
---|
| 202 | + |
---|
| 203 | + return NULL; |
---|
117 | 204 | } |
---|
118 | 205 | |
---|
119 | 206 | static xfs_failaddr_t |
---|
120 | 207 | xfs_da3_node_verify( |
---|
121 | 208 | struct xfs_buf *bp) |
---|
122 | 209 | { |
---|
123 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 210 | + struct xfs_mount *mp = bp->b_mount; |
---|
124 | 211 | struct xfs_da_intnode *hdr = bp->b_addr; |
---|
125 | 212 | struct xfs_da3_icnode_hdr ichdr; |
---|
126 | | - const struct xfs_dir_ops *ops; |
---|
| 213 | + xfs_failaddr_t fa; |
---|
127 | 214 | |
---|
128 | | - ops = xfs_dir_get_ops(mp, NULL); |
---|
| 215 | + xfs_da3_node_hdr_from_disk(mp, &ichdr, hdr); |
---|
129 | 216 | |
---|
130 | | - ops->node_hdr_from_disk(&ichdr, hdr); |
---|
| 217 | + fa = xfs_da3_blkinfo_verify(bp, bp->b_addr); |
---|
| 218 | + if (fa) |
---|
| 219 | + return fa; |
---|
131 | 220 | |
---|
132 | | - if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
133 | | - struct xfs_da3_node_hdr *hdr3 = bp->b_addr; |
---|
134 | | - |
---|
135 | | - if (ichdr.magic != XFS_DA3_NODE_MAGIC) |
---|
136 | | - return __this_address; |
---|
137 | | - |
---|
138 | | - if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) |
---|
139 | | - return __this_address; |
---|
140 | | - if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) |
---|
141 | | - return __this_address; |
---|
142 | | - if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->info.lsn))) |
---|
143 | | - return __this_address; |
---|
144 | | - } else { |
---|
145 | | - if (ichdr.magic != XFS_DA_NODE_MAGIC) |
---|
146 | | - return __this_address; |
---|
147 | | - } |
---|
148 | 221 | if (ichdr.level == 0) |
---|
149 | 222 | return __this_address; |
---|
150 | 223 | if (ichdr.level > XFS_DA_NODE_MAXDEPTH) |
---|
.. | .. |
---|
169 | 242 | xfs_da3_node_write_verify( |
---|
170 | 243 | struct xfs_buf *bp) |
---|
171 | 244 | { |
---|
172 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 245 | + struct xfs_mount *mp = bp->b_mount; |
---|
173 | 246 | struct xfs_buf_log_item *bip = bp->b_log_item; |
---|
174 | 247 | struct xfs_da3_node_hdr *hdr3 = bp->b_addr; |
---|
175 | 248 | xfs_failaddr_t fa; |
---|
.. | .. |
---|
257 | 330 | |
---|
258 | 331 | const struct xfs_buf_ops xfs_da3_node_buf_ops = { |
---|
259 | 332 | .name = "xfs_da3_node", |
---|
| 333 | + .magic16 = { cpu_to_be16(XFS_DA_NODE_MAGIC), |
---|
| 334 | + cpu_to_be16(XFS_DA3_NODE_MAGIC) }, |
---|
260 | 335 | .verify_read = xfs_da3_node_read_verify, |
---|
261 | 336 | .verify_write = xfs_da3_node_write_verify, |
---|
262 | 337 | .verify_struct = xfs_da3_node_verify_struct, |
---|
263 | 338 | }; |
---|
| 339 | + |
---|
| 340 | +static int |
---|
| 341 | +xfs_da3_node_set_type( |
---|
| 342 | + struct xfs_trans *tp, |
---|
| 343 | + struct xfs_buf *bp) |
---|
| 344 | +{ |
---|
| 345 | + struct xfs_da_blkinfo *info = bp->b_addr; |
---|
| 346 | + |
---|
| 347 | + switch (be16_to_cpu(info->magic)) { |
---|
| 348 | + case XFS_DA_NODE_MAGIC: |
---|
| 349 | + case XFS_DA3_NODE_MAGIC: |
---|
| 350 | + xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF); |
---|
| 351 | + return 0; |
---|
| 352 | + case XFS_ATTR_LEAF_MAGIC: |
---|
| 353 | + case XFS_ATTR3_LEAF_MAGIC: |
---|
| 354 | + xfs_trans_buf_set_type(tp, bp, XFS_BLFT_ATTR_LEAF_BUF); |
---|
| 355 | + return 0; |
---|
| 356 | + case XFS_DIR2_LEAFN_MAGIC: |
---|
| 357 | + case XFS_DIR3_LEAFN_MAGIC: |
---|
| 358 | + xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAFN_BUF); |
---|
| 359 | + return 0; |
---|
| 360 | + default: |
---|
| 361 | + XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, tp->t_mountp, |
---|
| 362 | + info, sizeof(*info)); |
---|
| 363 | + xfs_trans_brelse(tp, bp); |
---|
| 364 | + return -EFSCORRUPTED; |
---|
| 365 | + } |
---|
| 366 | +} |
---|
264 | 367 | |
---|
265 | 368 | int |
---|
266 | 369 | xfs_da3_node_read( |
---|
267 | 370 | struct xfs_trans *tp, |
---|
268 | 371 | struct xfs_inode *dp, |
---|
269 | 372 | xfs_dablk_t bno, |
---|
| 373 | + struct xfs_buf **bpp, |
---|
| 374 | + int whichfork) |
---|
| 375 | +{ |
---|
| 376 | + int error; |
---|
| 377 | + |
---|
| 378 | + error = xfs_da_read_buf(tp, dp, bno, 0, bpp, whichfork, |
---|
| 379 | + &xfs_da3_node_buf_ops); |
---|
| 380 | + if (error || !*bpp || !tp) |
---|
| 381 | + return error; |
---|
| 382 | + return xfs_da3_node_set_type(tp, *bpp); |
---|
| 383 | +} |
---|
| 384 | + |
---|
| 385 | +int |
---|
| 386 | +xfs_da3_node_read_mapped( |
---|
| 387 | + struct xfs_trans *tp, |
---|
| 388 | + struct xfs_inode *dp, |
---|
270 | 389 | xfs_daddr_t mappedbno, |
---|
271 | 390 | struct xfs_buf **bpp, |
---|
272 | | - int which_fork) |
---|
| 391 | + int whichfork) |
---|
273 | 392 | { |
---|
274 | | - int err; |
---|
| 393 | + struct xfs_mount *mp = dp->i_mount; |
---|
| 394 | + int error; |
---|
275 | 395 | |
---|
276 | | - err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp, |
---|
277 | | - which_fork, &xfs_da3_node_buf_ops); |
---|
278 | | - if (!err && tp && *bpp) { |
---|
279 | | - struct xfs_da_blkinfo *info = (*bpp)->b_addr; |
---|
280 | | - int type; |
---|
| 396 | + error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, mappedbno, |
---|
| 397 | + XFS_FSB_TO_BB(mp, xfs_dabuf_nfsb(mp, whichfork)), 0, |
---|
| 398 | + bpp, &xfs_da3_node_buf_ops); |
---|
| 399 | + if (error || !*bpp) |
---|
| 400 | + return error; |
---|
281 | 401 | |
---|
282 | | - switch (be16_to_cpu(info->magic)) { |
---|
283 | | - case XFS_DA_NODE_MAGIC: |
---|
284 | | - case XFS_DA3_NODE_MAGIC: |
---|
285 | | - type = XFS_BLFT_DA_NODE_BUF; |
---|
286 | | - break; |
---|
287 | | - case XFS_ATTR_LEAF_MAGIC: |
---|
288 | | - case XFS_ATTR3_LEAF_MAGIC: |
---|
289 | | - type = XFS_BLFT_ATTR_LEAF_BUF; |
---|
290 | | - break; |
---|
291 | | - case XFS_DIR2_LEAFN_MAGIC: |
---|
292 | | - case XFS_DIR3_LEAFN_MAGIC: |
---|
293 | | - type = XFS_BLFT_DIR_LEAFN_BUF; |
---|
294 | | - break; |
---|
295 | | - default: |
---|
296 | | - XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, |
---|
297 | | - tp->t_mountp, info, sizeof(*info)); |
---|
298 | | - xfs_trans_brelse(tp, *bpp); |
---|
299 | | - *bpp = NULL; |
---|
300 | | - return -EFSCORRUPTED; |
---|
301 | | - } |
---|
302 | | - xfs_trans_buf_set_type(tp, *bpp, type); |
---|
303 | | - } |
---|
304 | | - return err; |
---|
| 402 | + if (whichfork == XFS_ATTR_FORK) |
---|
| 403 | + xfs_buf_set_ref(*bpp, XFS_ATTR_BTREE_REF); |
---|
| 404 | + else |
---|
| 405 | + xfs_buf_set_ref(*bpp, XFS_DIR_BTREE_REF); |
---|
| 406 | + |
---|
| 407 | + if (!tp) |
---|
| 408 | + return 0; |
---|
| 409 | + return xfs_da3_node_set_type(tp, *bpp); |
---|
305 | 410 | } |
---|
306 | 411 | |
---|
307 | 412 | /*======================================================================== |
---|
.. | .. |
---|
330 | 435 | trace_xfs_da_node_create(args); |
---|
331 | 436 | ASSERT(level <= XFS_DA_NODE_MAXDEPTH); |
---|
332 | 437 | |
---|
333 | | - error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, whichfork); |
---|
| 438 | + error = xfs_da_get_buf(tp, dp, blkno, &bp, whichfork); |
---|
334 | 439 | if (error) |
---|
335 | 440 | return error; |
---|
336 | 441 | bp->b_ops = &xfs_da3_node_buf_ops; |
---|
.. | .. |
---|
350 | 455 | } |
---|
351 | 456 | ichdr.level = level; |
---|
352 | 457 | |
---|
353 | | - dp->d_ops->node_hdr_to_disk(node, &ichdr); |
---|
| 458 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node, &ichdr); |
---|
354 | 459 | xfs_trans_log_buf(tp, bp, |
---|
355 | | - XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); |
---|
| 460 | + XFS_DA_LOGRANGE(node, &node->hdr, args->geo->node_hdr_size)); |
---|
356 | 461 | |
---|
357 | 462 | *bpp = bp; |
---|
358 | 463 | return 0; |
---|
.. | .. |
---|
474 | 579 | ASSERT(state->path.active == 0); |
---|
475 | 580 | oldblk = &state->path.blk[0]; |
---|
476 | 581 | error = xfs_da3_root_split(state, oldblk, addblk); |
---|
477 | | - if (error) { |
---|
478 | | - addblk->bp = NULL; |
---|
479 | | - return error; /* GROT: dir is inconsistent */ |
---|
480 | | - } |
---|
| 582 | + if (error) |
---|
| 583 | + goto out; |
---|
481 | 584 | |
---|
482 | 585 | /* |
---|
483 | 586 | * Update pointers to the node which used to be block 0 and just got |
---|
.. | .. |
---|
492 | 595 | */ |
---|
493 | 596 | node = oldblk->bp->b_addr; |
---|
494 | 597 | if (node->hdr.info.forw) { |
---|
495 | | - ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno); |
---|
| 598 | + if (be32_to_cpu(node->hdr.info.forw) != addblk->blkno) { |
---|
| 599 | + xfs_buf_mark_corrupt(oldblk->bp); |
---|
| 600 | + error = -EFSCORRUPTED; |
---|
| 601 | + goto out; |
---|
| 602 | + } |
---|
496 | 603 | node = addblk->bp->b_addr; |
---|
497 | 604 | node->hdr.info.back = cpu_to_be32(oldblk->blkno); |
---|
498 | 605 | xfs_trans_log_buf(state->args->trans, addblk->bp, |
---|
.. | .. |
---|
501 | 608 | } |
---|
502 | 609 | node = oldblk->bp->b_addr; |
---|
503 | 610 | if (node->hdr.info.back) { |
---|
504 | | - ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno); |
---|
| 611 | + if (be32_to_cpu(node->hdr.info.back) != addblk->blkno) { |
---|
| 612 | + xfs_buf_mark_corrupt(oldblk->bp); |
---|
| 613 | + error = -EFSCORRUPTED; |
---|
| 614 | + goto out; |
---|
| 615 | + } |
---|
505 | 616 | node = addblk->bp->b_addr; |
---|
506 | 617 | node->hdr.info.forw = cpu_to_be32(oldblk->blkno); |
---|
507 | 618 | xfs_trans_log_buf(state->args->trans, addblk->bp, |
---|
508 | 619 | XFS_DA_LOGRANGE(node, &node->hdr.info, |
---|
509 | 620 | sizeof(node->hdr.info))); |
---|
510 | 621 | } |
---|
| 622 | +out: |
---|
511 | 623 | addblk->bp = NULL; |
---|
512 | | - return 0; |
---|
| 624 | + return error; |
---|
513 | 625 | } |
---|
514 | 626 | |
---|
515 | 627 | /* |
---|
.. | .. |
---|
550 | 662 | |
---|
551 | 663 | dp = args->dp; |
---|
552 | 664 | tp = args->trans; |
---|
553 | | - error = xfs_da_get_buf(tp, dp, blkno, -1, &bp, args->whichfork); |
---|
| 665 | + error = xfs_da_get_buf(tp, dp, blkno, &bp, args->whichfork); |
---|
554 | 666 | if (error) |
---|
555 | 667 | return error; |
---|
556 | 668 | node = bp->b_addr; |
---|
.. | .. |
---|
559 | 671 | oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC)) { |
---|
560 | 672 | struct xfs_da3_icnode_hdr icnodehdr; |
---|
561 | 673 | |
---|
562 | | - dp->d_ops->node_hdr_from_disk(&icnodehdr, oldroot); |
---|
563 | | - btree = dp->d_ops->node_tree_p(oldroot); |
---|
| 674 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &icnodehdr, oldroot); |
---|
| 675 | + btree = icnodehdr.btree; |
---|
564 | 676 | size = (int)((char *)&btree[icnodehdr.count] - (char *)oldroot); |
---|
565 | 677 | level = icnodehdr.level; |
---|
566 | 678 | |
---|
.. | .. |
---|
571 | 683 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF); |
---|
572 | 684 | } else { |
---|
573 | 685 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
574 | | - struct xfs_dir2_leaf_entry *ents; |
---|
575 | 686 | |
---|
576 | 687 | leaf = (xfs_dir2_leaf_t *)oldroot; |
---|
577 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
578 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 688 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); |
---|
579 | 689 | |
---|
580 | 690 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || |
---|
581 | 691 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); |
---|
582 | | - size = (int)((char *)&ents[leafhdr.count] - (char *)leaf); |
---|
| 692 | + size = (int)((char *)&leafhdr.ents[leafhdr.count] - |
---|
| 693 | + (char *)leaf); |
---|
583 | 694 | level = 0; |
---|
584 | 695 | |
---|
585 | 696 | /* |
---|
.. | .. |
---|
619 | 730 | return error; |
---|
620 | 731 | |
---|
621 | 732 | node = bp->b_addr; |
---|
622 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
623 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 733 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
| 734 | + btree = nodehdr.btree; |
---|
624 | 735 | btree[0].hashval = cpu_to_be32(blk1->hashval); |
---|
625 | 736 | btree[0].before = cpu_to_be32(blk1->blkno); |
---|
626 | 737 | btree[1].hashval = cpu_to_be32(blk2->hashval); |
---|
627 | 738 | btree[1].before = cpu_to_be32(blk2->blkno); |
---|
628 | 739 | nodehdr.count = 2; |
---|
629 | | - dp->d_ops->node_hdr_to_disk(node, &nodehdr); |
---|
| 740 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr); |
---|
630 | 741 | |
---|
631 | 742 | #ifdef DEBUG |
---|
632 | 743 | if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
---|
.. | .. |
---|
668 | 779 | trace_xfs_da_node_split(state->args); |
---|
669 | 780 | |
---|
670 | 781 | node = oldblk->bp->b_addr; |
---|
671 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
| 782 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
672 | 783 | |
---|
673 | 784 | /* |
---|
674 | 785 | * With V2 dirs the extra block is data or freespace. |
---|
.. | .. |
---|
715 | 826 | * If we had double-split op below us, then add the extra block too. |
---|
716 | 827 | */ |
---|
717 | 828 | node = oldblk->bp->b_addr; |
---|
718 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
| 829 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
719 | 830 | if (oldblk->index <= nodehdr.count) { |
---|
720 | 831 | oldblk->index++; |
---|
721 | 832 | xfs_da3_node_add(state, oldblk, addblk); |
---|
.. | .. |
---|
770 | 881 | |
---|
771 | 882 | node1 = blk1->bp->b_addr; |
---|
772 | 883 | node2 = blk2->bp->b_addr; |
---|
773 | | - dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); |
---|
774 | | - dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); |
---|
775 | | - btree1 = dp->d_ops->node_tree_p(node1); |
---|
776 | | - btree2 = dp->d_ops->node_tree_p(node2); |
---|
| 884 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); |
---|
| 885 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); |
---|
| 886 | + btree1 = nodehdr1.btree; |
---|
| 887 | + btree2 = nodehdr2.btree; |
---|
777 | 888 | |
---|
778 | 889 | /* |
---|
779 | 890 | * Figure out how many entries need to move, and in which direction. |
---|
.. | .. |
---|
786 | 897 | tmpnode = node1; |
---|
787 | 898 | node1 = node2; |
---|
788 | 899 | node2 = tmpnode; |
---|
789 | | - dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); |
---|
790 | | - dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); |
---|
791 | | - btree1 = dp->d_ops->node_tree_p(node1); |
---|
792 | | - btree2 = dp->d_ops->node_tree_p(node2); |
---|
| 900 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); |
---|
| 901 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); |
---|
| 902 | + btree1 = nodehdr1.btree; |
---|
| 903 | + btree2 = nodehdr2.btree; |
---|
793 | 904 | swap = 1; |
---|
794 | 905 | } |
---|
795 | 906 | |
---|
.. | .. |
---|
851 | 962 | /* |
---|
852 | 963 | * Log header of node 1 and all current bits of node 2. |
---|
853 | 964 | */ |
---|
854 | | - dp->d_ops->node_hdr_to_disk(node1, &nodehdr1); |
---|
| 965 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node1, &nodehdr1); |
---|
855 | 966 | xfs_trans_log_buf(tp, blk1->bp, |
---|
856 | | - XFS_DA_LOGRANGE(node1, &node1->hdr, dp->d_ops->node_hdr_size)); |
---|
| 967 | + XFS_DA_LOGRANGE(node1, &node1->hdr, |
---|
| 968 | + state->args->geo->node_hdr_size)); |
---|
857 | 969 | |
---|
858 | | - dp->d_ops->node_hdr_to_disk(node2, &nodehdr2); |
---|
| 970 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node2, &nodehdr2); |
---|
859 | 971 | xfs_trans_log_buf(tp, blk2->bp, |
---|
860 | 972 | XFS_DA_LOGRANGE(node2, &node2->hdr, |
---|
861 | | - dp->d_ops->node_hdr_size + |
---|
| 973 | + state->args->geo->node_hdr_size + |
---|
862 | 974 | (sizeof(btree2[0]) * nodehdr2.count))); |
---|
863 | 975 | |
---|
864 | 976 | /* |
---|
.. | .. |
---|
868 | 980 | if (swap) { |
---|
869 | 981 | node1 = blk1->bp->b_addr; |
---|
870 | 982 | node2 = blk2->bp->b_addr; |
---|
871 | | - dp->d_ops->node_hdr_from_disk(&nodehdr1, node1); |
---|
872 | | - dp->d_ops->node_hdr_from_disk(&nodehdr2, node2); |
---|
873 | | - btree1 = dp->d_ops->node_tree_p(node1); |
---|
874 | | - btree2 = dp->d_ops->node_tree_p(node2); |
---|
| 983 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); |
---|
| 984 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); |
---|
| 985 | + btree1 = nodehdr1.btree; |
---|
| 986 | + btree2 = nodehdr2.btree; |
---|
875 | 987 | } |
---|
876 | 988 | blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval); |
---|
877 | 989 | blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval); |
---|
.. | .. |
---|
903 | 1015 | trace_xfs_da_node_add(state->args); |
---|
904 | 1016 | |
---|
905 | 1017 | node = oldblk->bp->b_addr; |
---|
906 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
907 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1018 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
| 1019 | + btree = nodehdr.btree; |
---|
908 | 1020 | |
---|
909 | 1021 | ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); |
---|
910 | 1022 | ASSERT(newblk->blkno != 0); |
---|
.. | .. |
---|
927 | 1039 | tmp + sizeof(*btree))); |
---|
928 | 1040 | |
---|
929 | 1041 | nodehdr.count += 1; |
---|
930 | | - dp->d_ops->node_hdr_to_disk(node, &nodehdr); |
---|
| 1042 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr); |
---|
931 | 1043 | xfs_trans_log_buf(state->args->trans, oldblk->bp, |
---|
932 | | - XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); |
---|
| 1044 | + XFS_DA_LOGRANGE(node, &node->hdr, |
---|
| 1045 | + state->args->geo->node_hdr_size)); |
---|
933 | 1046 | |
---|
934 | 1047 | /* |
---|
935 | 1048 | * Copy the last hash value from the oldblk to propagate upwards. |
---|
.. | .. |
---|
1064 | 1177 | xfs_dablk_t child; |
---|
1065 | 1178 | struct xfs_buf *bp; |
---|
1066 | 1179 | struct xfs_da3_icnode_hdr oldroothdr; |
---|
1067 | | - struct xfs_da_node_entry *btree; |
---|
1068 | 1180 | int error; |
---|
1069 | 1181 | struct xfs_inode *dp = state->args->dp; |
---|
1070 | 1182 | |
---|
.. | .. |
---|
1074 | 1186 | |
---|
1075 | 1187 | args = state->args; |
---|
1076 | 1188 | oldroot = root_blk->bp->b_addr; |
---|
1077 | | - dp->d_ops->node_hdr_from_disk(&oldroothdr, oldroot); |
---|
| 1189 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &oldroothdr, oldroot); |
---|
1078 | 1190 | ASSERT(oldroothdr.forw == 0); |
---|
1079 | 1191 | ASSERT(oldroothdr.back == 0); |
---|
1080 | 1192 | |
---|
.. | .. |
---|
1088 | 1200 | * Read in the (only) child block, then copy those bytes into |
---|
1089 | 1201 | * the root block's buffer and free the original child block. |
---|
1090 | 1202 | */ |
---|
1091 | | - btree = dp->d_ops->node_tree_p(oldroot); |
---|
1092 | | - child = be32_to_cpu(btree[0].before); |
---|
| 1203 | + child = be32_to_cpu(oldroothdr.btree[0].before); |
---|
1093 | 1204 | ASSERT(child != 0); |
---|
1094 | | - error = xfs_da3_node_read(args->trans, dp, child, -1, &bp, |
---|
1095 | | - args->whichfork); |
---|
| 1205 | + error = xfs_da3_node_read(args->trans, dp, child, &bp, args->whichfork); |
---|
1096 | 1206 | if (error) |
---|
1097 | 1207 | return error; |
---|
1098 | 1208 | xfs_da_blkinfo_onlychild_validate(bp->b_addr, oldroothdr.level); |
---|
.. | .. |
---|
1154 | 1264 | blk = &state->path.blk[ state->path.active-1 ]; |
---|
1155 | 1265 | info = blk->bp->b_addr; |
---|
1156 | 1266 | node = (xfs_da_intnode_t *)info; |
---|
1157 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
| 1267 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
1158 | 1268 | if (nodehdr.count > (state->args->geo->node_ents >> 1)) { |
---|
1159 | 1269 | *action = 0; /* blk over 50%, don't try to join */ |
---|
1160 | 1270 | return 0; /* blk over 50%, don't try to join */ |
---|
.. | .. |
---|
1206 | 1316 | blkno = nodehdr.back; |
---|
1207 | 1317 | if (blkno == 0) |
---|
1208 | 1318 | continue; |
---|
1209 | | - error = xfs_da3_node_read(state->args->trans, dp, |
---|
1210 | | - blkno, -1, &bp, state->args->whichfork); |
---|
| 1319 | + error = xfs_da3_node_read(state->args->trans, dp, blkno, &bp, |
---|
| 1320 | + state->args->whichfork); |
---|
1211 | 1321 | if (error) |
---|
1212 | 1322 | return error; |
---|
1213 | 1323 | |
---|
1214 | 1324 | node = bp->b_addr; |
---|
1215 | | - dp->d_ops->node_hdr_from_disk(&thdr, node); |
---|
| 1325 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &thdr, node); |
---|
1216 | 1326 | xfs_trans_brelse(state->args->trans, bp); |
---|
1217 | 1327 | |
---|
1218 | 1328 | if (count - thdr.count >= 0) |
---|
.. | .. |
---|
1254 | 1364 | struct xfs_buf *bp, |
---|
1255 | 1365 | int *count) |
---|
1256 | 1366 | { |
---|
1257 | | - struct xfs_da_intnode *node; |
---|
1258 | | - struct xfs_da_node_entry *btree; |
---|
1259 | 1367 | struct xfs_da3_icnode_hdr nodehdr; |
---|
1260 | 1368 | |
---|
1261 | | - node = bp->b_addr; |
---|
1262 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
| 1369 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, bp->b_addr); |
---|
1263 | 1370 | if (count) |
---|
1264 | 1371 | *count = nodehdr.count; |
---|
1265 | 1372 | if (!nodehdr.count) |
---|
1266 | 1373 | return 0; |
---|
1267 | | - btree = dp->d_ops->node_tree_p(node); |
---|
1268 | | - return be32_to_cpu(btree[nodehdr.count - 1].hashval); |
---|
| 1374 | + return be32_to_cpu(nodehdr.btree[nodehdr.count - 1].hashval); |
---|
1269 | 1375 | } |
---|
1270 | 1376 | |
---|
1271 | 1377 | /* |
---|
.. | .. |
---|
1310 | 1416 | struct xfs_da3_icnode_hdr nodehdr; |
---|
1311 | 1417 | |
---|
1312 | 1418 | node = blk->bp->b_addr; |
---|
1313 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
1314 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1419 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
| 1420 | + btree = nodehdr.btree; |
---|
1315 | 1421 | if (be32_to_cpu(btree[blk->index].hashval) == lasthash) |
---|
1316 | 1422 | break; |
---|
1317 | 1423 | blk->hashval = lasthash; |
---|
.. | .. |
---|
1342 | 1448 | trace_xfs_da_node_remove(state->args); |
---|
1343 | 1449 | |
---|
1344 | 1450 | node = drop_blk->bp->b_addr; |
---|
1345 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
| 1451 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
1346 | 1452 | ASSERT(drop_blk->index < nodehdr.count); |
---|
1347 | 1453 | ASSERT(drop_blk->index >= 0); |
---|
1348 | 1454 | |
---|
.. | .. |
---|
1350 | 1456 | * Copy over the offending entry, or just zero it out. |
---|
1351 | 1457 | */ |
---|
1352 | 1458 | index = drop_blk->index; |
---|
1353 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1459 | + btree = nodehdr.btree; |
---|
1354 | 1460 | if (index < nodehdr.count - 1) { |
---|
1355 | 1461 | tmp = nodehdr.count - index - 1; |
---|
1356 | 1462 | tmp *= (uint)sizeof(xfs_da_node_entry_t); |
---|
.. | .. |
---|
1363 | 1469 | xfs_trans_log_buf(state->args->trans, drop_blk->bp, |
---|
1364 | 1470 | XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); |
---|
1365 | 1471 | nodehdr.count -= 1; |
---|
1366 | | - dp->d_ops->node_hdr_to_disk(node, &nodehdr); |
---|
| 1472 | + xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr); |
---|
1367 | 1473 | xfs_trans_log_buf(state->args->trans, drop_blk->bp, |
---|
1368 | | - XFS_DA_LOGRANGE(node, &node->hdr, dp->d_ops->node_hdr_size)); |
---|
| 1474 | + XFS_DA_LOGRANGE(node, &node->hdr, state->args->geo->node_hdr_size)); |
---|
1369 | 1475 | |
---|
1370 | 1476 | /* |
---|
1371 | 1477 | * Copy the last hash value from the block to propagate upwards. |
---|
.. | .. |
---|
1398 | 1504 | |
---|
1399 | 1505 | drop_node = drop_blk->bp->b_addr; |
---|
1400 | 1506 | save_node = save_blk->bp->b_addr; |
---|
1401 | | - dp->d_ops->node_hdr_from_disk(&drop_hdr, drop_node); |
---|
1402 | | - dp->d_ops->node_hdr_from_disk(&save_hdr, save_node); |
---|
1403 | | - drop_btree = dp->d_ops->node_tree_p(drop_node); |
---|
1404 | | - save_btree = dp->d_ops->node_tree_p(save_node); |
---|
| 1507 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &drop_hdr, drop_node); |
---|
| 1508 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &save_hdr, save_node); |
---|
| 1509 | + drop_btree = drop_hdr.btree; |
---|
| 1510 | + save_btree = save_hdr.btree; |
---|
1405 | 1511 | tp = state->args->trans; |
---|
1406 | 1512 | |
---|
1407 | 1513 | /* |
---|
.. | .. |
---|
1435 | 1541 | memcpy(&save_btree[sindex], &drop_btree[0], tmp); |
---|
1436 | 1542 | save_hdr.count += drop_hdr.count; |
---|
1437 | 1543 | |
---|
1438 | | - dp->d_ops->node_hdr_to_disk(save_node, &save_hdr); |
---|
| 1544 | + xfs_da3_node_hdr_to_disk(dp->i_mount, save_node, &save_hdr); |
---|
1439 | 1545 | xfs_trans_log_buf(tp, save_blk->bp, |
---|
1440 | 1546 | XFS_DA_LOGRANGE(save_node, &save_node->hdr, |
---|
1441 | | - dp->d_ops->node_hdr_size)); |
---|
| 1547 | + state->args->geo->node_hdr_size)); |
---|
1442 | 1548 | |
---|
1443 | 1549 | /* |
---|
1444 | 1550 | * Save the last hashval in the remaining block for upward propagation. |
---|
.. | .. |
---|
1499 | 1605 | */ |
---|
1500 | 1606 | blk->blkno = blkno; |
---|
1501 | 1607 | error = xfs_da3_node_read(args->trans, args->dp, blkno, |
---|
1502 | | - -1, &blk->bp, args->whichfork); |
---|
| 1608 | + &blk->bp, args->whichfork); |
---|
1503 | 1609 | if (error) { |
---|
1504 | 1610 | blk->blkno = 0; |
---|
1505 | 1611 | state->path.active--; |
---|
.. | .. |
---|
1523 | 1629 | break; |
---|
1524 | 1630 | } |
---|
1525 | 1631 | |
---|
1526 | | - if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) |
---|
| 1632 | + if (magic != XFS_DA_NODE_MAGIC && magic != XFS_DA3_NODE_MAGIC) { |
---|
| 1633 | + xfs_buf_mark_corrupt(blk->bp); |
---|
1527 | 1634 | return -EFSCORRUPTED; |
---|
| 1635 | + } |
---|
1528 | 1636 | |
---|
1529 | 1637 | blk->magic = XFS_DA_NODE_MAGIC; |
---|
1530 | 1638 | |
---|
.. | .. |
---|
1532 | 1640 | * Search an intermediate node for a match. |
---|
1533 | 1641 | */ |
---|
1534 | 1642 | node = blk->bp->b_addr; |
---|
1535 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
1536 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1643 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); |
---|
| 1644 | + btree = nodehdr.btree; |
---|
1537 | 1645 | |
---|
1538 | 1646 | /* Tree taller than we can handle; bail out! */ |
---|
1539 | | - if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) |
---|
| 1647 | + if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) { |
---|
| 1648 | + xfs_buf_mark_corrupt(blk->bp); |
---|
1540 | 1649 | return -EFSCORRUPTED; |
---|
| 1650 | + } |
---|
1541 | 1651 | |
---|
1542 | 1652 | /* Check the level from the root. */ |
---|
1543 | 1653 | if (blkno == args->geo->leafblk) |
---|
1544 | 1654 | expected_level = nodehdr.level - 1; |
---|
1545 | | - else if (expected_level != nodehdr.level) |
---|
| 1655 | + else if (expected_level != nodehdr.level) { |
---|
| 1656 | + xfs_buf_mark_corrupt(blk->bp); |
---|
1546 | 1657 | return -EFSCORRUPTED; |
---|
1547 | | - else |
---|
| 1658 | + } else |
---|
1548 | 1659 | expected_level--; |
---|
1549 | 1660 | |
---|
1550 | 1661 | max = nodehdr.count; |
---|
.. | .. |
---|
1594 | 1705 | } |
---|
1595 | 1706 | |
---|
1596 | 1707 | /* We can't point back to the root. */ |
---|
1597 | | - if (blkno == args->geo->leafblk) |
---|
| 1708 | + if (XFS_IS_CORRUPT(dp->i_mount, blkno == args->geo->leafblk)) |
---|
1598 | 1709 | return -EFSCORRUPTED; |
---|
1599 | 1710 | } |
---|
1600 | 1711 | |
---|
1601 | | - if (expected_level != 0) |
---|
| 1712 | + if (XFS_IS_CORRUPT(dp->i_mount, expected_level != 0)) |
---|
1602 | 1713 | return -EFSCORRUPTED; |
---|
1603 | 1714 | |
---|
1604 | 1715 | /* |
---|
.. | .. |
---|
1660 | 1771 | |
---|
1661 | 1772 | node1 = node1_bp->b_addr; |
---|
1662 | 1773 | node2 = node2_bp->b_addr; |
---|
1663 | | - dp->d_ops->node_hdr_from_disk(&node1hdr, node1); |
---|
1664 | | - dp->d_ops->node_hdr_from_disk(&node2hdr, node2); |
---|
1665 | | - btree1 = dp->d_ops->node_tree_p(node1); |
---|
1666 | | - btree2 = dp->d_ops->node_tree_p(node2); |
---|
| 1774 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &node1hdr, node1); |
---|
| 1775 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &node2hdr, node2); |
---|
| 1776 | + btree1 = node1hdr.btree; |
---|
| 1777 | + btree2 = node2hdr.btree; |
---|
1667 | 1778 | |
---|
1668 | 1779 | if (node1hdr.count > 0 && node2hdr.count > 0 && |
---|
1669 | 1780 | ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || |
---|
.. | .. |
---|
1728 | 1839 | if (old_info->back) { |
---|
1729 | 1840 | error = xfs_da3_node_read(args->trans, dp, |
---|
1730 | 1841 | be32_to_cpu(old_info->back), |
---|
1731 | | - -1, &bp, args->whichfork); |
---|
| 1842 | + &bp, args->whichfork); |
---|
1732 | 1843 | if (error) |
---|
1733 | 1844 | return error; |
---|
1734 | 1845 | ASSERT(bp != NULL); |
---|
.. | .. |
---|
1749 | 1860 | if (old_info->forw) { |
---|
1750 | 1861 | error = xfs_da3_node_read(args->trans, dp, |
---|
1751 | 1862 | be32_to_cpu(old_info->forw), |
---|
1752 | | - -1, &bp, args->whichfork); |
---|
| 1863 | + &bp, args->whichfork); |
---|
1753 | 1864 | if (error) |
---|
1754 | 1865 | return error; |
---|
1755 | 1866 | ASSERT(bp != NULL); |
---|
.. | .. |
---|
1808 | 1919 | if (drop_info->back) { |
---|
1809 | 1920 | error = xfs_da3_node_read(args->trans, args->dp, |
---|
1810 | 1921 | be32_to_cpu(drop_info->back), |
---|
1811 | | - -1, &bp, args->whichfork); |
---|
| 1922 | + &bp, args->whichfork); |
---|
1812 | 1923 | if (error) |
---|
1813 | 1924 | return error; |
---|
1814 | 1925 | ASSERT(bp != NULL); |
---|
.. | .. |
---|
1825 | 1936 | if (drop_info->forw) { |
---|
1826 | 1937 | error = xfs_da3_node_read(args->trans, args->dp, |
---|
1827 | 1938 | be32_to_cpu(drop_info->forw), |
---|
1828 | | - -1, &bp, args->whichfork); |
---|
| 1939 | + &bp, args->whichfork); |
---|
1829 | 1940 | if (error) |
---|
1830 | 1941 | return error; |
---|
1831 | 1942 | ASSERT(bp != NULL); |
---|
.. | .. |
---|
1860 | 1971 | { |
---|
1861 | 1972 | struct xfs_da_state_blk *blk; |
---|
1862 | 1973 | struct xfs_da_blkinfo *info; |
---|
1863 | | - struct xfs_da_intnode *node; |
---|
1864 | 1974 | struct xfs_da_args *args; |
---|
1865 | 1975 | struct xfs_da_node_entry *btree; |
---|
1866 | 1976 | struct xfs_da3_icnode_hdr nodehdr; |
---|
.. | .. |
---|
1882 | 1992 | ASSERT(path != NULL); |
---|
1883 | 1993 | ASSERT((path->active > 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); |
---|
1884 | 1994 | level = (path->active-1) - 1; /* skip bottom layer in path */ |
---|
1885 | | - for (blk = &path->blk[level]; level >= 0; blk--, level--) { |
---|
1886 | | - node = blk->bp->b_addr; |
---|
1887 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
1888 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 1995 | + for (; level >= 0; level--) { |
---|
| 1996 | + blk = &path->blk[level]; |
---|
| 1997 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, |
---|
| 1998 | + blk->bp->b_addr); |
---|
1889 | 1999 | |
---|
1890 | 2000 | if (forward && (blk->index < nodehdr.count - 1)) { |
---|
1891 | 2001 | blk->index++; |
---|
1892 | | - blkno = be32_to_cpu(btree[blk->index].before); |
---|
| 2002 | + blkno = be32_to_cpu(nodehdr.btree[blk->index].before); |
---|
1893 | 2003 | break; |
---|
1894 | 2004 | } else if (!forward && (blk->index > 0)) { |
---|
1895 | 2005 | blk->index--; |
---|
1896 | | - blkno = be32_to_cpu(btree[blk->index].before); |
---|
| 2006 | + blkno = be32_to_cpu(nodehdr.btree[blk->index].before); |
---|
1897 | 2007 | break; |
---|
1898 | 2008 | } |
---|
1899 | 2009 | } |
---|
.. | .. |
---|
1911 | 2021 | /* |
---|
1912 | 2022 | * Read the next child block into a local buffer. |
---|
1913 | 2023 | */ |
---|
1914 | | - error = xfs_da3_node_read(args->trans, dp, blkno, -1, &bp, |
---|
| 2024 | + error = xfs_da3_node_read(args->trans, dp, blkno, &bp, |
---|
1915 | 2025 | args->whichfork); |
---|
1916 | 2026 | if (error) |
---|
1917 | 2027 | return error; |
---|
.. | .. |
---|
1944 | 2054 | case XFS_DA_NODE_MAGIC: |
---|
1945 | 2055 | case XFS_DA3_NODE_MAGIC: |
---|
1946 | 2056 | blk->magic = XFS_DA_NODE_MAGIC; |
---|
1947 | | - node = (xfs_da_intnode_t *)info; |
---|
1948 | | - dp->d_ops->node_hdr_from_disk(&nodehdr, node); |
---|
1949 | | - btree = dp->d_ops->node_tree_p(node); |
---|
| 2057 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, |
---|
| 2058 | + bp->b_addr); |
---|
| 2059 | + btree = nodehdr.btree; |
---|
1950 | 2060 | blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); |
---|
1951 | 2061 | if (forward) |
---|
1952 | 2062 | blk->index = 0; |
---|
.. | .. |
---|
2026 | 2136 | XFS_CMP_EXACT : XFS_CMP_DIFFERENT; |
---|
2027 | 2137 | } |
---|
2028 | 2138 | |
---|
2029 | | -static xfs_dahash_t |
---|
2030 | | -xfs_default_hashname( |
---|
2031 | | - struct xfs_name *name) |
---|
2032 | | -{ |
---|
2033 | | - return xfs_da_hashname(name->name, name->len); |
---|
2034 | | -} |
---|
2035 | | - |
---|
2036 | | -const struct xfs_nameops xfs_default_nameops = { |
---|
2037 | | - .hashname = xfs_default_hashname, |
---|
2038 | | - .compname = xfs_da_compname |
---|
2039 | | -}; |
---|
2040 | | - |
---|
2041 | 2139 | int |
---|
2042 | 2140 | xfs_da_grow_inode_int( |
---|
2043 | 2141 | struct xfs_da_args *args, |
---|
.. | .. |
---|
2080 | 2178 | * If we didn't get it and the block might work if fragmented, |
---|
2081 | 2179 | * try without the CONTIG flag. Loop until we get it all. |
---|
2082 | 2180 | */ |
---|
2083 | | - mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); |
---|
| 2181 | + mapp = kmem_alloc(sizeof(*mapp) * count, 0); |
---|
2084 | 2182 | for (b = *bno, mapi = 0; b < *bno + count; ) { |
---|
2085 | 2183 | nmap = min(XFS_BMAP_MAX_NMAP, count); |
---|
2086 | 2184 | c = (int)(*bno + count - b); |
---|
.. | .. |
---|
2195 | 2293 | error = xfs_bmap_last_before(tp, dp, &lastoff, w); |
---|
2196 | 2294 | if (error) |
---|
2197 | 2295 | return error; |
---|
2198 | | - if (unlikely(lastoff == 0)) { |
---|
2199 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW, |
---|
2200 | | - mp); |
---|
| 2296 | + if (XFS_IS_CORRUPT(mp, lastoff == 0)) |
---|
2201 | 2297 | return -EFSCORRUPTED; |
---|
2202 | | - } |
---|
2203 | 2298 | /* |
---|
2204 | 2299 | * Read the last block in the btree space. |
---|
2205 | 2300 | */ |
---|
2206 | 2301 | last_blkno = (xfs_dablk_t)lastoff - args->geo->fsbcount; |
---|
2207 | | - error = xfs_da3_node_read(tp, dp, last_blkno, -1, &last_buf, w); |
---|
| 2302 | + error = xfs_da3_node_read(tp, dp, last_blkno, &last_buf, w); |
---|
2208 | 2303 | if (error) |
---|
2209 | 2304 | return error; |
---|
2210 | 2305 | /* |
---|
.. | .. |
---|
2222 | 2317 | struct xfs_dir2_leaf_entry *ents; |
---|
2223 | 2318 | |
---|
2224 | 2319 | dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; |
---|
2225 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, dead_leaf2); |
---|
2226 | | - ents = dp->d_ops->leaf_ents_p(dead_leaf2); |
---|
| 2320 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, |
---|
| 2321 | + dead_leaf2); |
---|
| 2322 | + ents = leafhdr.ents; |
---|
2227 | 2323 | dead_level = 0; |
---|
2228 | 2324 | dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); |
---|
2229 | 2325 | } else { |
---|
2230 | 2326 | struct xfs_da3_icnode_hdr deadhdr; |
---|
2231 | 2327 | |
---|
2232 | 2328 | dead_node = (xfs_da_intnode_t *)dead_info; |
---|
2233 | | - dp->d_ops->node_hdr_from_disk(&deadhdr, dead_node); |
---|
2234 | | - btree = dp->d_ops->node_tree_p(dead_node); |
---|
| 2329 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &deadhdr, dead_node); |
---|
| 2330 | + btree = deadhdr.btree; |
---|
2235 | 2331 | dead_level = deadhdr.level; |
---|
2236 | 2332 | dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); |
---|
2237 | 2333 | } |
---|
.. | .. |
---|
2240 | 2336 | * If the moved block has a left sibling, fix up the pointers. |
---|
2241 | 2337 | */ |
---|
2242 | 2338 | if ((sib_blkno = be32_to_cpu(dead_info->back))) { |
---|
2243 | | - error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); |
---|
| 2339 | + error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w); |
---|
2244 | 2340 | if (error) |
---|
2245 | 2341 | goto done; |
---|
2246 | 2342 | sib_info = sib_buf->b_addr; |
---|
2247 | | - if (unlikely( |
---|
2248 | | - be32_to_cpu(sib_info->forw) != last_blkno || |
---|
2249 | | - sib_info->magic != dead_info->magic)) { |
---|
2250 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)", |
---|
2251 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2343 | + if (XFS_IS_CORRUPT(mp, |
---|
| 2344 | + be32_to_cpu(sib_info->forw) != last_blkno || |
---|
| 2345 | + sib_info->magic != dead_info->magic)) { |
---|
2252 | 2346 | error = -EFSCORRUPTED; |
---|
2253 | 2347 | goto done; |
---|
2254 | 2348 | } |
---|
.. | .. |
---|
2262 | 2356 | * If the moved block has a right sibling, fix up the pointers. |
---|
2263 | 2357 | */ |
---|
2264 | 2358 | if ((sib_blkno = be32_to_cpu(dead_info->forw))) { |
---|
2265 | | - error = xfs_da3_node_read(tp, dp, sib_blkno, -1, &sib_buf, w); |
---|
| 2359 | + error = xfs_da3_node_read(tp, dp, sib_blkno, &sib_buf, w); |
---|
2266 | 2360 | if (error) |
---|
2267 | 2361 | goto done; |
---|
2268 | 2362 | sib_info = sib_buf->b_addr; |
---|
2269 | | - if (unlikely( |
---|
2270 | | - be32_to_cpu(sib_info->back) != last_blkno || |
---|
2271 | | - sib_info->magic != dead_info->magic)) { |
---|
2272 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)", |
---|
2273 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2363 | + if (XFS_IS_CORRUPT(mp, |
---|
| 2364 | + be32_to_cpu(sib_info->back) != last_blkno || |
---|
| 2365 | + sib_info->magic != dead_info->magic)) { |
---|
2274 | 2366 | error = -EFSCORRUPTED; |
---|
2275 | 2367 | goto done; |
---|
2276 | 2368 | } |
---|
.. | .. |
---|
2286 | 2378 | * Walk down the tree looking for the parent of the moved block. |
---|
2287 | 2379 | */ |
---|
2288 | 2380 | for (;;) { |
---|
2289 | | - error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); |
---|
| 2381 | + error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w); |
---|
2290 | 2382 | if (error) |
---|
2291 | 2383 | goto done; |
---|
2292 | 2384 | par_node = par_buf->b_addr; |
---|
2293 | | - dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); |
---|
2294 | | - if (level >= 0 && level != par_hdr.level + 1) { |
---|
2295 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", |
---|
2296 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2385 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); |
---|
| 2386 | + if (XFS_IS_CORRUPT(mp, |
---|
| 2387 | + level >= 0 && level != par_hdr.level + 1)) { |
---|
2297 | 2388 | error = -EFSCORRUPTED; |
---|
2298 | 2389 | goto done; |
---|
2299 | 2390 | } |
---|
2300 | 2391 | level = par_hdr.level; |
---|
2301 | | - btree = dp->d_ops->node_tree_p(par_node); |
---|
| 2392 | + btree = par_hdr.btree; |
---|
2302 | 2393 | for (entno = 0; |
---|
2303 | 2394 | entno < par_hdr.count && |
---|
2304 | 2395 | be32_to_cpu(btree[entno].hashval) < dead_hash; |
---|
2305 | 2396 | entno++) |
---|
2306 | 2397 | continue; |
---|
2307 | | - if (entno == par_hdr.count) { |
---|
2308 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)", |
---|
2309 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2398 | + if (XFS_IS_CORRUPT(mp, entno == par_hdr.count)) { |
---|
2310 | 2399 | error = -EFSCORRUPTED; |
---|
2311 | 2400 | goto done; |
---|
2312 | 2401 | } |
---|
.. | .. |
---|
2331 | 2420 | par_blkno = par_hdr.forw; |
---|
2332 | 2421 | xfs_trans_brelse(tp, par_buf); |
---|
2333 | 2422 | par_buf = NULL; |
---|
2334 | | - if (unlikely(par_blkno == 0)) { |
---|
2335 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)", |
---|
2336 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2423 | + if (XFS_IS_CORRUPT(mp, par_blkno == 0)) { |
---|
2337 | 2424 | error = -EFSCORRUPTED; |
---|
2338 | 2425 | goto done; |
---|
2339 | 2426 | } |
---|
2340 | | - error = xfs_da3_node_read(tp, dp, par_blkno, -1, &par_buf, w); |
---|
| 2427 | + error = xfs_da3_node_read(tp, dp, par_blkno, &par_buf, w); |
---|
2341 | 2428 | if (error) |
---|
2342 | 2429 | goto done; |
---|
2343 | 2430 | par_node = par_buf->b_addr; |
---|
2344 | | - dp->d_ops->node_hdr_from_disk(&par_hdr, par_node); |
---|
2345 | | - if (par_hdr.level != level) { |
---|
2346 | | - XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", |
---|
2347 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2431 | + xfs_da3_node_hdr_from_disk(dp->i_mount, &par_hdr, par_node); |
---|
| 2432 | + if (XFS_IS_CORRUPT(mp, par_hdr.level != level)) { |
---|
2348 | 2433 | error = -EFSCORRUPTED; |
---|
2349 | 2434 | goto done; |
---|
2350 | 2435 | } |
---|
2351 | | - btree = dp->d_ops->node_tree_p(par_node); |
---|
| 2436 | + btree = par_hdr.btree; |
---|
2352 | 2437 | entno = 0; |
---|
2353 | 2438 | } |
---|
2354 | 2439 | /* |
---|
.. | .. |
---|
2411 | 2496 | return error; |
---|
2412 | 2497 | } |
---|
2413 | 2498 | |
---|
2414 | | -/* |
---|
2415 | | - * See if the mapping(s) for this btree block are valid, i.e. |
---|
2416 | | - * don't contain holes, are logically contiguous, and cover the whole range. |
---|
2417 | | - */ |
---|
2418 | | -STATIC int |
---|
2419 | | -xfs_da_map_covers_blocks( |
---|
2420 | | - int nmap, |
---|
2421 | | - xfs_bmbt_irec_t *mapp, |
---|
2422 | | - xfs_dablk_t bno, |
---|
2423 | | - int count) |
---|
2424 | | -{ |
---|
2425 | | - int i; |
---|
2426 | | - xfs_fileoff_t off; |
---|
2427 | | - |
---|
2428 | | - for (i = 0, off = bno; i < nmap; i++) { |
---|
2429 | | - if (mapp[i].br_startblock == HOLESTARTBLOCK || |
---|
2430 | | - mapp[i].br_startblock == DELAYSTARTBLOCK) { |
---|
2431 | | - return 0; |
---|
2432 | | - } |
---|
2433 | | - if (off != mapp[i].br_startoff) { |
---|
2434 | | - return 0; |
---|
2435 | | - } |
---|
2436 | | - off += mapp[i].br_blockcount; |
---|
2437 | | - } |
---|
2438 | | - return off == bno + count; |
---|
2439 | | -} |
---|
2440 | | - |
---|
2441 | | -/* |
---|
2442 | | - * Convert a struct xfs_bmbt_irec to a struct xfs_buf_map. |
---|
2443 | | - * |
---|
2444 | | - * For the single map case, it is assumed that the caller has provided a pointer |
---|
2445 | | - * to a valid xfs_buf_map. For the multiple map case, this function will |
---|
2446 | | - * allocate the xfs_buf_map to hold all the maps and replace the caller's single |
---|
2447 | | - * map pointer with the allocated map. |
---|
2448 | | - */ |
---|
2449 | | -static int |
---|
2450 | | -xfs_buf_map_from_irec( |
---|
2451 | | - struct xfs_mount *mp, |
---|
2452 | | - struct xfs_buf_map **mapp, |
---|
2453 | | - int *nmaps, |
---|
2454 | | - struct xfs_bmbt_irec *irecs, |
---|
2455 | | - int nirecs) |
---|
2456 | | -{ |
---|
2457 | | - struct xfs_buf_map *map; |
---|
2458 | | - int i; |
---|
2459 | | - |
---|
2460 | | - ASSERT(*nmaps == 1); |
---|
2461 | | - ASSERT(nirecs >= 1); |
---|
2462 | | - |
---|
2463 | | - if (nirecs > 1) { |
---|
2464 | | - map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), |
---|
2465 | | - KM_SLEEP | KM_NOFS); |
---|
2466 | | - if (!map) |
---|
2467 | | - return -ENOMEM; |
---|
2468 | | - *mapp = map; |
---|
2469 | | - } |
---|
2470 | | - |
---|
2471 | | - *nmaps = nirecs; |
---|
2472 | | - map = *mapp; |
---|
2473 | | - for (i = 0; i < *nmaps; i++) { |
---|
2474 | | - ASSERT(irecs[i].br_startblock != DELAYSTARTBLOCK && |
---|
2475 | | - irecs[i].br_startblock != HOLESTARTBLOCK); |
---|
2476 | | - map[i].bm_bn = XFS_FSB_TO_DADDR(mp, irecs[i].br_startblock); |
---|
2477 | | - map[i].bm_len = XFS_FSB_TO_BB(mp, irecs[i].br_blockcount); |
---|
2478 | | - } |
---|
2479 | | - return 0; |
---|
2480 | | -} |
---|
2481 | | - |
---|
2482 | | -/* |
---|
2483 | | - * Map the block we are given ready for reading. There are three possible return |
---|
2484 | | - * values: |
---|
2485 | | - * -1 - will be returned if we land in a hole and mappedbno == -2 so the |
---|
2486 | | - * caller knows not to execute a subsequent read. |
---|
2487 | | - * 0 - if we mapped the block successfully |
---|
2488 | | - * >0 - positive error number if there was an error. |
---|
2489 | | - */ |
---|
2490 | 2499 | static int |
---|
2491 | 2500 | xfs_dabuf_map( |
---|
2492 | 2501 | struct xfs_inode *dp, |
---|
2493 | 2502 | xfs_dablk_t bno, |
---|
2494 | | - xfs_daddr_t mappedbno, |
---|
| 2503 | + unsigned int flags, |
---|
2495 | 2504 | int whichfork, |
---|
2496 | | - struct xfs_buf_map **map, |
---|
| 2505 | + struct xfs_buf_map **mapp, |
---|
2497 | 2506 | int *nmaps) |
---|
2498 | 2507 | { |
---|
2499 | 2508 | struct xfs_mount *mp = dp->i_mount; |
---|
2500 | | - int nfsb; |
---|
2501 | | - int error = 0; |
---|
2502 | | - struct xfs_bmbt_irec irec; |
---|
2503 | | - struct xfs_bmbt_irec *irecs = &irec; |
---|
2504 | | - int nirecs; |
---|
| 2509 | + int nfsb = xfs_dabuf_nfsb(mp, whichfork); |
---|
| 2510 | + struct xfs_bmbt_irec irec, *irecs = &irec; |
---|
| 2511 | + struct xfs_buf_map *map = *mapp; |
---|
| 2512 | + xfs_fileoff_t off = bno; |
---|
| 2513 | + int error = 0, nirecs, i; |
---|
2505 | 2514 | |
---|
2506 | | - ASSERT(map && *map); |
---|
2507 | | - ASSERT(*nmaps == 1); |
---|
| 2515 | + if (nfsb > 1) |
---|
| 2516 | + irecs = kmem_zalloc(sizeof(irec) * nfsb, KM_NOFS); |
---|
2508 | 2517 | |
---|
2509 | | - if (whichfork == XFS_DATA_FORK) |
---|
2510 | | - nfsb = mp->m_dir_geo->fsbcount; |
---|
2511 | | - else |
---|
2512 | | - nfsb = mp->m_attr_geo->fsbcount; |
---|
| 2518 | + nirecs = nfsb; |
---|
| 2519 | + error = xfs_bmapi_read(dp, bno, nfsb, irecs, &nirecs, |
---|
| 2520 | + xfs_bmapi_aflag(whichfork)); |
---|
| 2521 | + if (error) |
---|
| 2522 | + goto out_free_irecs; |
---|
2513 | 2523 | |
---|
2514 | 2524 | /* |
---|
2515 | | - * Caller doesn't have a mapping. -2 means don't complain |
---|
2516 | | - * if we land in a hole. |
---|
| 2525 | + * Use the caller provided map for the single map case, else allocate a |
---|
| 2526 | + * larger one that needs to be free by the caller. |
---|
2517 | 2527 | */ |
---|
2518 | | - if (mappedbno == -1 || mappedbno == -2) { |
---|
2519 | | - /* |
---|
2520 | | - * Optimize the one-block case. |
---|
2521 | | - */ |
---|
2522 | | - if (nfsb != 1) |
---|
2523 | | - irecs = kmem_zalloc(sizeof(irec) * nfsb, |
---|
2524 | | - KM_SLEEP | KM_NOFS); |
---|
2525 | | - |
---|
2526 | | - nirecs = nfsb; |
---|
2527 | | - error = xfs_bmapi_read(dp, (xfs_fileoff_t)bno, nfsb, irecs, |
---|
2528 | | - &nirecs, xfs_bmapi_aflag(whichfork)); |
---|
2529 | | - if (error) |
---|
2530 | | - goto out; |
---|
2531 | | - } else { |
---|
2532 | | - irecs->br_startblock = XFS_DADDR_TO_FSB(mp, mappedbno); |
---|
2533 | | - irecs->br_startoff = (xfs_fileoff_t)bno; |
---|
2534 | | - irecs->br_blockcount = nfsb; |
---|
2535 | | - irecs->br_state = 0; |
---|
2536 | | - nirecs = 1; |
---|
2537 | | - } |
---|
2538 | | - |
---|
2539 | | - if (!xfs_da_map_covers_blocks(nirecs, irecs, bno, nfsb)) { |
---|
2540 | | - error = mappedbno == -2 ? -1 : -EFSCORRUPTED; |
---|
2541 | | - if (unlikely(error == -EFSCORRUPTED)) { |
---|
2542 | | - if (xfs_error_level >= XFS_ERRLEVEL_LOW) { |
---|
2543 | | - int i; |
---|
2544 | | - xfs_alert(mp, "%s: bno %lld dir: inode %lld", |
---|
2545 | | - __func__, (long long)bno, |
---|
2546 | | - (long long)dp->i_ino); |
---|
2547 | | - for (i = 0; i < *nmaps; i++) { |
---|
2548 | | - xfs_alert(mp, |
---|
2549 | | -"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", |
---|
2550 | | - i, |
---|
2551 | | - (long long)irecs[i].br_startoff, |
---|
2552 | | - (long long)irecs[i].br_startblock, |
---|
2553 | | - (long long)irecs[i].br_blockcount, |
---|
2554 | | - irecs[i].br_state); |
---|
2555 | | - } |
---|
2556 | | - } |
---|
2557 | | - XFS_ERROR_REPORT("xfs_da_do_buf(1)", |
---|
2558 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 2528 | + if (nirecs > 1) { |
---|
| 2529 | + map = kmem_zalloc(nirecs * sizeof(struct xfs_buf_map), KM_NOFS); |
---|
| 2530 | + if (!map) { |
---|
| 2531 | + error = -ENOMEM; |
---|
| 2532 | + goto out_free_irecs; |
---|
2559 | 2533 | } |
---|
2560 | | - goto out; |
---|
| 2534 | + *mapp = map; |
---|
2561 | 2535 | } |
---|
2562 | | - error = xfs_buf_map_from_irec(mp, map, nmaps, irecs, nirecs); |
---|
2563 | | -out: |
---|
| 2536 | + |
---|
| 2537 | + for (i = 0; i < nirecs; i++) { |
---|
| 2538 | + if (irecs[i].br_startblock == HOLESTARTBLOCK || |
---|
| 2539 | + irecs[i].br_startblock == DELAYSTARTBLOCK) |
---|
| 2540 | + goto invalid_mapping; |
---|
| 2541 | + if (off != irecs[i].br_startoff) |
---|
| 2542 | + goto invalid_mapping; |
---|
| 2543 | + |
---|
| 2544 | + map[i].bm_bn = XFS_FSB_TO_DADDR(mp, irecs[i].br_startblock); |
---|
| 2545 | + map[i].bm_len = XFS_FSB_TO_BB(mp, irecs[i].br_blockcount); |
---|
| 2546 | + off += irecs[i].br_blockcount; |
---|
| 2547 | + } |
---|
| 2548 | + |
---|
| 2549 | + if (off != bno + nfsb) |
---|
| 2550 | + goto invalid_mapping; |
---|
| 2551 | + |
---|
| 2552 | + *nmaps = nirecs; |
---|
| 2553 | +out_free_irecs: |
---|
2564 | 2554 | if (irecs != &irec) |
---|
2565 | 2555 | kmem_free(irecs); |
---|
2566 | 2556 | return error; |
---|
| 2557 | + |
---|
| 2558 | +invalid_mapping: |
---|
| 2559 | + /* Caller ok with no mapping. */ |
---|
| 2560 | + if (XFS_IS_CORRUPT(mp, !(flags & XFS_DABUF_MAP_HOLE_OK))) { |
---|
| 2561 | + error = -EFSCORRUPTED; |
---|
| 2562 | + if (xfs_error_level >= XFS_ERRLEVEL_LOW) { |
---|
| 2563 | + xfs_alert(mp, "%s: bno %u inode %llu", |
---|
| 2564 | + __func__, bno, dp->i_ino); |
---|
| 2565 | + |
---|
| 2566 | + for (i = 0; i < nirecs; i++) { |
---|
| 2567 | + xfs_alert(mp, |
---|
| 2568 | +"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d", |
---|
| 2569 | + i, irecs[i].br_startoff, |
---|
| 2570 | + irecs[i].br_startblock, |
---|
| 2571 | + irecs[i].br_blockcount, |
---|
| 2572 | + irecs[i].br_state); |
---|
| 2573 | + } |
---|
| 2574 | + } |
---|
| 2575 | + } else { |
---|
| 2576 | + *nmaps = 0; |
---|
| 2577 | + } |
---|
| 2578 | + goto out_free_irecs; |
---|
2567 | 2579 | } |
---|
2568 | 2580 | |
---|
2569 | 2581 | /* |
---|
.. | .. |
---|
2571 | 2583 | */ |
---|
2572 | 2584 | int |
---|
2573 | 2585 | xfs_da_get_buf( |
---|
2574 | | - struct xfs_trans *trans, |
---|
| 2586 | + struct xfs_trans *tp, |
---|
2575 | 2587 | struct xfs_inode *dp, |
---|
2576 | 2588 | xfs_dablk_t bno, |
---|
2577 | | - xfs_daddr_t mappedbno, |
---|
2578 | 2589 | struct xfs_buf **bpp, |
---|
2579 | 2590 | int whichfork) |
---|
2580 | 2591 | { |
---|
| 2592 | + struct xfs_mount *mp = dp->i_mount; |
---|
2581 | 2593 | struct xfs_buf *bp; |
---|
2582 | | - struct xfs_buf_map map; |
---|
2583 | | - struct xfs_buf_map *mapp; |
---|
2584 | | - int nmap; |
---|
| 2594 | + struct xfs_buf_map map, *mapp = ↦ |
---|
| 2595 | + int nmap = 1; |
---|
2585 | 2596 | int error; |
---|
2586 | 2597 | |
---|
2587 | 2598 | *bpp = NULL; |
---|
2588 | | - mapp = ↦ |
---|
2589 | | - nmap = 1; |
---|
2590 | | - error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
---|
2591 | | - &mapp, &nmap); |
---|
2592 | | - if (error) { |
---|
2593 | | - /* mapping a hole is not an error, but we don't continue */ |
---|
2594 | | - if (error == -1) |
---|
2595 | | - error = 0; |
---|
| 2599 | + error = xfs_dabuf_map(dp, bno, 0, whichfork, &mapp, &nmap); |
---|
| 2600 | + if (error || nmap == 0) |
---|
2596 | 2601 | goto out_free; |
---|
2597 | | - } |
---|
2598 | 2602 | |
---|
2599 | | - bp = xfs_trans_get_buf_map(trans, dp->i_mount->m_ddev_targp, |
---|
2600 | | - mapp, nmap, 0); |
---|
2601 | | - error = bp ? bp->b_error : -EIO; |
---|
2602 | | - if (error) { |
---|
2603 | | - if (bp) |
---|
2604 | | - xfs_trans_brelse(trans, bp); |
---|
| 2603 | + error = xfs_trans_get_buf_map(tp, mp->m_ddev_targp, mapp, nmap, 0, &bp); |
---|
| 2604 | + if (error) |
---|
2605 | 2605 | goto out_free; |
---|
2606 | | - } |
---|
2607 | 2606 | |
---|
2608 | 2607 | *bpp = bp; |
---|
2609 | 2608 | |
---|
.. | .. |
---|
2619 | 2618 | */ |
---|
2620 | 2619 | int |
---|
2621 | 2620 | xfs_da_read_buf( |
---|
2622 | | - struct xfs_trans *trans, |
---|
| 2621 | + struct xfs_trans *tp, |
---|
2623 | 2622 | struct xfs_inode *dp, |
---|
2624 | 2623 | xfs_dablk_t bno, |
---|
2625 | | - xfs_daddr_t mappedbno, |
---|
| 2624 | + unsigned int flags, |
---|
2626 | 2625 | struct xfs_buf **bpp, |
---|
2627 | 2626 | int whichfork, |
---|
2628 | 2627 | const struct xfs_buf_ops *ops) |
---|
2629 | 2628 | { |
---|
| 2629 | + struct xfs_mount *mp = dp->i_mount; |
---|
2630 | 2630 | struct xfs_buf *bp; |
---|
2631 | | - struct xfs_buf_map map; |
---|
2632 | | - struct xfs_buf_map *mapp; |
---|
2633 | | - int nmap; |
---|
| 2631 | + struct xfs_buf_map map, *mapp = ↦ |
---|
| 2632 | + int nmap = 1; |
---|
2634 | 2633 | int error; |
---|
2635 | 2634 | |
---|
2636 | 2635 | *bpp = NULL; |
---|
2637 | | - mapp = ↦ |
---|
2638 | | - nmap = 1; |
---|
2639 | | - error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
---|
2640 | | - &mapp, &nmap); |
---|
2641 | | - if (error) { |
---|
2642 | | - /* mapping a hole is not an error, but we don't continue */ |
---|
2643 | | - if (error == -1) |
---|
2644 | | - error = 0; |
---|
| 2636 | + error = xfs_dabuf_map(dp, bno, flags, whichfork, &mapp, &nmap); |
---|
| 2637 | + if (error || !nmap) |
---|
2645 | 2638 | goto out_free; |
---|
2646 | | - } |
---|
2647 | 2639 | |
---|
2648 | | - error = xfs_trans_read_buf_map(dp->i_mount, trans, |
---|
2649 | | - dp->i_mount->m_ddev_targp, |
---|
2650 | | - mapp, nmap, 0, &bp, ops); |
---|
| 2640 | + error = xfs_trans_read_buf_map(mp, tp, mp->m_ddev_targp, mapp, nmap, 0, |
---|
| 2641 | + &bp, ops); |
---|
2651 | 2642 | if (error) |
---|
2652 | 2643 | goto out_free; |
---|
2653 | 2644 | |
---|
.. | .. |
---|
2670 | 2661 | xfs_da_reada_buf( |
---|
2671 | 2662 | struct xfs_inode *dp, |
---|
2672 | 2663 | xfs_dablk_t bno, |
---|
2673 | | - xfs_daddr_t mappedbno, |
---|
| 2664 | + unsigned int flags, |
---|
2674 | 2665 | int whichfork, |
---|
2675 | 2666 | const struct xfs_buf_ops *ops) |
---|
2676 | 2667 | { |
---|
.. | .. |
---|
2681 | 2672 | |
---|
2682 | 2673 | mapp = ↦ |
---|
2683 | 2674 | nmap = 1; |
---|
2684 | | - error = xfs_dabuf_map(dp, bno, mappedbno, whichfork, |
---|
2685 | | - &mapp, &nmap); |
---|
2686 | | - if (error) { |
---|
2687 | | - /* mapping a hole is not an error, but we don't continue */ |
---|
2688 | | - if (error == -1) |
---|
2689 | | - error = 0; |
---|
| 2675 | + error = xfs_dabuf_map(dp, bno, flags, whichfork, &mapp, &nmap); |
---|
| 2676 | + if (error || !nmap) |
---|
2690 | 2677 | goto out_free; |
---|
2691 | | - } |
---|
2692 | 2678 | |
---|
2693 | | - mappedbno = mapp[0].bm_bn; |
---|
2694 | 2679 | xfs_buf_readahead_map(dp->i_mount->m_ddev_targp, mapp, nmap, ops); |
---|
2695 | 2680 | |
---|
2696 | 2681 | out_free: |
---|