1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 4 * Copyright (c) 2013 Red Hat, Inc. 5 * All Rights Reserved. 6 */ 7 #include "xfs.h" 8 #include "xfs_fs.h" 9 #include "xfs_shared.h" 10 #include "xfs_format.h" 11 #include "xfs_log_format.h" 12 #include "xfs_trans_resv.h" 13 #include "xfs_mount.h" 14 #include "xfs_inode.h" 15 #include "xfs_dir2.h" 16 #include "xfs_dir2_priv.h" 17 #include "xfs_error.h" 18 #include "xfs_trans.h" 19 #include "xfs_buf_item.h" 20 #include "xfs_log.h" 21 #include "xfs_health.h" 22 23 static xfs_failaddr_t xfs_dir2_data_freefind_verify( 24 struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, 25 struct xfs_dir2_data_unused *dup, 26 struct xfs_dir2_data_free **bf_ent); 27 28 struct xfs_dir2_data_free * 29 xfs_dir2_data_bestfree_p( 30 struct xfs_mount *mp, 31 struct xfs_dir2_data_hdr *hdr) 32 { 33 if (xfs_has_crc(mp)) 34 return ((struct xfs_dir3_data_hdr *)hdr)->best_free; 35 return hdr->bestfree; 36 } 37 38 /* 39 * Pointer to an entry's tag word. 40 */ 41 __be16 * 42 xfs_dir2_data_entry_tag_p( 43 struct xfs_mount *mp, 44 struct xfs_dir2_data_entry *dep) 45 { 46 return (__be16 *)((char *)dep + 47 xfs_dir2_data_entsize(mp, dep->namelen) - sizeof(__be16)); 48 } 49 50 uint8_t 51 xfs_dir2_data_get_ftype( 52 struct xfs_mount *mp, 53 struct xfs_dir2_data_entry *dep) 54 { 55 if (xfs_has_ftype(mp)) { 56 uint8_t ftype = dep->name[dep->namelen]; 57 58 if (likely(ftype < XFS_DIR3_FT_MAX)) 59 return ftype; 60 } 61 62 return XFS_DIR3_FT_UNKNOWN; 63 } 64 65 void 66 xfs_dir2_data_put_ftype( 67 struct xfs_mount *mp, 68 struct xfs_dir2_data_entry *dep, 69 uint8_t ftype) 70 { 71 ASSERT(ftype < XFS_DIR3_FT_MAX); 72 ASSERT(dep->namelen != 0); 73 74 if (xfs_has_ftype(mp)) 75 dep->name[dep->namelen] = ftype; 76 } 77 78 /* 79 * The number of leaf entries is limited by the size of the block and the amount 80 * of space used by the data entries. We don't know how much space is used by 81 * the data entries yet, so just ensure that the count falls somewhere inside 82 * the block right now. 83 */ 84 static inline unsigned int 85 xfs_dir2_data_max_leaf_entries( 86 struct xfs_da_geometry *geo) 87 { 88 return (geo->blksize - sizeof(struct xfs_dir2_block_tail) - 89 geo->data_entry_offset) / 90 sizeof(struct xfs_dir2_leaf_entry); 91 } 92 93 /* 94 * Check the consistency of the data block. 95 * The input can also be a block-format directory. 96 * Return NULL if the buffer is good, otherwise the address of the error. 97 */ 98 xfs_failaddr_t 99 __xfs_dir3_data_check( 100 struct xfs_inode *dp, /* incore inode pointer */ 101 struct xfs_buf *bp) /* data block's buffer */ 102 { 103 xfs_dir2_dataptr_t addr; /* addr for leaf lookup */ 104 xfs_dir2_data_free_t *bf; /* bestfree table */ 105 xfs_dir2_block_tail_t *btp=NULL; /* block tail */ 106 int count; /* count of entries found */ 107 xfs_dir2_data_hdr_t *hdr; /* data block header */ 108 xfs_dir2_data_free_t *dfp; /* bestfree entry */ 109 int freeseen; /* mask of bestfrees seen */ 110 xfs_dahash_t hash; /* hash of current name */ 111 int i; /* leaf index */ 112 int lastfree; /* last entry was unused */ 113 xfs_dir2_leaf_entry_t *lep=NULL; /* block leaf entries */ 114 struct xfs_mount *mp = bp->b_mount; 115 int stale; /* count of stale leaves */ 116 struct xfs_name name; 117 unsigned int offset; 118 unsigned int end; 119 struct xfs_da_geometry *geo = mp->m_dir_geo; 120 121 /* 122 * If this isn't a directory, something is seriously wrong. Bail out. 123 */ 124 if (dp && !S_ISDIR(VFS_I(dp)->i_mode)) 125 return __this_address; 126 127 hdr = bp->b_addr; 128 offset = geo->data_entry_offset; 129 130 switch (hdr->magic) { 131 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): 132 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): 133 btp = xfs_dir2_block_tail_p(geo, hdr); 134 lep = xfs_dir2_block_leaf_p(btp); 135 136 if (be32_to_cpu(btp->count) >= 137 xfs_dir2_data_max_leaf_entries(geo)) 138 return __this_address; 139 break; 140 case cpu_to_be32(XFS_DIR3_DATA_MAGIC): 141 case cpu_to_be32(XFS_DIR2_DATA_MAGIC): 142 break; 143 default: 144 return __this_address; 145 } 146 end = xfs_dir3_data_end_offset(geo, hdr); 147 if (!end) 148 return __this_address; 149 150 /* 151 * Account for zero bestfree entries. 152 */ 153 bf = xfs_dir2_data_bestfree_p(mp, hdr); 154 count = lastfree = freeseen = 0; 155 if (!bf[0].length) { 156 if (bf[0].offset) 157 return __this_address; 158 freeseen |= 1 << 0; 159 } 160 if (!bf[1].length) { 161 if (bf[1].offset) 162 return __this_address; 163 freeseen |= 1 << 1; 164 } 165 if (!bf[2].length) { 166 if (bf[2].offset) 167 return __this_address; 168 freeseen |= 1 << 2; 169 } 170 171 if (be16_to_cpu(bf[0].length) < be16_to_cpu(bf[1].length)) 172 return __this_address; 173 if (be16_to_cpu(bf[1].length) < be16_to_cpu(bf[2].length)) 174 return __this_address; 175 /* 176 * Loop over the data/unused entries. 177 */ 178 while (offset < end) { 179 struct xfs_dir2_data_unused *dup = bp->b_addr + offset; 180 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; 181 unsigned int reclen; 182 183 /* 184 * Are the remaining bytes large enough to hold an 185 * unused entry? 186 */ 187 if (offset > end - xfs_dir2_data_unusedsize(1)) 188 return __this_address; 189 190 /* 191 * If it's unused, look for the space in the bestfree table. 192 * If we find it, account for that, else make sure it 193 * doesn't need to be there. 194 */ 195 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 196 xfs_failaddr_t fa; 197 198 reclen = xfs_dir2_data_unusedsize( 199 be16_to_cpu(dup->length)); 200 if (lastfree != 0) 201 return __this_address; 202 if (be16_to_cpu(dup->length) != reclen) 203 return __this_address; 204 if (offset + reclen > end) 205 return __this_address; 206 if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) != 207 offset) 208 return __this_address; 209 fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp); 210 if (fa) 211 return fa; 212 if (dfp) { 213 i = (int)(dfp - bf); 214 if ((freeseen & (1 << i)) != 0) 215 return __this_address; 216 freeseen |= 1 << i; 217 } else { 218 if (be16_to_cpu(dup->length) > 219 be16_to_cpu(bf[2].length)) 220 return __this_address; 221 } 222 offset += reclen; 223 lastfree = 1; 224 continue; 225 } 226 227 /* 228 * This is not an unused entry. Are the remaining bytes 229 * large enough for a dirent with a single-byte name? 230 */ 231 if (offset > end - xfs_dir2_data_entsize(mp, 1)) 232 return __this_address; 233 234 /* 235 * It's a real entry. Validate the fields. 236 * If this is a block directory then make sure it's 237 * in the leaf section of the block. 238 * The linear search is crude but this is DEBUG code. 239 */ 240 if (dep->namelen == 0) 241 return __this_address; 242 reclen = xfs_dir2_data_entsize(mp, dep->namelen); 243 if (offset + reclen > end) 244 return __this_address; 245 if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber))) 246 return __this_address; 247 if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset) 248 return __this_address; 249 if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX) 250 return __this_address; 251 count++; 252 lastfree = 0; 253 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 254 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { 255 addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk, 256 (xfs_dir2_data_aoff_t) 257 ((char *)dep - (char *)hdr)); 258 name.name = dep->name; 259 name.len = dep->namelen; 260 hash = xfs_dir2_hashname(mp, &name); 261 for (i = 0; i < be32_to_cpu(btp->count); i++) { 262 if (be32_to_cpu(lep[i].address) == addr && 263 be32_to_cpu(lep[i].hashval) == hash) 264 break; 265 } 266 if (i >= be32_to_cpu(btp->count)) 267 return __this_address; 268 } 269 offset += reclen; 270 } 271 /* 272 * Need to have seen all the entries and all the bestfree slots. 273 */ 274 if (freeseen != 7) 275 return __this_address; 276 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 277 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { 278 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) { 279 if (lep[i].address == 280 cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) 281 stale++; 282 if (i > 0 && be32_to_cpu(lep[i].hashval) < 283 be32_to_cpu(lep[i - 1].hashval)) 284 return __this_address; 285 } 286 if (count != be32_to_cpu(btp->count) - be32_to_cpu(btp->stale)) 287 return __this_address; 288 if (stale != be32_to_cpu(btp->stale)) 289 return __this_address; 290 } 291 return NULL; 292 } 293 294 #ifdef DEBUG 295 void 296 xfs_dir3_data_check( 297 struct xfs_inode *dp, 298 struct xfs_buf *bp) 299 { 300 xfs_failaddr_t fa; 301 302 fa = __xfs_dir3_data_check(dp, bp); 303 if (!fa) 304 return; 305 xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount, 306 bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__, 307 fa); 308 ASSERT(0); 309 } 310 #endif 311 312 static xfs_failaddr_t 313 xfs_dir3_data_verify( 314 struct xfs_buf *bp) 315 { 316 struct xfs_mount *mp = bp->b_mount; 317 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; 318 319 if (!xfs_verify_magic(bp, hdr3->magic)) 320 return __this_address; 321 322 if (xfs_has_crc(mp)) { 323 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) 324 return __this_address; 325 if (be64_to_cpu(hdr3->blkno) != xfs_buf_daddr(bp)) 326 return __this_address; 327 if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) 328 return __this_address; 329 } 330 return __xfs_dir3_data_check(NULL, bp); 331 } 332 333 /* 334 * Readahead of the first block of the directory when it is opened is completely 335 * oblivious to the format of the directory. Hence we can either get a block 336 * format buffer or a data format buffer on readahead. 337 */ 338 static void 339 xfs_dir3_data_reada_verify( 340 struct xfs_buf *bp) 341 { 342 struct xfs_dir2_data_hdr *hdr = bp->b_addr; 343 344 switch (hdr->magic) { 345 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): 346 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): 347 bp->b_ops = &xfs_dir3_block_buf_ops; 348 bp->b_ops->verify_read(bp); 349 return; 350 case cpu_to_be32(XFS_DIR2_DATA_MAGIC): 351 case cpu_to_be32(XFS_DIR3_DATA_MAGIC): 352 bp->b_ops = &xfs_dir3_data_buf_ops; 353 bp->b_ops->verify_read(bp); 354 return; 355 default: 356 xfs_verifier_error(bp, -EFSCORRUPTED, __this_address); 357 break; 358 } 359 } 360 361 static void 362 xfs_dir3_data_read_verify( 363 struct xfs_buf *bp) 364 { 365 struct xfs_mount *mp = bp->b_mount; 366 xfs_failaddr_t fa; 367 368 if (xfs_has_crc(mp) && 369 !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF)) 370 xfs_verifier_error(bp, -EFSBADCRC, __this_address); 371 else { 372 fa = xfs_dir3_data_verify(bp); 373 if (fa) 374 xfs_verifier_error(bp, -EFSCORRUPTED, fa); 375 } 376 } 377 378 static void 379 xfs_dir3_data_write_verify( 380 struct xfs_buf *bp) 381 { 382 struct xfs_mount *mp = bp->b_mount; 383 struct xfs_buf_log_item *bip = bp->b_log_item; 384 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; 385 xfs_failaddr_t fa; 386 387 fa = xfs_dir3_data_verify(bp); 388 if (fa) { 389 xfs_verifier_error(bp, -EFSCORRUPTED, fa); 390 return; 391 } 392 393 if (!xfs_has_crc(mp)) 394 return; 395 396 if (bip) 397 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn); 398 399 xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF); 400 } 401 402 const struct xfs_buf_ops xfs_dir3_data_buf_ops = { 403 .name = "xfs_dir3_data", 404 .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC), 405 cpu_to_be32(XFS_DIR3_DATA_MAGIC) }, 406 .verify_read = xfs_dir3_data_read_verify, 407 .verify_write = xfs_dir3_data_write_verify, 408 .verify_struct = xfs_dir3_data_verify, 409 }; 410 411 static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = { 412 .name = "xfs_dir3_data_reada", 413 .magic = { cpu_to_be32(XFS_DIR2_DATA_MAGIC), 414 cpu_to_be32(XFS_DIR3_DATA_MAGIC) }, 415 .verify_read = xfs_dir3_data_reada_verify, 416 .verify_write = xfs_dir3_data_write_verify, 417 }; 418 419 xfs_failaddr_t 420 xfs_dir3_data_header_check( 421 struct xfs_buf *bp, 422 xfs_ino_t owner) 423 { 424 struct xfs_mount *mp = bp->b_mount; 425 426 if (xfs_has_crc(mp)) { 427 struct xfs_dir3_data_hdr *hdr3 = bp->b_addr; 428 429 if (hdr3->hdr.magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) 430 return __this_address; 431 432 if (be64_to_cpu(hdr3->hdr.owner) != owner) 433 return __this_address; 434 } 435 436 return NULL; 437 } 438 439 int 440 xfs_dir3_data_read( 441 struct xfs_trans *tp, 442 struct xfs_inode *dp, 443 xfs_ino_t owner, 444 xfs_dablk_t bno, 445 unsigned int flags, 446 struct xfs_buf **bpp) 447 { 448 xfs_failaddr_t fa; 449 int err; 450 451 err = xfs_da_read_buf(tp, dp, bno, flags, bpp, XFS_DATA_FORK, 452 &xfs_dir3_data_buf_ops); 453 if (err || !*bpp) 454 return err; 455 456 /* Check things that we can't do in the verifier. */ 457 fa = xfs_dir3_data_header_check(*bpp, owner); 458 if (fa) { 459 __xfs_buf_mark_corrupt(*bpp, fa); 460 xfs_trans_brelse(tp, *bpp); 461 *bpp = NULL; 462 xfs_dirattr_mark_sick(dp, XFS_DATA_FORK); 463 return -EFSCORRUPTED; 464 } 465 466 xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_DATA_BUF); 467 return err; 468 } 469 470 int 471 xfs_dir3_data_readahead( 472 struct xfs_inode *dp, 473 xfs_dablk_t bno, 474 unsigned int flags) 475 { 476 return xfs_da_reada_buf(dp, bno, flags, XFS_DATA_FORK, 477 &xfs_dir3_data_reada_buf_ops); 478 } 479 480 /* 481 * Find the bestfree entry that exactly coincides with unused directory space 482 * or a verifier error because the bestfree data are bad. 483 */ 484 static xfs_failaddr_t 485 xfs_dir2_data_freefind_verify( 486 struct xfs_dir2_data_hdr *hdr, 487 struct xfs_dir2_data_free *bf, 488 struct xfs_dir2_data_unused *dup, 489 struct xfs_dir2_data_free **bf_ent) 490 { 491 struct xfs_dir2_data_free *dfp; 492 xfs_dir2_data_aoff_t off; 493 bool matched = false; 494 bool seenzero = false; 495 496 *bf_ent = NULL; 497 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); 498 499 /* 500 * Validate some consistency in the bestfree table. 501 * Check order, non-overlapping entries, and if we find the 502 * one we're looking for it has to be exact. 503 */ 504 for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { 505 if (!dfp->offset) { 506 if (dfp->length) 507 return __this_address; 508 seenzero = true; 509 continue; 510 } 511 if (seenzero) 512 return __this_address; 513 if (be16_to_cpu(dfp->offset) == off) { 514 matched = true; 515 if (dfp->length != dup->length) 516 return __this_address; 517 } else if (be16_to_cpu(dfp->offset) > off) { 518 if (off + be16_to_cpu(dup->length) > 519 be16_to_cpu(dfp->offset)) 520 return __this_address; 521 } else { 522 if (be16_to_cpu(dfp->offset) + 523 be16_to_cpu(dfp->length) > off) 524 return __this_address; 525 } 526 if (!matched && 527 be16_to_cpu(dfp->length) < be16_to_cpu(dup->length)) 528 return __this_address; 529 if (dfp > &bf[0] && 530 be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length)) 531 return __this_address; 532 } 533 534 /* Looks ok so far; now try to match up with a bestfree entry. */ 535 *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup); 536 return NULL; 537 } 538 539 /* 540 * Given a data block and an unused entry from that block, 541 * return the bestfree entry if any that corresponds to it. 542 */ 543 xfs_dir2_data_free_t * 544 xfs_dir2_data_freefind( 545 struct xfs_dir2_data_hdr *hdr, /* data block header */ 546 struct xfs_dir2_data_free *bf, /* bestfree table pointer */ 547 struct xfs_dir2_data_unused *dup) /* unused space */ 548 { 549 xfs_dir2_data_free_t *dfp; /* bestfree entry */ 550 xfs_dir2_data_aoff_t off; /* offset value needed */ 551 552 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); 553 554 /* 555 * If this is smaller than the smallest bestfree entry, 556 * it can't be there since they're sorted. 557 */ 558 if (be16_to_cpu(dup->length) < 559 be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) 560 return NULL; 561 /* 562 * Look at the three bestfree entries for our guy. 563 */ 564 for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { 565 if (!dfp->offset) 566 return NULL; 567 if (be16_to_cpu(dfp->offset) == off) 568 return dfp; 569 } 570 /* 571 * Didn't find it. This only happens if there are duplicate lengths. 572 */ 573 return NULL; 574 } 575 576 /* 577 * Insert an unused-space entry into the bestfree table. 578 */ 579 xfs_dir2_data_free_t * /* entry inserted */ 580 xfs_dir2_data_freeinsert( 581 struct xfs_dir2_data_hdr *hdr, /* data block pointer */ 582 struct xfs_dir2_data_free *dfp, /* bestfree table pointer */ 583 struct xfs_dir2_data_unused *dup, /* unused space */ 584 int *loghead) /* log the data header (out) */ 585 { 586 xfs_dir2_data_free_t new; /* new bestfree entry */ 587 588 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 589 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 590 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 591 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 592 593 new.length = dup->length; 594 new.offset = cpu_to_be16((char *)dup - (char *)hdr); 595 596 /* 597 * Insert at position 0, 1, or 2; or not at all. 598 */ 599 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) { 600 dfp[2] = dfp[1]; 601 dfp[1] = dfp[0]; 602 dfp[0] = new; 603 *loghead = 1; 604 return &dfp[0]; 605 } 606 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) { 607 dfp[2] = dfp[1]; 608 dfp[1] = new; 609 *loghead = 1; 610 return &dfp[1]; 611 } 612 if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) { 613 dfp[2] = new; 614 *loghead = 1; 615 return &dfp[2]; 616 } 617 return NULL; 618 } 619 620 /* 621 * Remove a bestfree entry from the table. 622 */ 623 STATIC void 624 xfs_dir2_data_freeremove( 625 struct xfs_dir2_data_hdr *hdr, /* data block header */ 626 struct xfs_dir2_data_free *bf, /* bestfree table pointer */ 627 struct xfs_dir2_data_free *dfp, /* bestfree entry pointer */ 628 int *loghead) /* out: log data header */ 629 { 630 631 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 632 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 633 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 634 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 635 636 /* 637 * It's the first entry, slide the next 2 up. 638 */ 639 if (dfp == &bf[0]) { 640 bf[0] = bf[1]; 641 bf[1] = bf[2]; 642 } 643 /* 644 * It's the second entry, slide the 3rd entry up. 645 */ 646 else if (dfp == &bf[1]) 647 bf[1] = bf[2]; 648 /* 649 * Must be the last entry. 650 */ 651 else 652 ASSERT(dfp == &bf[2]); 653 /* 654 * Clear the 3rd entry, must be zero now. 655 */ 656 bf[2].length = 0; 657 bf[2].offset = 0; 658 *loghead = 1; 659 } 660 661 /* 662 * Given a data block, reconstruct its bestfree map. 663 */ 664 void 665 xfs_dir2_data_freescan( 666 struct xfs_mount *mp, 667 struct xfs_dir2_data_hdr *hdr, 668 int *loghead) 669 { 670 struct xfs_da_geometry *geo = mp->m_dir_geo; 671 struct xfs_dir2_data_free *bf = xfs_dir2_data_bestfree_p(mp, hdr); 672 void *addr = hdr; 673 unsigned int offset = geo->data_entry_offset; 674 unsigned int end; 675 676 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 677 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 678 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 679 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 680 681 /* 682 * Start by clearing the table. 683 */ 684 memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT); 685 *loghead = 1; 686 687 end = xfs_dir3_data_end_offset(geo, addr); 688 while (offset < end) { 689 struct xfs_dir2_data_unused *dup = addr + offset; 690 struct xfs_dir2_data_entry *dep = addr + offset; 691 692 /* 693 * If it's a free entry, insert it. 694 */ 695 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 696 ASSERT(offset == 697 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))); 698 xfs_dir2_data_freeinsert(hdr, bf, dup, loghead); 699 offset += be16_to_cpu(dup->length); 700 continue; 701 } 702 703 /* 704 * For active entries, check their tags and skip them. 705 */ 706 ASSERT(offset == 707 be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep))); 708 offset += xfs_dir2_data_entsize(mp, dep->namelen); 709 } 710 } 711 712 /* 713 * Initialize a data block at the given block number in the directory. 714 * Give back the buffer for the created block. 715 */ 716 int /* error */ 717 xfs_dir3_data_init( 718 struct xfs_da_args *args, /* directory operation args */ 719 xfs_dir2_db_t blkno, /* logical dir block number */ 720 struct xfs_buf **bpp) /* output block buffer */ 721 { 722 struct xfs_trans *tp = args->trans; 723 struct xfs_inode *dp = args->dp; 724 struct xfs_mount *mp = dp->i_mount; 725 struct xfs_da_geometry *geo = args->geo; 726 struct xfs_buf *bp; 727 struct xfs_dir2_data_hdr *hdr; 728 struct xfs_dir2_data_unused *dup; 729 struct xfs_dir2_data_free *bf; 730 int error; 731 int i; 732 733 /* 734 * Get the buffer set up for the block. 735 */ 736 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, blkno), 737 &bp, XFS_DATA_FORK); 738 if (error) 739 return error; 740 bp->b_ops = &xfs_dir3_data_buf_ops; 741 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_DATA_BUF); 742 743 /* 744 * Initialize the header. 745 */ 746 hdr = bp->b_addr; 747 if (xfs_has_crc(mp)) { 748 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; 749 750 memset(hdr3, 0, sizeof(*hdr3)); 751 hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); 752 hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp)); 753 hdr3->owner = cpu_to_be64(args->owner); 754 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); 755 756 } else 757 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); 758 759 bf = xfs_dir2_data_bestfree_p(mp, hdr); 760 bf[0].offset = cpu_to_be16(geo->data_entry_offset); 761 bf[0].length = cpu_to_be16(geo->blksize - geo->data_entry_offset); 762 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { 763 bf[i].length = 0; 764 bf[i].offset = 0; 765 } 766 767 /* 768 * Set up an unused entry for the block's body. 769 */ 770 dup = bp->b_addr + geo->data_entry_offset; 771 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 772 dup->length = bf[0].length; 773 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); 774 775 /* 776 * Log it and return it. 777 */ 778 xfs_dir2_data_log_header(args, bp); 779 xfs_dir2_data_log_unused(args, bp, dup); 780 *bpp = bp; 781 return 0; 782 } 783 784 /* 785 * Log an active data entry from the block. 786 */ 787 void 788 xfs_dir2_data_log_entry( 789 struct xfs_da_args *args, 790 struct xfs_buf *bp, 791 xfs_dir2_data_entry_t *dep) /* data entry pointer */ 792 { 793 struct xfs_mount *mp = bp->b_mount; 794 struct xfs_dir2_data_hdr *hdr = bp->b_addr; 795 796 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 797 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 798 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 799 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 800 801 xfs_trans_log_buf(args->trans, bp, (uint)((char *)dep - (char *)hdr), 802 (uint)((char *)(xfs_dir2_data_entry_tag_p(mp, dep) + 1) - 803 (char *)hdr - 1)); 804 } 805 806 /* 807 * Log a data block header. 808 */ 809 void 810 xfs_dir2_data_log_header( 811 struct xfs_da_args *args, 812 struct xfs_buf *bp) 813 { 814 #ifdef DEBUG 815 struct xfs_dir2_data_hdr *hdr = bp->b_addr; 816 817 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 818 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 819 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 820 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 821 #endif 822 823 xfs_trans_log_buf(args->trans, bp, 0, args->geo->data_entry_offset - 1); 824 } 825 826 /* 827 * Log a data unused entry. 828 */ 829 void 830 xfs_dir2_data_log_unused( 831 struct xfs_da_args *args, 832 struct xfs_buf *bp, 833 xfs_dir2_data_unused_t *dup) /* data unused pointer */ 834 { 835 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 836 837 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 838 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 839 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || 840 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 841 842 /* 843 * Log the first part of the unused entry. 844 */ 845 xfs_trans_log_buf(args->trans, bp, (uint)((char *)dup - (char *)hdr), 846 (uint)((char *)&dup->length + sizeof(dup->length) - 847 1 - (char *)hdr)); 848 /* 849 * Log the end (tag) of the unused entry. 850 */ 851 xfs_trans_log_buf(args->trans, bp, 852 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr), 853 (uint)((char *)xfs_dir2_data_unused_tag_p(dup) - (char *)hdr + 854 sizeof(xfs_dir2_data_off_t) - 1)); 855 } 856 857 /* 858 * Make a byte range in the data block unused. 859 * Its current contents are unimportant. 860 */ 861 void 862 xfs_dir2_data_make_free( 863 struct xfs_da_args *args, 864 struct xfs_buf *bp, 865 xfs_dir2_data_aoff_t offset, /* starting byte offset */ 866 xfs_dir2_data_aoff_t len, /* length in bytes */ 867 int *needlogp, /* out: log header */ 868 int *needscanp) /* out: regen bestfree */ 869 { 870 xfs_dir2_data_hdr_t *hdr; /* data block pointer */ 871 xfs_dir2_data_free_t *dfp; /* bestfree pointer */ 872 int needscan; /* need to regen bestfree */ 873 xfs_dir2_data_unused_t *newdup; /* new unused entry */ 874 xfs_dir2_data_unused_t *postdup; /* unused entry after us */ 875 xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ 876 unsigned int end; 877 struct xfs_dir2_data_free *bf; 878 879 hdr = bp->b_addr; 880 881 /* 882 * Figure out where the end of the data area is. 883 */ 884 end = xfs_dir3_data_end_offset(args->geo, hdr); 885 ASSERT(end != 0); 886 887 /* 888 * If this isn't the start of the block, then back up to 889 * the previous entry and see if it's free. 890 */ 891 if (offset > args->geo->data_entry_offset) { 892 __be16 *tagp; /* tag just before us */ 893 894 tagp = (__be16 *)((char *)hdr + offset) - 1; 895 prevdup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp)); 896 if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG) 897 prevdup = NULL; 898 } else 899 prevdup = NULL; 900 /* 901 * If this isn't the end of the block, see if the entry after 902 * us is free. 903 */ 904 if (offset + len < end) { 905 postdup = 906 (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); 907 if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG) 908 postdup = NULL; 909 } else 910 postdup = NULL; 911 ASSERT(*needscanp == 0); 912 needscan = 0; 913 /* 914 * Previous and following entries are both free, 915 * merge everything into a single free entry. 916 */ 917 bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr); 918 if (prevdup && postdup) { 919 xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ 920 921 /* 922 * See if prevdup and/or postdup are in bestfree table. 923 */ 924 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); 925 dfp2 = xfs_dir2_data_freefind(hdr, bf, postdup); 926 /* 927 * We need a rescan unless there are exactly 2 free entries 928 * namely our two. Then we know what's happening, otherwise 929 * since the third bestfree is there, there might be more 930 * entries. 931 */ 932 needscan = (bf[2].length != 0); 933 /* 934 * Fix up the new big freespace. 935 */ 936 be16_add_cpu(&prevdup->length, len + be16_to_cpu(postdup->length)); 937 *xfs_dir2_data_unused_tag_p(prevdup) = 938 cpu_to_be16((char *)prevdup - (char *)hdr); 939 xfs_dir2_data_log_unused(args, bp, prevdup); 940 if (!needscan) { 941 /* 942 * Has to be the case that entries 0 and 1 are 943 * dfp and dfp2 (don't know which is which), and 944 * entry 2 is empty. 945 * Remove entry 1 first then entry 0. 946 */ 947 ASSERT(dfp && dfp2); 948 if (dfp == &bf[1]) { 949 dfp = &bf[0]; 950 ASSERT(dfp2 == dfp); 951 dfp2 = &bf[1]; 952 } 953 xfs_dir2_data_freeremove(hdr, bf, dfp2, needlogp); 954 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); 955 /* 956 * Now insert the new entry. 957 */ 958 dfp = xfs_dir2_data_freeinsert(hdr, bf, prevdup, 959 needlogp); 960 ASSERT(dfp == &bf[0]); 961 ASSERT(dfp->length == prevdup->length); 962 ASSERT(!dfp[1].length); 963 ASSERT(!dfp[2].length); 964 } 965 } 966 /* 967 * The entry before us is free, merge with it. 968 */ 969 else if (prevdup) { 970 dfp = xfs_dir2_data_freefind(hdr, bf, prevdup); 971 be16_add_cpu(&prevdup->length, len); 972 *xfs_dir2_data_unused_tag_p(prevdup) = 973 cpu_to_be16((char *)prevdup - (char *)hdr); 974 xfs_dir2_data_log_unused(args, bp, prevdup); 975 /* 976 * If the previous entry was in the table, the new entry 977 * is longer, so it will be in the table too. Remove 978 * the old one and add the new one. 979 */ 980 if (dfp) { 981 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); 982 xfs_dir2_data_freeinsert(hdr, bf, prevdup, needlogp); 983 } 984 /* 985 * Otherwise we need a scan if the new entry is big enough. 986 */ 987 else { 988 needscan = be16_to_cpu(prevdup->length) > 989 be16_to_cpu(bf[2].length); 990 } 991 } 992 /* 993 * The following entry is free, merge with it. 994 */ 995 else if (postdup) { 996 dfp = xfs_dir2_data_freefind(hdr, bf, postdup); 997 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); 998 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 999 newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length)); 1000 *xfs_dir2_data_unused_tag_p(newdup) = 1001 cpu_to_be16((char *)newdup - (char *)hdr); 1002 xfs_dir2_data_log_unused(args, bp, newdup); 1003 /* 1004 * If the following entry was in the table, the new entry 1005 * is longer, so it will be in the table too. Remove 1006 * the old one and add the new one. 1007 */ 1008 if (dfp) { 1009 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); 1010 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); 1011 } 1012 /* 1013 * Otherwise we need a scan if the new entry is big enough. 1014 */ 1015 else { 1016 needscan = be16_to_cpu(newdup->length) > 1017 be16_to_cpu(bf[2].length); 1018 } 1019 } 1020 /* 1021 * Neither neighbor is free. Make a new entry. 1022 */ 1023 else { 1024 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset); 1025 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 1026 newdup->length = cpu_to_be16(len); 1027 *xfs_dir2_data_unused_tag_p(newdup) = 1028 cpu_to_be16((char *)newdup - (char *)hdr); 1029 xfs_dir2_data_log_unused(args, bp, newdup); 1030 xfs_dir2_data_freeinsert(hdr, bf, newdup, needlogp); 1031 } 1032 *needscanp = needscan; 1033 } 1034 1035 /* Check our free data for obvious signs of corruption. */ 1036 static inline xfs_failaddr_t 1037 xfs_dir2_data_check_free( 1038 struct xfs_dir2_data_hdr *hdr, 1039 struct xfs_dir2_data_unused *dup, 1040 xfs_dir2_data_aoff_t offset, 1041 xfs_dir2_data_aoff_t len) 1042 { 1043 if (hdr->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC) && 1044 hdr->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC) && 1045 hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) && 1046 hdr->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) 1047 return __this_address; 1048 if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG) 1049 return __this_address; 1050 if (offset < (char *)dup - (char *)hdr) 1051 return __this_address; 1052 if (offset + len > (char *)dup + be16_to_cpu(dup->length) - (char *)hdr) 1053 return __this_address; 1054 if ((char *)dup - (char *)hdr != 1055 be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup))) 1056 return __this_address; 1057 return NULL; 1058 } 1059 1060 /* Sanity-check a new bestfree entry. */ 1061 static inline xfs_failaddr_t 1062 xfs_dir2_data_check_new_free( 1063 struct xfs_dir2_data_hdr *hdr, 1064 struct xfs_dir2_data_free *dfp, 1065 struct xfs_dir2_data_unused *newdup) 1066 { 1067 if (dfp == NULL) 1068 return __this_address; 1069 if (dfp->length != newdup->length) 1070 return __this_address; 1071 if (be16_to_cpu(dfp->offset) != (char *)newdup - (char *)hdr) 1072 return __this_address; 1073 return NULL; 1074 } 1075 1076 /* 1077 * Take a byte range out of an existing unused space and make it un-free. 1078 */ 1079 int 1080 xfs_dir2_data_use_free( 1081 struct xfs_da_args *args, 1082 struct xfs_buf *bp, 1083 xfs_dir2_data_unused_t *dup, /* unused entry */ 1084 xfs_dir2_data_aoff_t offset, /* starting offset to use */ 1085 xfs_dir2_data_aoff_t len, /* length to use */ 1086 int *needlogp, /* out: need to log header */ 1087 int *needscanp) /* out: need regen bestfree */ 1088 { 1089 xfs_dir2_data_hdr_t *hdr; /* data block header */ 1090 xfs_dir2_data_free_t *dfp; /* bestfree pointer */ 1091 xfs_dir2_data_unused_t *newdup; /* new unused entry */ 1092 xfs_dir2_data_unused_t *newdup2; /* another new unused entry */ 1093 struct xfs_dir2_data_free *bf; 1094 xfs_failaddr_t fa; 1095 int matchback; /* matches end of freespace */ 1096 int matchfront; /* matches start of freespace */ 1097 int needscan; /* need to regen bestfree */ 1098 int oldlen; /* old unused entry's length */ 1099 1100 hdr = bp->b_addr; 1101 fa = xfs_dir2_data_check_free(hdr, dup, offset, len); 1102 if (fa) 1103 goto corrupt; 1104 /* 1105 * Look up the entry in the bestfree table. 1106 */ 1107 oldlen = be16_to_cpu(dup->length); 1108 bf = xfs_dir2_data_bestfree_p(args->dp->i_mount, hdr); 1109 dfp = xfs_dir2_data_freefind(hdr, bf, dup); 1110 ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length)); 1111 /* 1112 * Check for alignment with front and back of the entry. 1113 */ 1114 matchfront = (char *)dup - (char *)hdr == offset; 1115 matchback = (char *)dup + oldlen - (char *)hdr == offset + len; 1116 ASSERT(*needscanp == 0); 1117 needscan = 0; 1118 /* 1119 * If we matched it exactly we just need to get rid of it from 1120 * the bestfree table. 1121 */ 1122 if (matchfront && matchback) { 1123 if (dfp) { 1124 needscan = (bf[2].offset != 0); 1125 if (!needscan) 1126 xfs_dir2_data_freeremove(hdr, bf, dfp, 1127 needlogp); 1128 } 1129 } 1130 /* 1131 * We match the first part of the entry. 1132 * Make a new entry with the remaining freespace. 1133 */ 1134 else if (matchfront) { 1135 newdup = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); 1136 newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 1137 newdup->length = cpu_to_be16(oldlen - len); 1138 *xfs_dir2_data_unused_tag_p(newdup) = 1139 cpu_to_be16((char *)newdup - (char *)hdr); 1140 xfs_dir2_data_log_unused(args, bp, newdup); 1141 /* 1142 * If it was in the table, remove it and add the new one. 1143 */ 1144 if (dfp) { 1145 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); 1146 dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, 1147 needlogp); 1148 fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup); 1149 if (fa) 1150 goto corrupt; 1151 /* 1152 * If we got inserted at the last slot, 1153 * that means we don't know if there was a better 1154 * choice for the last slot, or not. Rescan. 1155 */ 1156 needscan = dfp == &bf[2]; 1157 } 1158 } 1159 /* 1160 * We match the last part of the entry. 1161 * Trim the allocated space off the tail of the entry. 1162 */ 1163 else if (matchback) { 1164 newdup = dup; 1165 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); 1166 *xfs_dir2_data_unused_tag_p(newdup) = 1167 cpu_to_be16((char *)newdup - (char *)hdr); 1168 xfs_dir2_data_log_unused(args, bp, newdup); 1169 /* 1170 * If it was in the table, remove it and add the new one. 1171 */ 1172 if (dfp) { 1173 xfs_dir2_data_freeremove(hdr, bf, dfp, needlogp); 1174 dfp = xfs_dir2_data_freeinsert(hdr, bf, newdup, 1175 needlogp); 1176 fa = xfs_dir2_data_check_new_free(hdr, dfp, newdup); 1177 if (fa) 1178 goto corrupt; 1179 /* 1180 * If we got inserted at the last slot, 1181 * that means we don't know if there was a better 1182 * choice for the last slot, or not. Rescan. 1183 */ 1184 needscan = dfp == &bf[2]; 1185 } 1186 } 1187 /* 1188 * Poking out the middle of an entry. 1189 * Make two new entries. 1190 */ 1191 else { 1192 newdup = dup; 1193 newdup->length = cpu_to_be16(((char *)hdr + offset) - (char *)newdup); 1194 *xfs_dir2_data_unused_tag_p(newdup) = 1195 cpu_to_be16((char *)newdup - (char *)hdr); 1196 xfs_dir2_data_log_unused(args, bp, newdup); 1197 newdup2 = (xfs_dir2_data_unused_t *)((char *)hdr + offset + len); 1198 newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 1199 newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length)); 1200 *xfs_dir2_data_unused_tag_p(newdup2) = 1201 cpu_to_be16((char *)newdup2 - (char *)hdr); 1202 xfs_dir2_data_log_unused(args, bp, newdup2); 1203 /* 1204 * If the old entry was in the table, we need to scan 1205 * if the 3rd entry was valid, since these entries 1206 * are smaller than the old one. 1207 * If we don't need to scan that means there were 1 or 2 1208 * entries in the table, and removing the old and adding 1209 * the 2 new will work. 1210 */ 1211 if (dfp) { 1212 needscan = (bf[2].length != 0); 1213 if (!needscan) { 1214 xfs_dir2_data_freeremove(hdr, bf, dfp, 1215 needlogp); 1216 xfs_dir2_data_freeinsert(hdr, bf, newdup, 1217 needlogp); 1218 xfs_dir2_data_freeinsert(hdr, bf, newdup2, 1219 needlogp); 1220 } 1221 } 1222 } 1223 *needscanp = needscan; 1224 return 0; 1225 corrupt: 1226 xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount, 1227 hdr, sizeof(*hdr), __FILE__, __LINE__, fa); 1228 xfs_da_mark_sick(args); 1229 return -EFSCORRUPTED; 1230 } 1231 1232 /* Find the end of the entry data in a data/block format dir block. */ 1233 unsigned int 1234 xfs_dir3_data_end_offset( 1235 struct xfs_da_geometry *geo, 1236 struct xfs_dir2_data_hdr *hdr) 1237 { 1238 void *p; 1239 1240 switch (hdr->magic) { 1241 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC): 1242 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): 1243 p = xfs_dir2_block_leaf_p(xfs_dir2_block_tail_p(geo, hdr)); 1244 return p - (void *)hdr; 1245 case cpu_to_be32(XFS_DIR3_DATA_MAGIC): 1246 case cpu_to_be32(XFS_DIR2_DATA_MAGIC): 1247 return geo->blksize; 1248 default: 1249 return 0; 1250 } 1251 } 1252
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.