| .. | .. |
|---|
| 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: |
|---|