diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_da_btree.c | 45 | ||||
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 23 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_format.h | 60 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 792 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 475 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_priv.h | 32 |
7 files changed, 924 insertions, 522 deletions
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 4d7696a02418..2f23b14e3adf 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -139,7 +139,8 @@ xfs_da_node_read_verify( | |||
139 | bp->b_ops->verify_read(bp); | 139 | bp->b_ops->verify_read(bp); |
140 | return; | 140 | return; |
141 | case XFS_DIR2_LEAFN_MAGIC: | 141 | case XFS_DIR2_LEAFN_MAGIC: |
142 | bp->b_ops = &xfs_dir2_leafn_buf_ops; | 142 | case XFS_DIR3_LEAFN_MAGIC: |
143 | bp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
143 | bp->b_ops->verify_read(bp); | 144 | bp->b_ops->verify_read(bp); |
144 | return; | 145 | return; |
145 | default: | 146 | default: |
@@ -396,11 +397,18 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
396 | size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - | 397 | size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - |
397 | (char *)oldroot); | 398 | (char *)oldroot); |
398 | } else { | 399 | } else { |
399 | ASSERT(oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 400 | struct xfs_dir3_icleaf_hdr leafhdr; |
401 | struct xfs_dir2_leaf_entry *ents; | ||
402 | |||
400 | leaf = (xfs_dir2_leaf_t *)oldroot; | 403 | leaf = (xfs_dir2_leaf_t *)oldroot; |
401 | size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - | 404 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
402 | (char *)leaf); | 405 | ents = xfs_dir3_leaf_ents_p(leaf); |
406 | |||
407 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || | ||
408 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); | ||
409 | size = (int)((char *)&ents[leafhdr.count] - (char *)leaf); | ||
403 | } | 410 | } |
411 | /* XXX: can't just copy CRC headers from one block to another */ | ||
404 | memcpy(node, oldroot, size); | 412 | memcpy(node, oldroot, size); |
405 | xfs_trans_log_buf(tp, bp, 0, size - 1); | 413 | xfs_trans_log_buf(tp, bp, 0, size - 1); |
406 | 414 | ||
@@ -424,7 +432,8 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
424 | node->hdr.count = cpu_to_be16(2); | 432 | node->hdr.count = cpu_to_be16(2); |
425 | 433 | ||
426 | #ifdef DEBUG | 434 | #ifdef DEBUG |
427 | if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) { | 435 | if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
436 | oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { | ||
428 | ASSERT(blk1->blkno >= mp->m_dirleafblk && | 437 | ASSERT(blk1->blkno >= mp->m_dirleafblk && |
429 | blk1->blkno < mp->m_dirfreeblk); | 438 | blk1->blkno < mp->m_dirfreeblk); |
430 | ASSERT(blk2->blkno >= mp->m_dirleafblk && | 439 | ASSERT(blk2->blkno >= mp->m_dirleafblk && |
@@ -782,6 +791,7 @@ xfs_da_blkinfo_onlychild_validate(struct xfs_da_blkinfo *blkinfo, __u16 level) | |||
782 | 791 | ||
783 | if (level == 1) { | 792 | if (level == 1) { |
784 | ASSERT(magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 793 | ASSERT(magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
794 | magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC) || | ||
785 | magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 795 | magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); |
786 | } else | 796 | } else |
787 | ASSERT(magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); | 797 | ASSERT(magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); |
@@ -1565,6 +1575,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | |||
1565 | info = blk->bp->b_addr; | 1575 | info = blk->bp->b_addr; |
1566 | ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || | 1576 | ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || |
1567 | info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | 1577 | info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1578 | info->magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC) || | ||
1568 | info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); | 1579 | info->magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC)); |
1569 | blk->magic = be16_to_cpu(info->magic); | 1580 | blk->magic = be16_to_cpu(info->magic); |
1570 | if (blk->magic == XFS_DA_NODE_MAGIC) { | 1581 | if (blk->magic == XFS_DA_NODE_MAGIC) { |
@@ -1584,12 +1595,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | |||
1584 | NULL); | 1595 | NULL); |
1585 | break; | 1596 | break; |
1586 | case XFS_DIR2_LEAFN_MAGIC: | 1597 | case XFS_DIR2_LEAFN_MAGIC: |
1598 | case XFS_DIR3_LEAFN_MAGIC: | ||
1599 | blk->magic = XFS_DIR2_LEAFN_MAGIC; | ||
1587 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, | 1600 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, |
1588 | NULL); | 1601 | NULL); |
1589 | break; | 1602 | break; |
1590 | default: | 1603 | default: |
1591 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || | 1604 | ASSERT(0); |
1592 | blk->magic == XFS_DIR2_LEAFN_MAGIC); | ||
1593 | break; | 1605 | break; |
1594 | } | 1606 | } |
1595 | } | 1607 | } |
@@ -1833,10 +1845,16 @@ xfs_da_swap_lastblock( | |||
1833 | /* | 1845 | /* |
1834 | * Get values from the moved block. | 1846 | * Get values from the moved block. |
1835 | */ | 1847 | */ |
1836 | if (dead_info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) { | 1848 | if (dead_info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1849 | dead_info->magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { | ||
1850 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1851 | struct xfs_dir2_leaf_entry *ents; | ||
1852 | |||
1837 | dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; | 1853 | dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; |
1854 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, dead_leaf2); | ||
1855 | ents = xfs_dir3_leaf_ents_p(dead_leaf2); | ||
1838 | dead_level = 0; | 1856 | dead_level = 0; |
1839 | dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); | 1857 | dead_hash = be32_to_cpu(ents[leafhdr.count - 1].hashval); |
1840 | } else { | 1858 | } else { |
1841 | ASSERT(dead_info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); | 1859 | ASSERT(dead_info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC)); |
1842 | dead_node = (xfs_da_intnode_t *)dead_info; | 1860 | dead_node = (xfs_da_intnode_t *)dead_info; |
@@ -2281,10 +2299,17 @@ xfs_da_read_buf( | |||
2281 | XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && | 2299 | XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && |
2282 | (magic != XFS_ATTR_LEAF_MAGIC) && | 2300 | (magic != XFS_ATTR_LEAF_MAGIC) && |
2283 | (magic != XFS_DIR2_LEAF1_MAGIC) && | 2301 | (magic != XFS_DIR2_LEAF1_MAGIC) && |
2302 | (magic != XFS_DIR3_LEAF1_MAGIC) && | ||
2284 | (magic != XFS_DIR2_LEAFN_MAGIC) && | 2303 | (magic != XFS_DIR2_LEAFN_MAGIC) && |
2304 | (magic != XFS_DIR3_LEAFN_MAGIC) && | ||
2285 | (magic1 != XFS_DIR2_BLOCK_MAGIC) && | 2305 | (magic1 != XFS_DIR2_BLOCK_MAGIC) && |
2306 | (magic1 != XFS_DIR3_BLOCK_MAGIC) && | ||
2286 | (magic1 != XFS_DIR2_DATA_MAGIC) && | 2307 | (magic1 != XFS_DIR2_DATA_MAGIC) && |
2287 | (free->hdr.magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)), | 2308 | (magic1 != XFS_DIR3_DATA_MAGIC) && |
2309 | (free->hdr.magic != | ||
2310 | cpu_to_be32(XFS_DIR2_FREE_MAGIC)) && | ||
2311 | (free->hdr.magic != | ||
2312 | cpu_to_be32(XFS_DIR3_FREE_MAGIC)), | ||
2288 | mp, XFS_ERRTAG_DA_READ_BUF, | 2313 | mp, XFS_ERRTAG_DA_READ_BUF, |
2289 | XFS_RANDOM_DA_READ_BUF))) { | 2314 | XFS_RANDOM_DA_READ_BUF))) { |
2290 | trace_xfs_da_btree_corrupt(bp, _RET_IP_); | 2315 | trace_xfs_da_btree_corrupt(bp, _RET_IP_); |
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index ee5170c46ae1..0854b95b1dc1 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -47,6 +47,29 @@ typedef struct xfs_da_blkinfo { | |||
47 | } xfs_da_blkinfo_t; | 47 | } xfs_da_blkinfo_t; |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * CRC enabled directory structure types | ||
51 | * | ||
52 | * The headers change size for the additional verification information, but | ||
53 | * otherwise the tree layouts and contents are unchanged. | ||
54 | */ | ||
55 | #define XFS_DIR3_LEAF1_MAGIC 0x3df1 /* magic number: v2 dirlf single blks */ | ||
56 | #define XFS_DIR3_LEAFN_MAGIC 0x3dff /* magic number: v2 dirlf multi blks */ | ||
57 | |||
58 | struct xfs_da3_blkinfo { | ||
59 | /* | ||
60 | * the node link manipulation code relies on the fact that the first | ||
61 | * element of this structure is the struct xfs_da_blkinfo so it can | ||
62 | * ignore the differences in the rest of the structures. | ||
63 | */ | ||
64 | struct xfs_da_blkinfo hdr; | ||
65 | __be32 crc; /* CRC of block */ | ||
66 | __be64 blkno; /* first block of the buffer */ | ||
67 | __be64 lsn; /* sequence number of last write */ | ||
68 | uuid_t uuid; /* filesystem we belong to */ | ||
69 | __be64 owner; /* inode that owns the block */ | ||
70 | }; | ||
71 | |||
72 | /* | ||
50 | * This is the structure of the root and intermediate nodes in the Btree. | 73 | * This is the structure of the root and intermediate nodes in the Btree. |
51 | * The leaf nodes are defined above. | 74 | * The leaf nodes are defined above. |
52 | * | 75 | * |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 7ec87c20cbd2..d2e445f92ffb 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -1013,6 +1013,8 @@ xfs_dir2_leaf_to_block( | |||
1013 | __be16 *tagp; /* end of entry (tag) */ | 1013 | __be16 *tagp; /* end of entry (tag) */ |
1014 | int to; /* block/leaf to index */ | 1014 | int to; /* block/leaf to index */ |
1015 | xfs_trans_t *tp; /* transaction pointer */ | 1015 | xfs_trans_t *tp; /* transaction pointer */ |
1016 | struct xfs_dir2_leaf_entry *ents; | ||
1017 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1016 | 1018 | ||
1017 | trace_xfs_dir2_leaf_to_block(args); | 1019 | trace_xfs_dir2_leaf_to_block(args); |
1018 | 1020 | ||
@@ -1020,8 +1022,12 @@ xfs_dir2_leaf_to_block( | |||
1020 | tp = args->trans; | 1022 | tp = args->trans; |
1021 | mp = dp->i_mount; | 1023 | mp = dp->i_mount; |
1022 | leaf = lbp->b_addr; | 1024 | leaf = lbp->b_addr; |
1023 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 1025 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
1026 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1024 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1027 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1028 | |||
1029 | ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC || | ||
1030 | leafhdr.magic == XFS_DIR3_LEAF1_MAGIC); | ||
1025 | /* | 1031 | /* |
1026 | * If there are data blocks other than the first one, take this | 1032 | * If there are data blocks other than the first one, take this |
1027 | * opportunity to remove trailing empty data blocks that may have | 1033 | * opportunity to remove trailing empty data blocks that may have |
@@ -1058,7 +1064,7 @@ xfs_dir2_leaf_to_block( | |||
1058 | * Size of the "leaf" area in the block. | 1064 | * Size of the "leaf" area in the block. |
1059 | */ | 1065 | */ |
1060 | size = (uint)sizeof(xfs_dir2_block_tail_t) + | 1066 | size = (uint)sizeof(xfs_dir2_block_tail_t) + |
1061 | (uint)sizeof(*lep) * (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)); | 1067 | (uint)sizeof(*lep) * (leafhdr.count - leafhdr.stale); |
1062 | /* | 1068 | /* |
1063 | * Look at the last data entry. | 1069 | * Look at the last data entry. |
1064 | */ | 1070 | */ |
@@ -1087,18 +1093,17 @@ xfs_dir2_leaf_to_block( | |||
1087 | * Initialize the block tail. | 1093 | * Initialize the block tail. |
1088 | */ | 1094 | */ |
1089 | btp = xfs_dir2_block_tail_p(mp, hdr); | 1095 | btp = xfs_dir2_block_tail_p(mp, hdr); |
1090 | btp->count = cpu_to_be32(be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale)); | 1096 | btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale); |
1091 | btp->stale = 0; | 1097 | btp->stale = 0; |
1092 | xfs_dir2_block_log_tail(tp, dbp); | 1098 | xfs_dir2_block_log_tail(tp, dbp); |
1093 | /* | 1099 | /* |
1094 | * Initialize the block leaf area. We compact out stale entries. | 1100 | * Initialize the block leaf area. We compact out stale entries. |
1095 | */ | 1101 | */ |
1096 | lep = xfs_dir2_block_leaf_p(btp); | 1102 | lep = xfs_dir2_block_leaf_p(btp); |
1097 | for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) { | 1103 | for (from = to = 0; from < leafhdr.count; from++) { |
1098 | if (leaf->ents[from].address == | 1104 | if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
1099 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
1100 | continue; | 1105 | continue; |
1101 | lep[to++] = leaf->ents[from]; | 1106 | lep[to++] = ents[from]; |
1102 | } | 1107 | } |
1103 | ASSERT(to == be32_to_cpu(btp->count)); | 1108 | ASSERT(to == be32_to_cpu(btp->count)); |
1104 | xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); | 1109 | xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1); |
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index 0ac09502b830..7b986d334b33 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h | |||
@@ -470,6 +470,21 @@ typedef struct xfs_dir2_leaf_hdr { | |||
470 | __be16 stale; /* count of stale entries */ | 470 | __be16 stale; /* count of stale entries */ |
471 | } xfs_dir2_leaf_hdr_t; | 471 | } xfs_dir2_leaf_hdr_t; |
472 | 472 | ||
473 | struct xfs_dir3_leaf_hdr { | ||
474 | struct xfs_da3_blkinfo info; /* header for da routines */ | ||
475 | __be16 count; /* count of entries */ | ||
476 | __be16 stale; /* count of stale entries */ | ||
477 | __be32 pad; | ||
478 | }; | ||
479 | |||
480 | struct xfs_dir3_icleaf_hdr { | ||
481 | __uint32_t forw; | ||
482 | __uint32_t back; | ||
483 | __uint16_t magic; | ||
484 | __uint16_t count; | ||
485 | __uint16_t stale; | ||
486 | }; | ||
487 | |||
473 | /* | 488 | /* |
474 | * Leaf block entry. | 489 | * Leaf block entry. |
475 | */ | 490 | */ |
@@ -489,23 +504,50 @@ typedef struct xfs_dir2_leaf_tail { | |||
489 | * Leaf block. | 504 | * Leaf block. |
490 | */ | 505 | */ |
491 | typedef struct xfs_dir2_leaf { | 506 | typedef struct xfs_dir2_leaf { |
492 | xfs_dir2_leaf_hdr_t hdr; /* leaf header */ | 507 | xfs_dir2_leaf_hdr_t hdr; /* leaf header */ |
493 | xfs_dir2_leaf_entry_t ents[]; /* entries */ | 508 | xfs_dir2_leaf_entry_t __ents[]; /* entries */ |
494 | } xfs_dir2_leaf_t; | 509 | } xfs_dir2_leaf_t; |
495 | 510 | ||
496 | /* | 511 | struct xfs_dir3_leaf { |
497 | * DB blocks here are logical directory block numbers, not filesystem blocks. | 512 | struct xfs_dir3_leaf_hdr hdr; /* leaf header */ |
498 | */ | 513 | struct xfs_dir2_leaf_entry __ents[]; /* entries */ |
514 | }; | ||
515 | |||
516 | #define XFS_DIR3_LEAF_CRC_OFF offsetof(struct xfs_dir3_leaf_hdr, info.crc) | ||
517 | |||
518 | static inline int | ||
519 | xfs_dir3_leaf_hdr_size(struct xfs_dir2_leaf *lp) | ||
520 | { | ||
521 | if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || | ||
522 | lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) | ||
523 | return sizeof(struct xfs_dir3_leaf_hdr); | ||
524 | return sizeof(struct xfs_dir2_leaf_hdr); | ||
525 | } | ||
499 | 526 | ||
500 | static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp) | 527 | static inline int |
528 | xfs_dir3_max_leaf_ents(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) | ||
501 | { | 529 | { |
502 | return (mp->m_dirblksize - (uint)sizeof(struct xfs_dir2_leaf_hdr)) / | 530 | return (mp->m_dirblksize - xfs_dir3_leaf_hdr_size(lp)) / |
503 | (uint)sizeof(struct xfs_dir2_leaf_entry); | 531 | (uint)sizeof(struct xfs_dir2_leaf_entry); |
504 | } | 532 | } |
505 | 533 | ||
506 | /* | 534 | /* |
507 | * Get address of the bestcount field in the single-leaf block. | 535 | * Get address of the bestcount field in the single-leaf block. |
508 | */ | 536 | */ |
537 | static inline struct xfs_dir2_leaf_entry * | ||
538 | xfs_dir3_leaf_ents_p(struct xfs_dir2_leaf *lp) | ||
539 | { | ||
540 | if (lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || | ||
541 | lp->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) { | ||
542 | struct xfs_dir3_leaf *lp3 = (struct xfs_dir3_leaf *)lp; | ||
543 | return lp3->__ents; | ||
544 | } | ||
545 | return lp->__ents; | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * Get address of the bestcount field in the single-leaf block. | ||
550 | */ | ||
509 | static inline struct xfs_dir2_leaf_tail * | 551 | static inline struct xfs_dir2_leaf_tail * |
510 | xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) | 552 | xfs_dir2_leaf_tail_p(struct xfs_mount *mp, struct xfs_dir2_leaf *lp) |
511 | { | 553 | { |
@@ -524,6 +566,10 @@ xfs_dir2_leaf_bests_p(struct xfs_dir2_leaf_tail *ltp) | |||
524 | } | 566 | } |
525 | 567 | ||
526 | /* | 568 | /* |
569 | * DB blocks here are logical directory block numbers, not filesystem blocks. | ||
570 | */ | ||
571 | |||
572 | /* | ||
527 | * Convert dataptr to byte in file space | 573 | * Convert dataptr to byte in file space |
528 | */ | 574 | */ |
529 | static inline xfs_dir2_off_t | 575 | static inline xfs_dir2_off_t |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index c7dca950f768..7352e41d2aaa 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
3 | * Copyright (c) 2013 Red Hat, Inc. | ||
3 | * All Rights Reserved. | 4 | * All Rights Reserved. |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -33,77 +34,263 @@ | |||
33 | #include "xfs_dir2_priv.h" | 34 | #include "xfs_dir2_priv.h" |
34 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
35 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
37 | #include "xfs_buf_item.h" | ||
38 | #include "xfs_cksum.h" | ||
36 | 39 | ||
37 | /* | 40 | /* |
38 | * Local function declarations. | 41 | * Local function declarations. |
39 | */ | 42 | */ |
40 | #ifdef DEBUG | ||
41 | static void xfs_dir2_leaf_check(struct xfs_inode *dp, struct xfs_buf *bp); | ||
42 | #else | ||
43 | #define xfs_dir2_leaf_check(dp, bp) | ||
44 | #endif | ||
45 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, | 43 | static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, struct xfs_buf **lbpp, |
46 | int *indexp, struct xfs_buf **dbpp); | 44 | int *indexp, struct xfs_buf **dbpp); |
47 | static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, | 45 | static void xfs_dir3_leaf_log_bests(struct xfs_trans *tp, struct xfs_buf *bp, |
48 | int first, int last); | 46 | int first, int last); |
49 | static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); | 47 | static void xfs_dir3_leaf_log_tail(struct xfs_trans *tp, struct xfs_buf *bp); |
50 | 48 | ||
51 | static void | 49 | /* |
52 | xfs_dir2_leaf_verify( | 50 | * Check the internal consistency of a leaf1 block. |
51 | * Pop an assert if something is wrong. | ||
52 | */ | ||
53 | #ifdef DEBUG | ||
54 | #define xfs_dir3_leaf_check(mp, bp) \ | ||
55 | do { \ | ||
56 | if (!xfs_dir3_leaf1_check((mp), (bp))) \ | ||
57 | ASSERT(0); \ | ||
58 | } while (0); | ||
59 | |||
60 | STATIC bool | ||
61 | xfs_dir3_leaf1_check( | ||
62 | struct xfs_mount *mp, | ||
63 | struct xfs_buf *bp) | ||
64 | { | ||
65 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
66 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
67 | |||
68 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
69 | |||
70 | if (leafhdr.magic == XFS_DIR3_LEAF1_MAGIC) { | ||
71 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
72 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
73 | return false; | ||
74 | } else if (leafhdr.magic != XFS_DIR2_LEAF1_MAGIC) | ||
75 | return false; | ||
76 | |||
77 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
78 | } | ||
79 | #else | ||
80 | #define xfs_dir3_leaf_check(mp, bp) | ||
81 | #endif | ||
82 | |||
83 | void | ||
84 | xfs_dir3_leaf_hdr_from_disk( | ||
85 | struct xfs_dir3_icleaf_hdr *to, | ||
86 | struct xfs_dir2_leaf *from) | ||
87 | { | ||
88 | if (from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | ||
89 | from->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)) { | ||
90 | to->forw = be32_to_cpu(from->hdr.info.forw); | ||
91 | to->back = be32_to_cpu(from->hdr.info.back); | ||
92 | to->magic = be16_to_cpu(from->hdr.info.magic); | ||
93 | to->count = be16_to_cpu(from->hdr.count); | ||
94 | to->stale = be16_to_cpu(from->hdr.stale); | ||
95 | } else { | ||
96 | struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)from; | ||
97 | |||
98 | to->forw = be32_to_cpu(hdr3->info.hdr.forw); | ||
99 | to->back = be32_to_cpu(hdr3->info.hdr.back); | ||
100 | to->magic = be16_to_cpu(hdr3->info.hdr.magic); | ||
101 | to->count = be16_to_cpu(hdr3->count); | ||
102 | to->stale = be16_to_cpu(hdr3->stale); | ||
103 | } | ||
104 | |||
105 | ASSERT(to->magic == XFS_DIR2_LEAF1_MAGIC || | ||
106 | to->magic == XFS_DIR3_LEAF1_MAGIC || | ||
107 | to->magic == XFS_DIR2_LEAFN_MAGIC || | ||
108 | to->magic == XFS_DIR3_LEAFN_MAGIC); | ||
109 | } | ||
110 | |||
111 | void | ||
112 | xfs_dir3_leaf_hdr_to_disk( | ||
113 | struct xfs_dir2_leaf *to, | ||
114 | struct xfs_dir3_icleaf_hdr *from) | ||
115 | { | ||
116 | ASSERT(from->magic == XFS_DIR2_LEAF1_MAGIC || | ||
117 | from->magic == XFS_DIR3_LEAF1_MAGIC || | ||
118 | from->magic == XFS_DIR2_LEAFN_MAGIC || | ||
119 | from->magic == XFS_DIR3_LEAFN_MAGIC); | ||
120 | |||
121 | if (from->magic == XFS_DIR2_LEAF1_MAGIC || | ||
122 | from->magic == XFS_DIR2_LEAFN_MAGIC) { | ||
123 | to->hdr.info.forw = cpu_to_be32(from->forw); | ||
124 | to->hdr.info.back = cpu_to_be32(from->back); | ||
125 | to->hdr.info.magic = cpu_to_be16(from->magic); | ||
126 | to->hdr.count = cpu_to_be16(from->count); | ||
127 | to->hdr.stale = cpu_to_be16(from->stale); | ||
128 | } else { | ||
129 | struct xfs_dir3_leaf_hdr *hdr3 = (struct xfs_dir3_leaf_hdr *)to; | ||
130 | |||
131 | hdr3->info.hdr.forw = cpu_to_be32(from->forw); | ||
132 | hdr3->info.hdr.back = cpu_to_be32(from->back); | ||
133 | hdr3->info.hdr.magic = cpu_to_be16(from->magic); | ||
134 | hdr3->count = cpu_to_be16(from->count); | ||
135 | hdr3->stale = cpu_to_be16(from->stale); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | bool | ||
140 | xfs_dir3_leaf_check_int( | ||
141 | struct xfs_mount *mp, | ||
142 | struct xfs_dir3_icleaf_hdr *hdr, | ||
143 | struct xfs_dir2_leaf *leaf) | ||
144 | { | ||
145 | struct xfs_dir2_leaf_entry *ents; | ||
146 | xfs_dir2_leaf_tail_t *ltp; | ||
147 | int stale; | ||
148 | int i; | ||
149 | |||
150 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
151 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
152 | |||
153 | /* | ||
154 | * XXX (dgc): This value is not restrictive enough. | ||
155 | * Should factor in the size of the bests table as well. | ||
156 | * We can deduce a value for that from di_size. | ||
157 | */ | ||
158 | if (hdr->count > xfs_dir3_max_leaf_ents(mp, leaf)) | ||
159 | return false; | ||
160 | |||
161 | /* Leaves and bests don't overlap in leaf format. */ | ||
162 | if ((hdr->magic == XFS_DIR2_LEAF1_MAGIC || | ||
163 | hdr->magic == XFS_DIR3_LEAF1_MAGIC) && | ||
164 | (char *)&ents[hdr->count] > (char *)xfs_dir2_leaf_bests_p(ltp)) | ||
165 | return false; | ||
166 | |||
167 | /* Check hash value order, count stale entries. */ | ||
168 | for (i = stale = 0; i < hdr->count; i++) { | ||
169 | if (i + 1 < hdr->count) { | ||
170 | if (be32_to_cpu(ents[i].hashval) > | ||
171 | be32_to_cpu(ents[i + 1].hashval)) | ||
172 | return false; | ||
173 | } | ||
174 | if (ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
175 | stale++; | ||
176 | } | ||
177 | if (hdr->stale != stale) | ||
178 | return false; | ||
179 | return true; | ||
180 | } | ||
181 | |||
182 | static bool | ||
183 | xfs_dir3_leaf_verify( | ||
53 | struct xfs_buf *bp, | 184 | struct xfs_buf *bp, |
54 | __be16 magic) | 185 | __uint16_t magic) |
186 | { | ||
187 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
188 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
189 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
190 | |||
191 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); | ||
192 | |||
193 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
194 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
195 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
196 | |||
197 | if ((magic == XFS_DIR2_LEAF1_MAGIC && | ||
198 | leafhdr.magic != XFS_DIR3_LEAF1_MAGIC) || | ||
199 | (magic == XFS_DIR2_LEAFN_MAGIC && | ||
200 | leafhdr.magic != XFS_DIR3_LEAFN_MAGIC)) | ||
201 | return false; | ||
202 | |||
203 | if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) | ||
204 | return false; | ||
205 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
206 | return false; | ||
207 | } else { | ||
208 | if (leafhdr.magic != magic) | ||
209 | return false; | ||
210 | } | ||
211 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | __read_verify( | ||
216 | struct xfs_buf *bp, | ||
217 | __uint16_t magic) | ||
218 | { | ||
219 | struct xfs_mount *mp = bp->b_target->bt_mount; | ||
220 | |||
221 | if ((xfs_sb_version_hascrc(&mp->m_sb) && | ||
222 | !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length), | ||
223 | XFS_DIR3_LEAF_CRC_OFF)) || | ||
224 | !xfs_dir3_leaf_verify(bp, magic)) { | ||
225 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); | ||
226 | xfs_buf_ioerror(bp, EFSCORRUPTED); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | static void | ||
231 | __write_verify( | ||
232 | struct xfs_buf *bp, | ||
233 | __uint16_t magic) | ||
55 | { | 234 | { |
56 | struct xfs_mount *mp = bp->b_target->bt_mount; | 235 | struct xfs_mount *mp = bp->b_target->bt_mount; |
57 | struct xfs_dir2_leaf_hdr *hdr = bp->b_addr; | 236 | struct xfs_buf_log_item *bip = bp->b_fspriv; |
58 | int block_ok = 0; | 237 | struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; |
59 | 238 | ||
60 | block_ok = hdr->info.magic == magic; | 239 | if (!xfs_dir3_leaf_verify(bp, magic)) { |
61 | if (!block_ok) { | 240 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); |
62 | XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); | ||
63 | xfs_buf_ioerror(bp, EFSCORRUPTED); | 241 | xfs_buf_ioerror(bp, EFSCORRUPTED); |
242 | return; | ||
64 | } | 243 | } |
244 | |||
245 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | ||
246 | return; | ||
247 | |||
248 | if (bip) | ||
249 | hdr3->info.lsn = cpu_to_be64(bip->bli_item.li_lsn); | ||
250 | |||
251 | xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_LEAF_CRC_OFF); | ||
65 | } | 252 | } |
66 | 253 | ||
67 | static void | 254 | static void |
68 | xfs_dir2_leaf1_read_verify( | 255 | xfs_dir3_leaf1_read_verify( |
69 | struct xfs_buf *bp) | 256 | struct xfs_buf *bp) |
70 | { | 257 | { |
71 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 258 | __read_verify(bp, XFS_DIR2_LEAF1_MAGIC); |
72 | } | 259 | } |
73 | 260 | ||
74 | static void | 261 | static void |
75 | xfs_dir2_leaf1_write_verify( | 262 | xfs_dir3_leaf1_write_verify( |
76 | struct xfs_buf *bp) | 263 | struct xfs_buf *bp) |
77 | { | 264 | { |
78 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 265 | __write_verify(bp, XFS_DIR2_LEAF1_MAGIC); |
79 | } | 266 | } |
80 | 267 | ||
81 | void | 268 | static void |
82 | xfs_dir2_leafn_read_verify( | 269 | xfs_dir3_leafn_read_verify( |
83 | struct xfs_buf *bp) | 270 | struct xfs_buf *bp) |
84 | { | 271 | { |
85 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 272 | __read_verify(bp, XFS_DIR2_LEAFN_MAGIC); |
86 | } | 273 | } |
87 | 274 | ||
88 | void | 275 | static void |
89 | xfs_dir2_leafn_write_verify( | 276 | xfs_dir3_leafn_write_verify( |
90 | struct xfs_buf *bp) | 277 | struct xfs_buf *bp) |
91 | { | 278 | { |
92 | xfs_dir2_leaf_verify(bp, cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 279 | __write_verify(bp, XFS_DIR2_LEAFN_MAGIC); |
93 | } | 280 | } |
94 | 281 | ||
95 | static const struct xfs_buf_ops xfs_dir2_leaf1_buf_ops = { | 282 | static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = { |
96 | .verify_read = xfs_dir2_leaf1_read_verify, | 283 | .verify_read = xfs_dir3_leaf1_read_verify, |
97 | .verify_write = xfs_dir2_leaf1_write_verify, | 284 | .verify_write = xfs_dir3_leaf1_write_verify, |
98 | }; | 285 | }; |
99 | 286 | ||
100 | const struct xfs_buf_ops xfs_dir2_leafn_buf_ops = { | 287 | const struct xfs_buf_ops xfs_dir3_leafn_buf_ops = { |
101 | .verify_read = xfs_dir2_leafn_read_verify, | 288 | .verify_read = xfs_dir3_leafn_read_verify, |
102 | .verify_write = xfs_dir2_leafn_write_verify, | 289 | .verify_write = xfs_dir3_leafn_write_verify, |
103 | }; | 290 | }; |
104 | 291 | ||
105 | static int | 292 | static int |
106 | xfs_dir2_leaf_read( | 293 | xfs_dir3_leaf_read( |
107 | struct xfs_trans *tp, | 294 | struct xfs_trans *tp, |
108 | struct xfs_inode *dp, | 295 | struct xfs_inode *dp, |
109 | xfs_dablk_t fbno, | 296 | xfs_dablk_t fbno, |
@@ -111,11 +298,11 @@ xfs_dir2_leaf_read( | |||
111 | struct xfs_buf **bpp) | 298 | struct xfs_buf **bpp) |
112 | { | 299 | { |
113 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | 300 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
114 | XFS_DATA_FORK, &xfs_dir2_leaf1_buf_ops); | 301 | XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops); |
115 | } | 302 | } |
116 | 303 | ||
117 | int | 304 | int |
118 | xfs_dir2_leafn_read( | 305 | xfs_dir3_leafn_read( |
119 | struct xfs_trans *tp, | 306 | struct xfs_trans *tp, |
120 | struct xfs_inode *dp, | 307 | struct xfs_inode *dp, |
121 | xfs_dablk_t fbno, | 308 | xfs_dablk_t fbno, |
@@ -123,7 +310,81 @@ xfs_dir2_leafn_read( | |||
123 | struct xfs_buf **bpp) | 310 | struct xfs_buf **bpp) |
124 | { | 311 | { |
125 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, | 312 | return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
126 | XFS_DATA_FORK, &xfs_dir2_leafn_buf_ops); | 313 | XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops); |
314 | } | ||
315 | |||
316 | /* | ||
317 | * Initialize a new leaf block, leaf1 or leafn magic accepted. | ||
318 | */ | ||
319 | static void | ||
320 | xfs_dir3_leaf_init( | ||
321 | struct xfs_mount *mp, | ||
322 | struct xfs_buf *bp, | ||
323 | xfs_ino_t owner, | ||
324 | __uint16_t type) | ||
325 | { | ||
326 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
327 | |||
328 | ASSERT(type == XFS_DIR2_LEAF1_MAGIC || type == XFS_DIR2_LEAFN_MAGIC); | ||
329 | |||
330 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | ||
331 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
332 | |||
333 | memset(leaf3, 0, sizeof(*leaf3)); | ||
334 | |||
335 | leaf3->info.hdr.magic = (type == XFS_DIR2_LEAF1_MAGIC) | ||
336 | ? cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) | ||
337 | : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | ||
338 | leaf3->info.blkno = cpu_to_be64(bp->b_bn); | ||
339 | leaf3->info.owner = cpu_to_be64(owner); | ||
340 | uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_uuid); | ||
341 | } else { | ||
342 | memset(leaf, 0, sizeof(*leaf)); | ||
343 | leaf->hdr.info.magic = cpu_to_be16(type); | ||
344 | } | ||
345 | |||
346 | /* | ||
347 | * If it's a leaf-format directory initialize the tail. | ||
348 | * Caller is responsible for initialising the bests table. | ||
349 | */ | ||
350 | if (type == XFS_DIR2_LEAF1_MAGIC) { | ||
351 | struct xfs_dir2_leaf_tail *ltp; | ||
352 | |||
353 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
354 | ltp->bestcount = 0; | ||
355 | bp->b_ops = &xfs_dir3_leaf1_buf_ops; | ||
356 | } else | ||
357 | bp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
358 | } | ||
359 | |||
360 | int | ||
361 | xfs_dir3_leaf_get_buf( | ||
362 | xfs_da_args_t *args, | ||
363 | xfs_dir2_db_t bno, | ||
364 | struct xfs_buf **bpp, | ||
365 | __uint16_t magic) | ||
366 | { | ||
367 | struct xfs_inode *dp = args->dp; | ||
368 | struct xfs_trans *tp = args->trans; | ||
369 | struct xfs_mount *mp = dp->i_mount; | ||
370 | struct xfs_buf *bp; | ||
371 | int error; | ||
372 | |||
373 | ASSERT(magic == XFS_DIR2_LEAF1_MAGIC || magic == XFS_DIR2_LEAFN_MAGIC); | ||
374 | ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) && | ||
375 | bno < XFS_DIR2_FREE_FIRSTDB(mp)); | ||
376 | |||
377 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, | ||
378 | XFS_DATA_FORK); | ||
379 | if (error) | ||
380 | return error; | ||
381 | |||
382 | xfs_dir3_leaf_init(mp, bp, dp->i_ino, magic); | ||
383 | xfs_dir3_leaf_log_header(tp, bp); | ||
384 | if (magic == XFS_DIR2_LEAF1_MAGIC) | ||
385 | xfs_dir3_leaf_log_tail(tp, bp); | ||
386 | *bpp = bp; | ||
387 | return 0; | ||
127 | } | 388 | } |
128 | 389 | ||
129 | /* | 390 | /* |
@@ -150,6 +411,8 @@ xfs_dir2_block_to_leaf( | |||
150 | int needscan; /* need to rescan bestfree */ | 411 | int needscan; /* need to rescan bestfree */ |
151 | xfs_trans_t *tp; /* transaction pointer */ | 412 | xfs_trans_t *tp; /* transaction pointer */ |
152 | struct xfs_dir2_data_free *bf; | 413 | struct xfs_dir2_data_free *bf; |
414 | struct xfs_dir2_leaf_entry *ents; | ||
415 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
153 | 416 | ||
154 | trace_xfs_dir2_block_to_leaf(args); | 417 | trace_xfs_dir2_block_to_leaf(args); |
155 | 418 | ||
@@ -169,27 +432,33 @@ xfs_dir2_block_to_leaf( | |||
169 | /* | 432 | /* |
170 | * Initialize the leaf block, get a buffer for it. | 433 | * Initialize the leaf block, get a buffer for it. |
171 | */ | 434 | */ |
172 | if ((error = xfs_dir2_leaf_init(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC))) { | 435 | error = xfs_dir3_leaf_get_buf(args, ldb, &lbp, XFS_DIR2_LEAF1_MAGIC); |
436 | if (error) | ||
173 | return error; | 437 | return error; |
174 | } | 438 | |
175 | ASSERT(lbp != NULL); | ||
176 | leaf = lbp->b_addr; | 439 | leaf = lbp->b_addr; |
177 | hdr = dbp->b_addr; | 440 | hdr = dbp->b_addr; |
178 | xfs_dir3_data_check(dp, dbp); | 441 | xfs_dir3_data_check(dp, dbp); |
179 | btp = xfs_dir2_block_tail_p(mp, hdr); | 442 | btp = xfs_dir2_block_tail_p(mp, hdr); |
180 | blp = xfs_dir2_block_leaf_p(btp); | 443 | blp = xfs_dir2_block_leaf_p(btp); |
181 | bf = xfs_dir3_data_bestfree_p(hdr); | 444 | bf = xfs_dir3_data_bestfree_p(hdr); |
445 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
446 | |||
182 | /* | 447 | /* |
183 | * Set the counts in the leaf header. | 448 | * Set the counts in the leaf header. |
184 | */ | 449 | */ |
185 | leaf->hdr.count = cpu_to_be16(be32_to_cpu(btp->count)); | 450 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
186 | leaf->hdr.stale = cpu_to_be16(be32_to_cpu(btp->stale)); | 451 | leafhdr.count = be32_to_cpu(btp->count); |
452 | leafhdr.stale = be32_to_cpu(btp->stale); | ||
453 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); | ||
454 | xfs_dir3_leaf_log_header(tp, lbp); | ||
455 | |||
187 | /* | 456 | /* |
188 | * Could compact these but I think we always do the conversion | 457 | * Could compact these but I think we always do the conversion |
189 | * after squeezing out stale entries. | 458 | * after squeezing out stale entries. |
190 | */ | 459 | */ |
191 | memcpy(leaf->ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); | 460 | memcpy(ents, blp, be32_to_cpu(btp->count) * sizeof(xfs_dir2_leaf_entry_t)); |
192 | xfs_dir2_leaf_log_ents(tp, lbp, 0, be16_to_cpu(leaf->hdr.count) - 1); | 461 | xfs_dir3_leaf_log_ents(tp, lbp, 0, leafhdr.count - 1); |
193 | needscan = 0; | 462 | needscan = 0; |
194 | needlog = 1; | 463 | needlog = 1; |
195 | /* | 464 | /* |
@@ -224,15 +493,16 @@ xfs_dir2_block_to_leaf( | |||
224 | */ | 493 | */ |
225 | if (needlog) | 494 | if (needlog) |
226 | xfs_dir2_data_log_header(tp, dbp); | 495 | xfs_dir2_data_log_header(tp, dbp); |
227 | xfs_dir2_leaf_check(dp, lbp); | 496 | xfs_dir3_leaf_check(mp, lbp); |
228 | xfs_dir3_data_check(dp, dbp); | 497 | xfs_dir3_data_check(dp, dbp); |
229 | xfs_dir2_leaf_log_bests(tp, lbp, 0, 0); | 498 | xfs_dir3_leaf_log_bests(tp, lbp, 0, 0); |
230 | return 0; | 499 | return 0; |
231 | } | 500 | } |
232 | 501 | ||
233 | STATIC void | 502 | STATIC void |
234 | xfs_dir2_leaf_find_stale( | 503 | xfs_dir3_leaf_find_stale( |
235 | struct xfs_dir2_leaf *leaf, | 504 | struct xfs_dir3_icleaf_hdr *leafhdr, |
505 | struct xfs_dir2_leaf_entry *ents, | ||
236 | int index, | 506 | int index, |
237 | int *lowstale, | 507 | int *lowstale, |
238 | int *highstale) | 508 | int *highstale) |
@@ -241,7 +511,7 @@ xfs_dir2_leaf_find_stale( | |||
241 | * Find the first stale entry before our index, if any. | 511 | * Find the first stale entry before our index, if any. |
242 | */ | 512 | */ |
243 | for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) { | 513 | for (*lowstale = index - 1; *lowstale >= 0; --*lowstale) { |
244 | if (leaf->ents[*lowstale].address == | 514 | if (ents[*lowstale].address == |
245 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 515 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
246 | break; | 516 | break; |
247 | } | 517 | } |
@@ -251,10 +521,8 @@ xfs_dir2_leaf_find_stale( | |||
251 | * Stop if the result would require moving more entries than using | 521 | * Stop if the result would require moving more entries than using |
252 | * lowstale. | 522 | * lowstale. |
253 | */ | 523 | */ |
254 | for (*highstale = index; | 524 | for (*highstale = index; *highstale < leafhdr->count; ++*highstale) { |
255 | *highstale < be16_to_cpu(leaf->hdr.count); | 525 | if (ents[*highstale].address == |
256 | ++*highstale) { | ||
257 | if (leaf->ents[*highstale].address == | ||
258 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 526 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
259 | break; | 527 | break; |
260 | if (*lowstale >= 0 && index - *lowstale <= *highstale - index) | 528 | if (*lowstale >= 0 && index - *lowstale <= *highstale - index) |
@@ -263,8 +531,9 @@ xfs_dir2_leaf_find_stale( | |||
263 | } | 531 | } |
264 | 532 | ||
265 | struct xfs_dir2_leaf_entry * | 533 | struct xfs_dir2_leaf_entry * |
266 | xfs_dir2_leaf_find_entry( | 534 | xfs_dir3_leaf_find_entry( |
267 | xfs_dir2_leaf_t *leaf, /* leaf structure */ | 535 | struct xfs_dir3_icleaf_hdr *leafhdr, |
536 | struct xfs_dir2_leaf_entry *ents, | ||
268 | int index, /* leaf table position */ | 537 | int index, /* leaf table position */ |
269 | int compact, /* need to compact leaves */ | 538 | int compact, /* need to compact leaves */ |
270 | int lowstale, /* index of prev stale leaf */ | 539 | int lowstale, /* index of prev stale leaf */ |
@@ -272,7 +541,7 @@ xfs_dir2_leaf_find_entry( | |||
272 | int *lfloglow, /* low leaf logging index */ | 541 | int *lfloglow, /* low leaf logging index */ |
273 | int *lfloghigh) /* high leaf logging index */ | 542 | int *lfloghigh) /* high leaf logging index */ |
274 | { | 543 | { |
275 | if (!leaf->hdr.stale) { | 544 | if (!leafhdr->stale) { |
276 | xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ | 545 | xfs_dir2_leaf_entry_t *lep; /* leaf entry table pointer */ |
277 | 546 | ||
278 | /* | 547 | /* |
@@ -280,18 +549,16 @@ xfs_dir2_leaf_find_entry( | |||
280 | * | 549 | * |
281 | * If there are no stale entries, just insert a hole at index. | 550 | * If there are no stale entries, just insert a hole at index. |
282 | */ | 551 | */ |
283 | lep = &leaf->ents[index]; | 552 | lep = &ents[index]; |
284 | if (index < be16_to_cpu(leaf->hdr.count)) | 553 | if (index < leafhdr->count) |
285 | memmove(lep + 1, lep, | 554 | memmove(lep + 1, lep, |
286 | (be16_to_cpu(leaf->hdr.count) - index) * | 555 | (leafhdr->count - index) * sizeof(*lep)); |
287 | sizeof(*lep)); | ||
288 | 556 | ||
289 | /* | 557 | /* |
290 | * Record low and high logging indices for the leaf. | 558 | * Record low and high logging indices for the leaf. |
291 | */ | 559 | */ |
292 | *lfloglow = index; | 560 | *lfloglow = index; |
293 | *lfloghigh = be16_to_cpu(leaf->hdr.count); | 561 | *lfloghigh = leafhdr->count++; |
294 | be16_add_cpu(&leaf->hdr.count, 1); | ||
295 | return lep; | 562 | return lep; |
296 | } | 563 | } |
297 | 564 | ||
@@ -305,16 +572,17 @@ xfs_dir2_leaf_find_entry( | |||
305 | * entries before and after our insertion point. | 572 | * entries before and after our insertion point. |
306 | */ | 573 | */ |
307 | if (compact == 0) | 574 | if (compact == 0) |
308 | xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale); | 575 | xfs_dir3_leaf_find_stale(leafhdr, ents, index, |
576 | &lowstale, &highstale); | ||
309 | 577 | ||
310 | /* | 578 | /* |
311 | * If the low one is better, use it. | 579 | * If the low one is better, use it. |
312 | */ | 580 | */ |
313 | if (lowstale >= 0 && | 581 | if (lowstale >= 0 && |
314 | (highstale == be16_to_cpu(leaf->hdr.count) || | 582 | (highstale == leafhdr->count || |
315 | index - lowstale - 1 < highstale - index)) { | 583 | index - lowstale - 1 < highstale - index)) { |
316 | ASSERT(index - lowstale - 1 >= 0); | 584 | ASSERT(index - lowstale - 1 >= 0); |
317 | ASSERT(leaf->ents[lowstale].address == | 585 | ASSERT(ents[lowstale].address == |
318 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); | 586 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); |
319 | 587 | ||
320 | /* | 588 | /* |
@@ -322,37 +590,34 @@ xfs_dir2_leaf_find_entry( | |||
322 | * for the new entry. | 590 | * for the new entry. |
323 | */ | 591 | */ |
324 | if (index - lowstale - 1 > 0) { | 592 | if (index - lowstale - 1 > 0) { |
325 | memmove(&leaf->ents[lowstale], | 593 | memmove(&ents[lowstale], &ents[lowstale + 1], |
326 | &leaf->ents[lowstale + 1], | ||
327 | (index - lowstale - 1) * | 594 | (index - lowstale - 1) * |
328 | sizeof(xfs_dir2_leaf_entry_t)); | 595 | sizeof(xfs_dir2_leaf_entry_t)); |
329 | } | 596 | } |
330 | *lfloglow = MIN(lowstale, *lfloglow); | 597 | *lfloglow = MIN(lowstale, *lfloglow); |
331 | *lfloghigh = MAX(index - 1, *lfloghigh); | 598 | *lfloghigh = MAX(index - 1, *lfloghigh); |
332 | be16_add_cpu(&leaf->hdr.stale, -1); | 599 | leafhdr->stale--; |
333 | return &leaf->ents[index - 1]; | 600 | return &ents[index - 1]; |
334 | } | 601 | } |
335 | 602 | ||
336 | /* | 603 | /* |
337 | * The high one is better, so use that one. | 604 | * The high one is better, so use that one. |
338 | */ | 605 | */ |
339 | ASSERT(highstale - index >= 0); | 606 | ASSERT(highstale - index >= 0); |
340 | ASSERT(leaf->ents[highstale].address == | 607 | ASSERT(ents[highstale].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); |
341 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)); | ||
342 | 608 | ||
343 | /* | 609 | /* |
344 | * Copy entries down to cover the stale entry and make room for the | 610 | * Copy entries down to cover the stale entry and make room for the |
345 | * new entry. | 611 | * new entry. |
346 | */ | 612 | */ |
347 | if (highstale - index > 0) { | 613 | if (highstale - index > 0) { |
348 | memmove(&leaf->ents[index + 1], | 614 | memmove(&ents[index + 1], &ents[index], |
349 | &leaf->ents[index], | ||
350 | (highstale - index) * sizeof(xfs_dir2_leaf_entry_t)); | 615 | (highstale - index) * sizeof(xfs_dir2_leaf_entry_t)); |
351 | } | 616 | } |
352 | *lfloglow = MIN(index, *lfloglow); | 617 | *lfloglow = MIN(index, *lfloglow); |
353 | *lfloghigh = MAX(highstale, *lfloghigh); | 618 | *lfloghigh = MAX(highstale, *lfloghigh); |
354 | be16_add_cpu(&leaf->hdr.stale, -1); | 619 | leafhdr->stale--; |
355 | return &leaf->ents[index]; | 620 | return &ents[index]; |
356 | } | 621 | } |
357 | 622 | ||
358 | /* | 623 | /* |
@@ -390,6 +655,8 @@ xfs_dir2_leaf_addname( | |||
390 | xfs_trans_t *tp; /* transaction pointer */ | 655 | xfs_trans_t *tp; /* transaction pointer */ |
391 | xfs_dir2_db_t use_block; /* data block number */ | 656 | xfs_dir2_db_t use_block; /* data block number */ |
392 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 657 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
658 | struct xfs_dir2_leaf_entry *ents; | ||
659 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
393 | 660 | ||
394 | trace_xfs_dir2_leaf_addname(args); | 661 | trace_xfs_dir2_leaf_addname(args); |
395 | 662 | ||
@@ -397,7 +664,7 @@ xfs_dir2_leaf_addname( | |||
397 | tp = args->trans; | 664 | tp = args->trans; |
398 | mp = dp->i_mount; | 665 | mp = dp->i_mount; |
399 | 666 | ||
400 | error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 667 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); |
401 | if (error) | 668 | if (error) |
402 | return error; | 669 | return error; |
403 | 670 | ||
@@ -410,16 +677,19 @@ xfs_dir2_leaf_addname( | |||
410 | index = xfs_dir2_leaf_search_hash(args, lbp); | 677 | index = xfs_dir2_leaf_search_hash(args, lbp); |
411 | leaf = lbp->b_addr; | 678 | leaf = lbp->b_addr; |
412 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 679 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
680 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
681 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
413 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 682 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
414 | length = xfs_dir2_data_entsize(args->namelen); | 683 | length = xfs_dir2_data_entsize(args->namelen); |
684 | |||
415 | /* | 685 | /* |
416 | * See if there are any entries with the same hash value | 686 | * See if there are any entries with the same hash value |
417 | * and space in their block for the new entry. | 687 | * and space in their block for the new entry. |
418 | * This is good because it puts multiple same-hash value entries | 688 | * This is good because it puts multiple same-hash value entries |
419 | * in a data block, improving the lookup of those entries. | 689 | * in a data block, improving the lookup of those entries. |
420 | */ | 690 | */ |
421 | for (use_block = -1, lep = &leaf->ents[index]; | 691 | for (use_block = -1, lep = &ents[index]; |
422 | index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval; | 692 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
423 | index++, lep++) { | 693 | index++, lep++) { |
424 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) | 694 | if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR) |
425 | continue; | 695 | continue; |
@@ -452,7 +722,7 @@ xfs_dir2_leaf_addname( | |||
452 | * How many bytes do we need in the leaf block? | 722 | * How many bytes do we need in the leaf block? |
453 | */ | 723 | */ |
454 | needbytes = 0; | 724 | needbytes = 0; |
455 | if (!leaf->hdr.stale) | 725 | if (!leafhdr.stale) |
456 | needbytes += sizeof(xfs_dir2_leaf_entry_t); | 726 | needbytes += sizeof(xfs_dir2_leaf_entry_t); |
457 | if (use_block == -1) | 727 | if (use_block == -1) |
458 | needbytes += sizeof(xfs_dir2_data_off_t); | 728 | needbytes += sizeof(xfs_dir2_data_off_t); |
@@ -467,16 +737,15 @@ xfs_dir2_leaf_addname( | |||
467 | * If we don't have enough free bytes but we can make enough | 737 | * If we don't have enough free bytes but we can make enough |
468 | * by compacting out stale entries, we'll do that. | 738 | * by compacting out stale entries, we'll do that. |
469 | */ | 739 | */ |
470 | if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] < | 740 | if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes && |
471 | needbytes && be16_to_cpu(leaf->hdr.stale) > 1) { | 741 | leafhdr.stale > 1) |
472 | compact = 1; | 742 | compact = 1; |
473 | } | 743 | |
474 | /* | 744 | /* |
475 | * Otherwise if we don't have enough free bytes we need to | 745 | * Otherwise if we don't have enough free bytes we need to |
476 | * convert to node form. | 746 | * convert to node form. |
477 | */ | 747 | */ |
478 | else if ((char *)bestsp - (char *)&leaf->ents[be16_to_cpu( | 748 | else if ((char *)bestsp - (char *)&ents[leafhdr.count] < needbytes) { |
479 | leaf->hdr.count)] < needbytes) { | ||
480 | /* | 749 | /* |
481 | * Just checking or no space reservation, give up. | 750 | * Just checking or no space reservation, give up. |
482 | */ | 751 | */ |
@@ -524,15 +793,15 @@ xfs_dir2_leaf_addname( | |||
524 | * point later. | 793 | * point later. |
525 | */ | 794 | */ |
526 | if (compact) { | 795 | if (compact) { |
527 | xfs_dir2_leaf_compact_x1(lbp, &index, &lowstale, &highstale, | 796 | xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, |
528 | &lfloglow, &lfloghigh); | 797 | &highstale, &lfloglow, &lfloghigh); |
529 | } | 798 | } |
530 | /* | 799 | /* |
531 | * There are stale entries, so we'll need log-low and log-high | 800 | * There are stale entries, so we'll need log-low and log-high |
532 | * impossibly bad values later. | 801 | * impossibly bad values later. |
533 | */ | 802 | */ |
534 | else if (be16_to_cpu(leaf->hdr.stale)) { | 803 | else if (leafhdr.stale) { |
535 | lfloglow = be16_to_cpu(leaf->hdr.count); | 804 | lfloglow = leafhdr.count; |
536 | lfloghigh = -1; | 805 | lfloghigh = -1; |
537 | } | 806 | } |
538 | /* | 807 | /* |
@@ -564,14 +833,14 @@ xfs_dir2_leaf_addname( | |||
564 | memmove(&bestsp[0], &bestsp[1], | 833 | memmove(&bestsp[0], &bestsp[1], |
565 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); | 834 | be32_to_cpu(ltp->bestcount) * sizeof(bestsp[0])); |
566 | be32_add_cpu(<p->bestcount, 1); | 835 | be32_add_cpu(<p->bestcount, 1); |
567 | xfs_dir2_leaf_log_tail(tp, lbp); | 836 | xfs_dir3_leaf_log_tail(tp, lbp); |
568 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 837 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
569 | } | 838 | } |
570 | /* | 839 | /* |
571 | * If we're filling in a previously empty block just log it. | 840 | * If we're filling in a previously empty block just log it. |
572 | */ | 841 | */ |
573 | else | 842 | else |
574 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 843 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); |
575 | hdr = dbp->b_addr; | 844 | hdr = dbp->b_addr; |
576 | bf = xfs_dir3_data_bestfree_p(hdr); | 845 | bf = xfs_dir3_data_bestfree_p(hdr); |
577 | bestsp[use_block] = bf[0].length; | 846 | bestsp[use_block] = bf[0].length; |
@@ -632,10 +901,10 @@ xfs_dir2_leaf_addname( | |||
632 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { | 901 | if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) { |
633 | bestsp[use_block] = bf[0].length; | 902 | bestsp[use_block] = bf[0].length; |
634 | if (!grown) | 903 | if (!grown) |
635 | xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block); | 904 | xfs_dir3_leaf_log_bests(tp, lbp, use_block, use_block); |
636 | } | 905 | } |
637 | 906 | ||
638 | lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale, | 907 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, |
639 | highstale, &lfloglow, &lfloghigh); | 908 | highstale, &lfloglow, &lfloghigh); |
640 | 909 | ||
641 | /* | 910 | /* |
@@ -647,82 +916,40 @@ xfs_dir2_leaf_addname( | |||
647 | /* | 916 | /* |
648 | * Log the leaf fields and give up the buffers. | 917 | * Log the leaf fields and give up the buffers. |
649 | */ | 918 | */ |
650 | xfs_dir2_leaf_log_header(tp, lbp); | 919 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
651 | xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); | 920 | xfs_dir3_leaf_log_header(tp, lbp); |
652 | xfs_dir2_leaf_check(dp, lbp); | 921 | xfs_dir3_leaf_log_ents(tp, lbp, lfloglow, lfloghigh); |
922 | xfs_dir3_leaf_check(mp, lbp); | ||
653 | xfs_dir3_data_check(dp, dbp); | 923 | xfs_dir3_data_check(dp, dbp); |
654 | return 0; | 924 | return 0; |
655 | } | 925 | } |
656 | 926 | ||
657 | #ifdef DEBUG | ||
658 | /* | ||
659 | * Check the internal consistency of a leaf1 block. | ||
660 | * Pop an assert if something is wrong. | ||
661 | */ | ||
662 | STATIC void | ||
663 | xfs_dir2_leaf_check( | ||
664 | struct xfs_inode *dp, /* incore directory inode */ | ||
665 | struct xfs_buf *bp) /* leaf's buffer */ | ||
666 | { | ||
667 | int i; /* leaf index */ | ||
668 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
669 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail pointer */ | ||
670 | xfs_mount_t *mp; /* filesystem mount point */ | ||
671 | int stale; /* count of stale leaves */ | ||
672 | |||
673 | leaf = bp->b_addr; | ||
674 | mp = dp->i_mount; | ||
675 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | ||
676 | /* | ||
677 | * This value is not restrictive enough. | ||
678 | * Should factor in the size of the bests table as well. | ||
679 | * We can deduce a value for that from di_size. | ||
680 | */ | ||
681 | ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp)); | ||
682 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
683 | /* | ||
684 | * Leaves and bests don't overlap. | ||
685 | */ | ||
686 | ASSERT((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] <= | ||
687 | (char *)xfs_dir2_leaf_bests_p(ltp)); | ||
688 | /* | ||
689 | * Check hash value order, count stale entries. | ||
690 | */ | ||
691 | for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { | ||
692 | if (i + 1 < be16_to_cpu(leaf->hdr.count)) | ||
693 | ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= | ||
694 | be32_to_cpu(leaf->ents[i + 1].hashval)); | ||
695 | if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
696 | stale++; | ||
697 | } | ||
698 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); | ||
699 | } | ||
700 | #endif /* DEBUG */ | ||
701 | |||
702 | /* | 927 | /* |
703 | * Compact out any stale entries in the leaf. | 928 | * Compact out any stale entries in the leaf. |
704 | * Log the header and changed leaf entries, if any. | 929 | * Log the header and changed leaf entries, if any. |
705 | */ | 930 | */ |
706 | void | 931 | void |
707 | xfs_dir2_leaf_compact( | 932 | xfs_dir3_leaf_compact( |
708 | xfs_da_args_t *args, /* operation arguments */ | 933 | xfs_da_args_t *args, /* operation arguments */ |
934 | struct xfs_dir3_icleaf_hdr *leafhdr, | ||
709 | struct xfs_buf *bp) /* leaf buffer */ | 935 | struct xfs_buf *bp) /* leaf buffer */ |
710 | { | 936 | { |
711 | int from; /* source leaf index */ | 937 | int from; /* source leaf index */ |
712 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 938 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
713 | int loglow; /* first leaf entry to log */ | 939 | int loglow; /* first leaf entry to log */ |
714 | int to; /* target leaf index */ | 940 | int to; /* target leaf index */ |
941 | struct xfs_dir2_leaf_entry *ents; | ||
715 | 942 | ||
716 | leaf = bp->b_addr; | 943 | leaf = bp->b_addr; |
717 | if (!leaf->hdr.stale) { | 944 | if (!leafhdr->stale) |
718 | return; | 945 | return; |
719 | } | 946 | |
720 | /* | 947 | /* |
721 | * Compress out the stale entries in place. | 948 | * Compress out the stale entries in place. |
722 | */ | 949 | */ |
723 | for (from = to = 0, loglow = -1; from < be16_to_cpu(leaf->hdr.count); from++) { | 950 | ents = xfs_dir3_leaf_ents_p(leaf); |
724 | if (leaf->ents[from].address == | 951 | for (from = to = 0, loglow = -1; from < leafhdr->count; from++) { |
725 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 952 | if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
726 | continue; | 953 | continue; |
727 | /* | 954 | /* |
728 | * Only actually copy the entries that are different. | 955 | * Only actually copy the entries that are different. |
@@ -730,19 +957,21 @@ xfs_dir2_leaf_compact( | |||
730 | if (from > to) { | 957 | if (from > to) { |
731 | if (loglow == -1) | 958 | if (loglow == -1) |
732 | loglow = to; | 959 | loglow = to; |
733 | leaf->ents[to] = leaf->ents[from]; | 960 | ents[to] = ents[from]; |
734 | } | 961 | } |
735 | to++; | 962 | to++; |
736 | } | 963 | } |
737 | /* | 964 | /* |
738 | * Update and log the header, log the leaf entries. | 965 | * Update and log the header, log the leaf entries. |
739 | */ | 966 | */ |
740 | ASSERT(be16_to_cpu(leaf->hdr.stale) == from - to); | 967 | ASSERT(leafhdr->stale == from - to); |
741 | be16_add_cpu(&leaf->hdr.count, -(be16_to_cpu(leaf->hdr.stale))); | 968 | leafhdr->count -= leafhdr->stale; |
742 | leaf->hdr.stale = 0; | 969 | leafhdr->stale = 0; |
743 | xfs_dir2_leaf_log_header(args->trans, bp); | 970 | |
971 | xfs_dir3_leaf_hdr_to_disk(leaf, leafhdr); | ||
972 | xfs_dir3_leaf_log_header(args->trans, bp); | ||
744 | if (loglow != -1) | 973 | if (loglow != -1) |
745 | xfs_dir2_leaf_log_ents(args->trans, bp, loglow, to - 1); | 974 | xfs_dir3_leaf_log_ents(args->trans, bp, loglow, to - 1); |
746 | } | 975 | } |
747 | 976 | ||
748 | /* | 977 | /* |
@@ -754,8 +983,9 @@ xfs_dir2_leaf_compact( | |||
754 | * and leaf logging indices. | 983 | * and leaf logging indices. |
755 | */ | 984 | */ |
756 | void | 985 | void |
757 | xfs_dir2_leaf_compact_x1( | 986 | xfs_dir3_leaf_compact_x1( |
758 | struct xfs_buf *bp, /* leaf buffer */ | 987 | struct xfs_dir3_icleaf_hdr *leafhdr, |
988 | struct xfs_dir2_leaf_entry *ents, | ||
759 | int *indexp, /* insertion index */ | 989 | int *indexp, /* insertion index */ |
760 | int *lowstalep, /* out: stale entry before us */ | 990 | int *lowstalep, /* out: stale entry before us */ |
761 | int *highstalep, /* out: stale entry after us */ | 991 | int *highstalep, /* out: stale entry after us */ |
@@ -766,22 +996,20 @@ xfs_dir2_leaf_compact_x1( | |||
766 | int highstale; /* stale entry at/after index */ | 996 | int highstale; /* stale entry at/after index */ |
767 | int index; /* insertion index */ | 997 | int index; /* insertion index */ |
768 | int keepstale; /* source index of kept stale */ | 998 | int keepstale; /* source index of kept stale */ |
769 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
770 | int lowstale; /* stale entry before index */ | 999 | int lowstale; /* stale entry before index */ |
771 | int newindex=0; /* new insertion index */ | 1000 | int newindex=0; /* new insertion index */ |
772 | int to; /* destination copy index */ | 1001 | int to; /* destination copy index */ |
773 | 1002 | ||
774 | leaf = bp->b_addr; | 1003 | ASSERT(leafhdr->stale > 1); |
775 | ASSERT(be16_to_cpu(leaf->hdr.stale) > 1); | ||
776 | index = *indexp; | 1004 | index = *indexp; |
777 | 1005 | ||
778 | xfs_dir2_leaf_find_stale(leaf, index, &lowstale, &highstale); | 1006 | xfs_dir3_leaf_find_stale(leafhdr, ents, index, &lowstale, &highstale); |
779 | 1007 | ||
780 | /* | 1008 | /* |
781 | * Pick the better of lowstale and highstale. | 1009 | * Pick the better of lowstale and highstale. |
782 | */ | 1010 | */ |
783 | if (lowstale >= 0 && | 1011 | if (lowstale >= 0 && |
784 | (highstale == be16_to_cpu(leaf->hdr.count) || | 1012 | (highstale == leafhdr->count || |
785 | index - lowstale <= highstale - index)) | 1013 | index - lowstale <= highstale - index)) |
786 | keepstale = lowstale; | 1014 | keepstale = lowstale; |
787 | else | 1015 | else |
@@ -790,15 +1018,14 @@ xfs_dir2_leaf_compact_x1( | |||
790 | * Copy the entries in place, removing all the stale entries | 1018 | * Copy the entries in place, removing all the stale entries |
791 | * except keepstale. | 1019 | * except keepstale. |
792 | */ | 1020 | */ |
793 | for (from = to = 0; from < be16_to_cpu(leaf->hdr.count); from++) { | 1021 | for (from = to = 0; from < leafhdr->count; from++) { |
794 | /* | 1022 | /* |
795 | * Notice the new value of index. | 1023 | * Notice the new value of index. |
796 | */ | 1024 | */ |
797 | if (index == from) | 1025 | if (index == from) |
798 | newindex = to; | 1026 | newindex = to; |
799 | if (from != keepstale && | 1027 | if (from != keepstale && |
800 | leaf->ents[from].address == | 1028 | ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { |
801 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) { | ||
802 | if (from == to) | 1029 | if (from == to) |
803 | *lowlogp = to; | 1030 | *lowlogp = to; |
804 | continue; | 1031 | continue; |
@@ -812,7 +1039,7 @@ xfs_dir2_leaf_compact_x1( | |||
812 | * Copy only the entries that have moved. | 1039 | * Copy only the entries that have moved. |
813 | */ | 1040 | */ |
814 | if (from > to) | 1041 | if (from > to) |
815 | leaf->ents[to] = leaf->ents[from]; | 1042 | ents[to] = ents[from]; |
816 | to++; | 1043 | to++; |
817 | } | 1044 | } |
818 | ASSERT(from > to); | 1045 | ASSERT(from > to); |
@@ -826,8 +1053,8 @@ xfs_dir2_leaf_compact_x1( | |||
826 | /* | 1053 | /* |
827 | * Adjust the leaf header values. | 1054 | * Adjust the leaf header values. |
828 | */ | 1055 | */ |
829 | be16_add_cpu(&leaf->hdr.count, -(from - to)); | 1056 | leafhdr->count -= from - to; |
830 | leaf->hdr.stale = cpu_to_be16(1); | 1057 | leafhdr->stale = 1; |
831 | /* | 1058 | /* |
832 | * Remember the low/high stale value only in the "right" | 1059 | * Remember the low/high stale value only in the "right" |
833 | * direction. | 1060 | * direction. |
@@ -835,8 +1062,8 @@ xfs_dir2_leaf_compact_x1( | |||
835 | if (lowstale >= newindex) | 1062 | if (lowstale >= newindex) |
836 | lowstale = -1; | 1063 | lowstale = -1; |
837 | else | 1064 | else |
838 | highstale = be16_to_cpu(leaf->hdr.count); | 1065 | highstale = leafhdr->count; |
839 | *highlogp = be16_to_cpu(leaf->hdr.count) - 1; | 1066 | *highlogp = leafhdr->count - 1; |
840 | *lowstalep = lowstale; | 1067 | *lowstalep = lowstale; |
841 | *highstalep = highstale; | 1068 | *highstalep = highstale; |
842 | } | 1069 | } |
@@ -1229,69 +1456,12 @@ xfs_dir2_leaf_getdents( | |||
1229 | return error; | 1456 | return error; |
1230 | } | 1457 | } |
1231 | 1458 | ||
1232 | /* | ||
1233 | * Initialize a new leaf block, leaf1 or leafn magic accepted. | ||
1234 | */ | ||
1235 | int | ||
1236 | xfs_dir2_leaf_init( | ||
1237 | xfs_da_args_t *args, /* operation arguments */ | ||
1238 | xfs_dir2_db_t bno, /* directory block number */ | ||
1239 | struct xfs_buf **bpp, /* out: leaf buffer */ | ||
1240 | int magic) /* magic number for block */ | ||
1241 | { | ||
1242 | struct xfs_buf *bp; /* leaf buffer */ | ||
1243 | xfs_inode_t *dp; /* incore directory inode */ | ||
1244 | int error; /* error return code */ | ||
1245 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
1246 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | ||
1247 | xfs_mount_t *mp; /* filesystem mount point */ | ||
1248 | xfs_trans_t *tp; /* transaction pointer */ | ||
1249 | |||
1250 | dp = args->dp; | ||
1251 | ASSERT(dp != NULL); | ||
1252 | tp = args->trans; | ||
1253 | mp = dp->i_mount; | ||
1254 | ASSERT(bno >= XFS_DIR2_LEAF_FIRSTDB(mp) && | ||
1255 | bno < XFS_DIR2_FREE_FIRSTDB(mp)); | ||
1256 | /* | ||
1257 | * Get the buffer for the block. | ||
1258 | */ | ||
1259 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, bno), -1, &bp, | ||
1260 | XFS_DATA_FORK); | ||
1261 | if (error) | ||
1262 | return error; | ||
1263 | |||
1264 | /* | ||
1265 | * Initialize the header. | ||
1266 | */ | ||
1267 | leaf = bp->b_addr; | ||
1268 | leaf->hdr.info.magic = cpu_to_be16(magic); | ||
1269 | leaf->hdr.info.forw = 0; | ||
1270 | leaf->hdr.info.back = 0; | ||
1271 | leaf->hdr.count = 0; | ||
1272 | leaf->hdr.stale = 0; | ||
1273 | xfs_dir2_leaf_log_header(tp, bp); | ||
1274 | /* | ||
1275 | * If it's a leaf-format directory initialize the tail. | ||
1276 | * In this case our caller has the real bests table to copy into | ||
1277 | * the block. | ||
1278 | */ | ||
1279 | if (magic == XFS_DIR2_LEAF1_MAGIC) { | ||
1280 | bp->b_ops = &xfs_dir2_leaf1_buf_ops; | ||
1281 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | ||
1282 | ltp->bestcount = 0; | ||
1283 | xfs_dir2_leaf_log_tail(tp, bp); | ||
1284 | } else | ||
1285 | bp->b_ops = &xfs_dir2_leafn_buf_ops; | ||
1286 | *bpp = bp; | ||
1287 | return 0; | ||
1288 | } | ||
1289 | 1459 | ||
1290 | /* | 1460 | /* |
1291 | * Log the bests entries indicated from a leaf1 block. | 1461 | * Log the bests entries indicated from a leaf1 block. |
1292 | */ | 1462 | */ |
1293 | static void | 1463 | static void |
1294 | xfs_dir2_leaf_log_bests( | 1464 | xfs_dir3_leaf_log_bests( |
1295 | xfs_trans_t *tp, /* transaction pointer */ | 1465 | xfs_trans_t *tp, /* transaction pointer */ |
1296 | struct xfs_buf *bp, /* leaf buffer */ | 1466 | struct xfs_buf *bp, /* leaf buffer */ |
1297 | int first, /* first entry to log */ | 1467 | int first, /* first entry to log */ |
@@ -1299,11 +1469,12 @@ xfs_dir2_leaf_log_bests( | |||
1299 | { | 1469 | { |
1300 | __be16 *firstb; /* pointer to first entry */ | 1470 | __be16 *firstb; /* pointer to first entry */ |
1301 | __be16 *lastb; /* pointer to last entry */ | 1471 | __be16 *lastb; /* pointer to last entry */ |
1302 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1472 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1303 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | 1473 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
1304 | 1474 | ||
1305 | leaf = bp->b_addr; | 1475 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1306 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | 1476 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC)); |
1477 | |||
1307 | ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); | 1478 | ltp = xfs_dir2_leaf_tail_p(tp->t_mountp, leaf); |
1308 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; | 1479 | firstb = xfs_dir2_leaf_bests_p(ltp) + first; |
1309 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; | 1480 | lastb = xfs_dir2_leaf_bests_p(ltp) + last; |
@@ -1315,7 +1486,7 @@ xfs_dir2_leaf_log_bests( | |||
1315 | * Log the leaf entries indicated from a leaf1 or leafn block. | 1486 | * Log the leaf entries indicated from a leaf1 or leafn block. |
1316 | */ | 1487 | */ |
1317 | void | 1488 | void |
1318 | xfs_dir2_leaf_log_ents( | 1489 | xfs_dir3_leaf_log_ents( |
1319 | xfs_trans_t *tp, /* transaction pointer */ | 1490 | xfs_trans_t *tp, /* transaction pointer */ |
1320 | struct xfs_buf *bp, /* leaf buffer */ | 1491 | struct xfs_buf *bp, /* leaf buffer */ |
1321 | int first, /* first entry to log */ | 1492 | int first, /* first entry to log */ |
@@ -1323,13 +1494,17 @@ xfs_dir2_leaf_log_ents( | |||
1323 | { | 1494 | { |
1324 | xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ | 1495 | xfs_dir2_leaf_entry_t *firstlep; /* pointer to first entry */ |
1325 | xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ | 1496 | xfs_dir2_leaf_entry_t *lastlep; /* pointer to last entry */ |
1326 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1497 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1498 | struct xfs_dir2_leaf_entry *ents; | ||
1327 | 1499 | ||
1328 | leaf = bp->b_addr; | ||
1329 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1500 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1330 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1501 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || |
1331 | firstlep = &leaf->ents[first]; | 1502 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || |
1332 | lastlep = &leaf->ents[last]; | 1503 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); |
1504 | |||
1505 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1506 | firstlep = &ents[first]; | ||
1507 | lastlep = &ents[last]; | ||
1333 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), | 1508 | xfs_trans_log_buf(tp, bp, (uint)((char *)firstlep - (char *)leaf), |
1334 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); | 1509 | (uint)((char *)lastlep - (char *)leaf + sizeof(*lastlep) - 1)); |
1335 | } | 1510 | } |
@@ -1338,34 +1513,38 @@ xfs_dir2_leaf_log_ents( | |||
1338 | * Log the header of the leaf1 or leafn block. | 1513 | * Log the header of the leaf1 or leafn block. |
1339 | */ | 1514 | */ |
1340 | void | 1515 | void |
1341 | xfs_dir2_leaf_log_header( | 1516 | xfs_dir3_leaf_log_header( |
1342 | struct xfs_trans *tp, | 1517 | struct xfs_trans *tp, |
1343 | struct xfs_buf *bp) | 1518 | struct xfs_buf *bp) |
1344 | { | 1519 | { |
1345 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1520 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1346 | 1521 | ||
1347 | leaf = bp->b_addr; | ||
1348 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | 1522 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || |
1349 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1523 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || |
1524 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | ||
1525 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | ||
1526 | |||
1350 | xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), | 1527 | xfs_trans_log_buf(tp, bp, (uint)((char *)&leaf->hdr - (char *)leaf), |
1351 | (uint)(sizeof(leaf->hdr) - 1)); | 1528 | xfs_dir3_leaf_hdr_size(leaf) - 1); |
1352 | } | 1529 | } |
1353 | 1530 | ||
1354 | /* | 1531 | /* |
1355 | * Log the tail of the leaf1 block. | 1532 | * Log the tail of the leaf1 block. |
1356 | */ | 1533 | */ |
1357 | STATIC void | 1534 | STATIC void |
1358 | xfs_dir2_leaf_log_tail( | 1535 | xfs_dir3_leaf_log_tail( |
1359 | struct xfs_trans *tp, | 1536 | struct xfs_trans *tp, |
1360 | struct xfs_buf *bp) | 1537 | struct xfs_buf *bp) |
1361 | { | 1538 | { |
1362 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1539 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
1363 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ | 1540 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
1364 | xfs_mount_t *mp; /* filesystem mount point */ | 1541 | struct xfs_mount *mp = tp->t_mountp; |
1542 | |||
1543 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC) || | ||
1544 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAF1_MAGIC) || | ||
1545 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC) || | ||
1546 | leaf->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)); | ||
1365 | 1547 | ||
1366 | mp = tp->t_mountp; | ||
1367 | leaf = bp->b_addr; | ||
1368 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)); | ||
1369 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 1548 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1370 | xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), | 1549 | xfs_trans_log_buf(tp, bp, (uint)((char *)ltp - (char *)leaf), |
1371 | (uint)(mp->m_dirblksize - 1)); | 1550 | (uint)(mp->m_dirblksize - 1)); |
@@ -1389,6 +1568,7 @@ xfs_dir2_leaf_lookup( | |||
1389 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1568 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1390 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1569 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1391 | xfs_trans_t *tp; /* transaction pointer */ | 1570 | xfs_trans_t *tp; /* transaction pointer */ |
1571 | struct xfs_dir2_leaf_entry *ents; | ||
1392 | 1572 | ||
1393 | trace_xfs_dir2_leaf_lookup(args); | 1573 | trace_xfs_dir2_leaf_lookup(args); |
1394 | 1574 | ||
@@ -1400,12 +1580,14 @@ xfs_dir2_leaf_lookup( | |||
1400 | } | 1580 | } |
1401 | tp = args->trans; | 1581 | tp = args->trans; |
1402 | dp = args->dp; | 1582 | dp = args->dp; |
1403 | xfs_dir2_leaf_check(dp, lbp); | 1583 | xfs_dir3_leaf_check(dp->i_mount, lbp); |
1404 | leaf = lbp->b_addr; | 1584 | leaf = lbp->b_addr; |
1585 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1405 | /* | 1586 | /* |
1406 | * Get to the leaf entry and contained data entry address. | 1587 | * Get to the leaf entry and contained data entry address. |
1407 | */ | 1588 | */ |
1408 | lep = &leaf->ents[index]; | 1589 | lep = &ents[index]; |
1590 | |||
1409 | /* | 1591 | /* |
1410 | * Point to the data entry. | 1592 | * Point to the data entry. |
1411 | */ | 1593 | */ |
@@ -1449,18 +1631,23 @@ xfs_dir2_leaf_lookup_int( | |||
1449 | xfs_trans_t *tp; /* transaction pointer */ | 1631 | xfs_trans_t *tp; /* transaction pointer */ |
1450 | xfs_dir2_db_t cidb = -1; /* case match data block no. */ | 1632 | xfs_dir2_db_t cidb = -1; /* case match data block no. */ |
1451 | enum xfs_dacmp cmp; /* name compare result */ | 1633 | enum xfs_dacmp cmp; /* name compare result */ |
1634 | struct xfs_dir2_leaf_entry *ents; | ||
1635 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1452 | 1636 | ||
1453 | dp = args->dp; | 1637 | dp = args->dp; |
1454 | tp = args->trans; | 1638 | tp = args->trans; |
1455 | mp = dp->i_mount; | 1639 | mp = dp->i_mount; |
1456 | 1640 | ||
1457 | error = xfs_dir2_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); | 1641 | error = xfs_dir3_leaf_read(tp, dp, mp->m_dirleafblk, -1, &lbp); |
1458 | if (error) | 1642 | if (error) |
1459 | return error; | 1643 | return error; |
1460 | 1644 | ||
1461 | *lbpp = lbp; | 1645 | *lbpp = lbp; |
1462 | leaf = lbp->b_addr; | 1646 | leaf = lbp->b_addr; |
1463 | xfs_dir2_leaf_check(dp, lbp); | 1647 | xfs_dir3_leaf_check(mp, lbp); |
1648 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1649 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1650 | |||
1464 | /* | 1651 | /* |
1465 | * Look for the first leaf entry with our hash value. | 1652 | * Look for the first leaf entry with our hash value. |
1466 | */ | 1653 | */ |
@@ -1469,9 +1656,9 @@ xfs_dir2_leaf_lookup_int( | |||
1469 | * Loop over all the entries with the right hash value | 1656 | * Loop over all the entries with the right hash value |
1470 | * looking to match the name. | 1657 | * looking to match the name. |
1471 | */ | 1658 | */ |
1472 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 1659 | for (lep = &ents[index]; |
1473 | be32_to_cpu(lep->hashval) == args->hashval; | 1660 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
1474 | lep++, index++) { | 1661 | lep++, index++) { |
1475 | /* | 1662 | /* |
1476 | * Skip over stale leaf entries. | 1663 | * Skip over stale leaf entries. |
1477 | */ | 1664 | */ |
@@ -1576,6 +1763,8 @@ xfs_dir2_leaf_removename( | |||
1576 | xfs_dir2_data_off_t oldbest; /* old value of best free */ | 1763 | xfs_dir2_data_off_t oldbest; /* old value of best free */ |
1577 | xfs_trans_t *tp; /* transaction pointer */ | 1764 | xfs_trans_t *tp; /* transaction pointer */ |
1578 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 1765 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
1766 | struct xfs_dir2_leaf_entry *ents; | ||
1767 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1579 | 1768 | ||
1580 | trace_xfs_dir2_leaf_removename(args); | 1769 | trace_xfs_dir2_leaf_removename(args); |
1581 | 1770 | ||
@@ -1590,12 +1779,14 @@ xfs_dir2_leaf_removename( | |||
1590 | mp = dp->i_mount; | 1779 | mp = dp->i_mount; |
1591 | leaf = lbp->b_addr; | 1780 | leaf = lbp->b_addr; |
1592 | hdr = dbp->b_addr; | 1781 | hdr = dbp->b_addr; |
1593 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
1594 | xfs_dir3_data_check(dp, dbp); | 1782 | xfs_dir3_data_check(dp, dbp); |
1783 | bf = xfs_dir3_data_bestfree_p(hdr); | ||
1784 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1785 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1595 | /* | 1786 | /* |
1596 | * Point to the leaf entry, use that to point to the data entry. | 1787 | * Point to the leaf entry, use that to point to the data entry. |
1597 | */ | 1788 | */ |
1598 | lep = &leaf->ents[index]; | 1789 | lep = &ents[index]; |
1599 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); | 1790 | db = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address)); |
1600 | dep = (xfs_dir2_data_entry_t *) | 1791 | dep = (xfs_dir2_data_entry_t *) |
1601 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); | 1792 | ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address))); |
@@ -1613,10 +1804,13 @@ xfs_dir2_leaf_removename( | |||
1613 | /* | 1804 | /* |
1614 | * We just mark the leaf entry stale by putting a null in it. | 1805 | * We just mark the leaf entry stale by putting a null in it. |
1615 | */ | 1806 | */ |
1616 | be16_add_cpu(&leaf->hdr.stale, 1); | 1807 | leafhdr.stale++; |
1617 | xfs_dir2_leaf_log_header(tp, lbp); | 1808 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1809 | xfs_dir3_leaf_log_header(tp, lbp); | ||
1810 | |||
1618 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1811 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1619 | xfs_dir2_leaf_log_ents(tp, lbp, index, index); | 1812 | xfs_dir3_leaf_log_ents(tp, lbp, index, index); |
1813 | |||
1620 | /* | 1814 | /* |
1621 | * Scan the freespace in the data block again if necessary, | 1815 | * Scan the freespace in the data block again if necessary, |
1622 | * log the data block header if necessary. | 1816 | * log the data block header if necessary. |
@@ -1631,7 +1825,7 @@ xfs_dir2_leaf_removename( | |||
1631 | */ | 1825 | */ |
1632 | if (be16_to_cpu(bf[0].length) != oldbest) { | 1826 | if (be16_to_cpu(bf[0].length) != oldbest) { |
1633 | bestsp[db] = bf[0].length; | 1827 | bestsp[db] = bf[0].length; |
1634 | xfs_dir2_leaf_log_bests(tp, lbp, db, db); | 1828 | xfs_dir3_leaf_log_bests(tp, lbp, db, db); |
1635 | } | 1829 | } |
1636 | xfs_dir3_data_check(dp, dbp); | 1830 | xfs_dir3_data_check(dp, dbp); |
1637 | /* | 1831 | /* |
@@ -1649,7 +1843,7 @@ xfs_dir2_leaf_removename( | |||
1649 | */ | 1843 | */ |
1650 | if (error == ENOSPC && args->total == 0) | 1844 | if (error == ENOSPC && args->total == 0) |
1651 | error = 0; | 1845 | error = 0; |
1652 | xfs_dir2_leaf_check(dp, lbp); | 1846 | xfs_dir3_leaf_check(mp, lbp); |
1653 | return error; | 1847 | return error; |
1654 | } | 1848 | } |
1655 | dbp = NULL; | 1849 | dbp = NULL; |
@@ -1672,8 +1866,8 @@ xfs_dir2_leaf_removename( | |||
1672 | memmove(&bestsp[db - i], bestsp, | 1866 | memmove(&bestsp[db - i], bestsp, |
1673 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); | 1867 | (be32_to_cpu(ltp->bestcount) - (db - i)) * sizeof(*bestsp)); |
1674 | be32_add_cpu(<p->bestcount, -(db - i)); | 1868 | be32_add_cpu(<p->bestcount, -(db - i)); |
1675 | xfs_dir2_leaf_log_tail(tp, lbp); | 1869 | xfs_dir3_leaf_log_tail(tp, lbp); |
1676 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 1870 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1677 | } else | 1871 | } else |
1678 | bestsp[db] = cpu_to_be16(NULLDATAOFF); | 1872 | bestsp[db] = cpu_to_be16(NULLDATAOFF); |
1679 | } | 1873 | } |
@@ -1683,7 +1877,7 @@ xfs_dir2_leaf_removename( | |||
1683 | else if (db != mp->m_dirdatablk) | 1877 | else if (db != mp->m_dirdatablk) |
1684 | dbp = NULL; | 1878 | dbp = NULL; |
1685 | 1879 | ||
1686 | xfs_dir2_leaf_check(dp, lbp); | 1880 | xfs_dir3_leaf_check(mp, lbp); |
1687 | /* | 1881 | /* |
1688 | * See if we can convert to block form. | 1882 | * See if we can convert to block form. |
1689 | */ | 1883 | */ |
@@ -1706,6 +1900,7 @@ xfs_dir2_leaf_replace( | |||
1706 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1900 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1707 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1901 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1708 | xfs_trans_t *tp; /* transaction pointer */ | 1902 | xfs_trans_t *tp; /* transaction pointer */ |
1903 | struct xfs_dir2_leaf_entry *ents; | ||
1709 | 1904 | ||
1710 | trace_xfs_dir2_leaf_replace(args); | 1905 | trace_xfs_dir2_leaf_replace(args); |
1711 | 1906 | ||
@@ -1717,10 +1912,11 @@ xfs_dir2_leaf_replace( | |||
1717 | } | 1912 | } |
1718 | dp = args->dp; | 1913 | dp = args->dp; |
1719 | leaf = lbp->b_addr; | 1914 | leaf = lbp->b_addr; |
1915 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1720 | /* | 1916 | /* |
1721 | * Point to the leaf entry, get data address from it. | 1917 | * Point to the leaf entry, get data address from it. |
1722 | */ | 1918 | */ |
1723 | lep = &leaf->ents[index]; | 1919 | lep = &ents[index]; |
1724 | /* | 1920 | /* |
1725 | * Point to the data entry. | 1921 | * Point to the data entry. |
1726 | */ | 1922 | */ |
@@ -1734,7 +1930,7 @@ xfs_dir2_leaf_replace( | |||
1734 | dep->inumber = cpu_to_be64(args->inumber); | 1930 | dep->inumber = cpu_to_be64(args->inumber); |
1735 | tp = args->trans; | 1931 | tp = args->trans; |
1736 | xfs_dir2_data_log_entry(tp, dbp, dep); | 1932 | xfs_dir2_data_log_entry(tp, dbp, dep); |
1737 | xfs_dir2_leaf_check(dp, lbp); | 1933 | xfs_dir3_leaf_check(dp->i_mount, lbp); |
1738 | xfs_trans_brelse(tp, lbp); | 1934 | xfs_trans_brelse(tp, lbp); |
1739 | return 0; | 1935 | return 0; |
1740 | } | 1936 | } |
@@ -1756,17 +1952,22 @@ xfs_dir2_leaf_search_hash( | |||
1756 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1952 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1757 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ | 1953 | xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
1758 | int mid=0; /* current leaf index */ | 1954 | int mid=0; /* current leaf index */ |
1955 | struct xfs_dir2_leaf_entry *ents; | ||
1956 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1759 | 1957 | ||
1760 | leaf = lbp->b_addr; | 1958 | leaf = lbp->b_addr; |
1959 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1960 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
1961 | |||
1761 | #ifndef __KERNEL__ | 1962 | #ifndef __KERNEL__ |
1762 | if (!leaf->hdr.count) | 1963 | if (!leafhdr.count) |
1763 | return 0; | 1964 | return 0; |
1764 | #endif | 1965 | #endif |
1765 | /* | 1966 | /* |
1766 | * Note, the table cannot be empty, so we have to go through the loop. | 1967 | * Note, the table cannot be empty, so we have to go through the loop. |
1767 | * Binary search the leaf entries looking for our hash value. | 1968 | * Binary search the leaf entries looking for our hash value. |
1768 | */ | 1969 | */ |
1769 | for (lep = leaf->ents, low = 0, high = be16_to_cpu(leaf->hdr.count) - 1, | 1970 | for (lep = ents, low = 0, high = leafhdr.count - 1, |
1770 | hashwant = args->hashval; | 1971 | hashwant = args->hashval; |
1771 | low <= high; ) { | 1972 | low <= high; ) { |
1772 | mid = (low + high) >> 1; | 1973 | mid = (low + high) >> 1; |
@@ -1852,23 +2053,29 @@ xfs_dir2_leaf_trim_data( | |||
1852 | bestsp = xfs_dir2_leaf_bests_p(ltp); | 2053 | bestsp = xfs_dir2_leaf_bests_p(ltp); |
1853 | be32_add_cpu(<p->bestcount, -1); | 2054 | be32_add_cpu(<p->bestcount, -1); |
1854 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); | 2055 | memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp)); |
1855 | xfs_dir2_leaf_log_tail(tp, lbp); | 2056 | xfs_dir3_leaf_log_tail(tp, lbp); |
1856 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 2057 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); |
1857 | return 0; | 2058 | return 0; |
1858 | } | 2059 | } |
1859 | 2060 | ||
1860 | static inline size_t | 2061 | static inline size_t |
1861 | xfs_dir2_leaf_size( | 2062 | xfs_dir3_leaf_size( |
1862 | struct xfs_dir2_leaf_hdr *hdr, | 2063 | struct xfs_dir3_icleaf_hdr *hdr, |
1863 | int counts) | 2064 | int counts) |
1864 | { | 2065 | { |
1865 | int entries; | 2066 | int entries; |
2067 | int hdrsize; | ||
2068 | |||
2069 | entries = hdr->count - hdr->stale; | ||
2070 | if (hdr->magic == XFS_DIR2_LEAF1_MAGIC || | ||
2071 | hdr->magic == XFS_DIR2_LEAFN_MAGIC) | ||
2072 | hdrsize = sizeof(struct xfs_dir2_leaf_hdr); | ||
2073 | else | ||
2074 | hdrsize = sizeof(struct xfs_dir3_leaf_hdr); | ||
1866 | 2075 | ||
1867 | entries = be16_to_cpu(hdr->count) - be16_to_cpu(hdr->stale); | 2076 | return hdrsize + entries * sizeof(xfs_dir2_leaf_entry_t) |
1868 | return sizeof(xfs_dir2_leaf_hdr_t) + | 2077 | + counts * sizeof(xfs_dir2_data_off_t) |
1869 | entries * sizeof(xfs_dir2_leaf_entry_t) + | 2078 | + sizeof(xfs_dir2_leaf_tail_t); |
1870 | counts * sizeof(xfs_dir2_data_off_t) + | ||
1871 | sizeof(xfs_dir2_leaf_tail_t); | ||
1872 | } | 2079 | } |
1873 | 2080 | ||
1874 | /* | 2081 | /* |
@@ -1892,6 +2099,7 @@ xfs_dir2_node_to_leaf( | |||
1892 | xfs_mount_t *mp; /* filesystem mount point */ | 2099 | xfs_mount_t *mp; /* filesystem mount point */ |
1893 | int rval; /* successful free trim? */ | 2100 | int rval; /* successful free trim? */ |
1894 | xfs_trans_t *tp; /* transaction pointer */ | 2101 | xfs_trans_t *tp; /* transaction pointer */ |
2102 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1895 | struct xfs_dir3_icfree_hdr freehdr; | 2103 | struct xfs_dir3_icfree_hdr freehdr; |
1896 | 2104 | ||
1897 | /* | 2105 | /* |
@@ -1942,7 +2150,11 @@ xfs_dir2_node_to_leaf( | |||
1942 | return 0; | 2150 | return 0; |
1943 | lbp = state->path.blk[0].bp; | 2151 | lbp = state->path.blk[0].bp; |
1944 | leaf = lbp->b_addr; | 2152 | leaf = lbp->b_addr; |
1945 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 2153 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
2154 | |||
2155 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || | ||
2156 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); | ||
2157 | |||
1946 | /* | 2158 | /* |
1947 | * Read the freespace block. | 2159 | * Read the freespace block. |
1948 | */ | 2160 | */ |
@@ -1958,36 +2170,40 @@ xfs_dir2_node_to_leaf( | |||
1958 | * Now see if the leafn and free data will fit in a leaf1. | 2170 | * Now see if the leafn and free data will fit in a leaf1. |
1959 | * If not, release the buffer and give up. | 2171 | * If not, release the buffer and give up. |
1960 | */ | 2172 | */ |
1961 | if (xfs_dir2_leaf_size(&leaf->hdr, freehdr.nvalid) > mp->m_dirblksize) { | 2173 | if (xfs_dir3_leaf_size(&leafhdr, freehdr.nvalid) > mp->m_dirblksize) { |
1962 | xfs_trans_brelse(tp, fbp); | 2174 | xfs_trans_brelse(tp, fbp); |
1963 | return 0; | 2175 | return 0; |
1964 | } | 2176 | } |
1965 | 2177 | ||
1966 | /* | 2178 | /* |
1967 | * If the leaf has any stale entries in it, compress them out. | 2179 | * If the leaf has any stale entries in it, compress them out. |
1968 | * The compact routine will log the header. | ||
1969 | */ | 2180 | */ |
1970 | if (be16_to_cpu(leaf->hdr.stale)) | 2181 | if (leafhdr.stale) |
1971 | xfs_dir2_leaf_compact(args, lbp); | 2182 | xfs_dir3_leaf_compact(args, &leafhdr, lbp); |
1972 | else | ||
1973 | xfs_dir2_leaf_log_header(tp, lbp); | ||
1974 | 2183 | ||
1975 | lbp->b_ops = &xfs_dir2_leaf1_buf_ops; | 2184 | lbp->b_ops = &xfs_dir3_leaf1_buf_ops; |
1976 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAF1_MAGIC); | 2185 | leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC) |
2186 | ? XFS_DIR2_LEAF1_MAGIC | ||
2187 | : XFS_DIR3_LEAF1_MAGIC; | ||
1977 | 2188 | ||
1978 | /* | 2189 | /* |
1979 | * Set up the leaf tail from the freespace block. | 2190 | * Set up the leaf tail from the freespace block. |
1980 | */ | 2191 | */ |
1981 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); | 2192 | ltp = xfs_dir2_leaf_tail_p(mp, leaf); |
1982 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); | 2193 | ltp->bestcount = cpu_to_be32(freehdr.nvalid); |
2194 | |||
1983 | /* | 2195 | /* |
1984 | * Set up the leaf bests table. | 2196 | * Set up the leaf bests table. |
1985 | */ | 2197 | */ |
1986 | memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), | 2198 | memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free), |
1987 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); | 2199 | freehdr.nvalid * sizeof(xfs_dir2_data_off_t)); |
1988 | xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | 2200 | |
1989 | xfs_dir2_leaf_log_tail(tp, lbp); | 2201 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1990 | xfs_dir2_leaf_check(dp, lbp); | 2202 | xfs_dir3_leaf_log_header(tp, lbp); |
2203 | xfs_dir3_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); | ||
2204 | xfs_dir3_leaf_log_tail(tp, lbp); | ||
2205 | xfs_dir3_leaf_check(mp, lbp); | ||
2206 | |||
1991 | /* | 2207 | /* |
1992 | * Get rid of the freespace block. | 2208 | * Get rid of the freespace block. |
1993 | */ | 2209 | */ |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index abf617d5060b..baaf9d96e354 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -41,14 +41,6 @@ | |||
41 | */ | 41 | */ |
42 | static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, | 42 | static int xfs_dir2_leafn_add(struct xfs_buf *bp, xfs_da_args_t *args, |
43 | int index); | 43 | int index); |
44 | #ifdef DEBUG | ||
45 | static void xfs_dir2_leafn_check(struct xfs_inode *dp, struct xfs_buf *bp); | ||
46 | #else | ||
47 | #define xfs_dir2_leafn_check(dp, bp) | ||
48 | #endif | ||
49 | static void xfs_dir2_leafn_moveents(xfs_da_args_t *args, struct xfs_buf *bp_s, | ||
50 | int start_s, struct xfs_buf *bp_d, | ||
51 | int start_d, int count); | ||
52 | static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, | 44 | static void xfs_dir2_leafn_rebalance(xfs_da_state_t *state, |
53 | xfs_da_state_blk_t *blk1, | 45 | xfs_da_state_blk_t *blk1, |
54 | xfs_da_state_blk_t *blk2); | 46 | xfs_da_state_blk_t *blk2); |
@@ -58,6 +50,39 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, | |||
58 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, | 50 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, |
59 | xfs_da_state_blk_t *fblk); | 51 | xfs_da_state_blk_t *fblk); |
60 | 52 | ||
53 | /* | ||
54 | * Check internal consistency of a leafn block. | ||
55 | */ | ||
56 | #ifdef DEBUG | ||
57 | #define xfs_dir3_leaf_check(mp, bp) \ | ||
58 | do { \ | ||
59 | if (!xfs_dir3_leafn_check((mp), (bp))) \ | ||
60 | ASSERT(0); \ | ||
61 | } while (0); | ||
62 | |||
63 | static bool | ||
64 | xfs_dir3_leafn_check( | ||
65 | struct xfs_mount *mp, | ||
66 | struct xfs_buf *bp) | ||
67 | { | ||
68 | struct xfs_dir2_leaf *leaf = bp->b_addr; | ||
69 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
70 | |||
71 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
72 | |||
73 | if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { | ||
74 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; | ||
75 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | ||
76 | return false; | ||
77 | } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) | ||
78 | return false; | ||
79 | |||
80 | return xfs_dir3_leaf_check_int(mp, &leafhdr, leaf); | ||
81 | } | ||
82 | #else | ||
83 | #define xfs_dir3_leaf_check(mp, bp) | ||
84 | #endif | ||
85 | |||
61 | static bool | 86 | static bool |
62 | xfs_dir3_free_verify( | 87 | xfs_dir3_free_verify( |
63 | struct xfs_buf *bp) | 88 | struct xfs_buf *bp) |
@@ -360,11 +385,19 @@ xfs_dir2_leaf_to_node( | |||
360 | xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); | 385 | xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1); |
361 | xfs_dir2_free_log_header(tp, fbp); | 386 | xfs_dir2_free_log_header(tp, fbp); |
362 | 387 | ||
363 | /* convert the leaf to a leafnode */ | 388 | /* |
364 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | 389 | * Converting the leaf to a leafnode is just a matter of changing the |
365 | lbp->b_ops = &xfs_dir2_leafn_buf_ops; | 390 | * magic number and the ops. Do the change directly to the buffer as |
366 | xfs_dir2_leaf_log_header(tp, lbp); | 391 | * it's less work (and less code) than decoding the header to host |
367 | xfs_dir2_leafn_check(dp, lbp); | 392 | * format and back again. |
393 | */ | ||
394 | if (leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAF1_MAGIC)) | ||
395 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC); | ||
396 | else | ||
397 | leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | ||
398 | lbp->b_ops = &xfs_dir3_leafn_buf_ops; | ||
399 | xfs_dir3_leaf_log_header(tp, lbp); | ||
400 | xfs_dir3_leaf_check(mp, lbp); | ||
368 | return 0; | 401 | return 0; |
369 | } | 402 | } |
370 | 403 | ||
@@ -388,6 +421,8 @@ xfs_dir2_leafn_add( | |||
388 | int lowstale; /* previous stale entry */ | 421 | int lowstale; /* previous stale entry */ |
389 | xfs_mount_t *mp; /* filesystem mount point */ | 422 | xfs_mount_t *mp; /* filesystem mount point */ |
390 | xfs_trans_t *tp; /* transaction pointer */ | 423 | xfs_trans_t *tp; /* transaction pointer */ |
424 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
425 | struct xfs_dir2_leaf_entry *ents; | ||
391 | 426 | ||
392 | trace_xfs_dir2_leafn_add(args, index); | 427 | trace_xfs_dir2_leafn_add(args, index); |
393 | 428 | ||
@@ -395,6 +430,8 @@ xfs_dir2_leafn_add( | |||
395 | mp = dp->i_mount; | 430 | mp = dp->i_mount; |
396 | tp = args->trans; | 431 | tp = args->trans; |
397 | leaf = bp->b_addr; | 432 | leaf = bp->b_addr; |
433 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
434 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
398 | 435 | ||
399 | /* | 436 | /* |
400 | * Quick check just to make sure we are not going to index | 437 | * Quick check just to make sure we are not going to index |
@@ -410,15 +447,15 @@ xfs_dir2_leafn_add( | |||
410 | * a compact. | 447 | * a compact. |
411 | */ | 448 | */ |
412 | 449 | ||
413 | if (be16_to_cpu(leaf->hdr.count) == xfs_dir2_max_leaf_ents(mp)) { | 450 | if (leafhdr.count == xfs_dir3_max_leaf_ents(mp, leaf)) { |
414 | if (!leaf->hdr.stale) | 451 | if (!leafhdr.stale) |
415 | return XFS_ERROR(ENOSPC); | 452 | return XFS_ERROR(ENOSPC); |
416 | compact = be16_to_cpu(leaf->hdr.stale) > 1; | 453 | compact = leafhdr.stale > 1; |
417 | } else | 454 | } else |
418 | compact = 0; | 455 | compact = 0; |
419 | ASSERT(index == 0 || be32_to_cpu(leaf->ents[index - 1].hashval) <= args->hashval); | 456 | ASSERT(index == 0 || be32_to_cpu(ents[index - 1].hashval) <= args->hashval); |
420 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 457 | ASSERT(index == leafhdr.count || |
421 | be32_to_cpu(leaf->ents[index].hashval) >= args->hashval); | 458 | be32_to_cpu(ents[index].hashval) >= args->hashval); |
422 | 459 | ||
423 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) | 460 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
424 | return 0; | 461 | return 0; |
@@ -427,62 +464,35 @@ xfs_dir2_leafn_add( | |||
427 | * Compact out all but one stale leaf entry. Leaves behind | 464 | * Compact out all but one stale leaf entry. Leaves behind |
428 | * the entry closest to index. | 465 | * the entry closest to index. |
429 | */ | 466 | */ |
430 | if (compact) { | 467 | if (compact) |
431 | xfs_dir2_leaf_compact_x1(bp, &index, &lowstale, &highstale, | 468 | xfs_dir3_leaf_compact_x1(&leafhdr, ents, &index, &lowstale, |
432 | &lfloglow, &lfloghigh); | 469 | &highstale, &lfloglow, &lfloghigh); |
433 | } | 470 | else if (leafhdr.stale) { |
434 | /* | 471 | /* |
435 | * Set impossible logging indices for this case. | 472 | * Set impossible logging indices for this case. |
436 | */ | 473 | */ |
437 | else if (leaf->hdr.stale) { | 474 | lfloglow = leafhdr.count; |
438 | lfloglow = be16_to_cpu(leaf->hdr.count); | ||
439 | lfloghigh = -1; | 475 | lfloghigh = -1; |
440 | } | 476 | } |
441 | 477 | ||
442 | /* | 478 | /* |
443 | * Insert the new entry, log everything. | 479 | * Insert the new entry, log everything. |
444 | */ | 480 | */ |
445 | lep = xfs_dir2_leaf_find_entry(leaf, index, compact, lowstale, | 481 | lep = xfs_dir3_leaf_find_entry(&leafhdr, ents, index, compact, lowstale, |
446 | highstale, &lfloglow, &lfloghigh); | 482 | highstale, &lfloglow, &lfloghigh); |
447 | 483 | ||
448 | lep->hashval = cpu_to_be32(args->hashval); | 484 | lep->hashval = cpu_to_be32(args->hashval); |
449 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, | 485 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(mp, |
450 | args->blkno, args->index)); | 486 | args->blkno, args->index)); |
451 | xfs_dir2_leaf_log_header(tp, bp); | 487 | |
452 | xfs_dir2_leaf_log_ents(tp, bp, lfloglow, lfloghigh); | 488 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
453 | xfs_dir2_leafn_check(dp, bp); | 489 | xfs_dir3_leaf_log_header(tp, bp); |
490 | xfs_dir3_leaf_log_ents(tp, bp, lfloglow, lfloghigh); | ||
491 | xfs_dir3_leaf_check(mp, bp); | ||
454 | return 0; | 492 | return 0; |
455 | } | 493 | } |
456 | 494 | ||
457 | #ifdef DEBUG | 495 | #ifdef DEBUG |
458 | /* | ||
459 | * Check internal consistency of a leafn block. | ||
460 | */ | ||
461 | void | ||
462 | xfs_dir2_leafn_check( | ||
463 | struct xfs_inode *dp, | ||
464 | struct xfs_buf *bp) | ||
465 | { | ||
466 | int i; /* leaf index */ | ||
467 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | ||
468 | xfs_mount_t *mp; /* filesystem mount point */ | ||
469 | int stale; /* count of stale leaves */ | ||
470 | |||
471 | leaf = bp->b_addr; | ||
472 | mp = dp->i_mount; | ||
473 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | ||
474 | ASSERT(be16_to_cpu(leaf->hdr.count) <= xfs_dir2_max_leaf_ents(mp)); | ||
475 | for (i = stale = 0; i < be16_to_cpu(leaf->hdr.count); i++) { | ||
476 | if (i + 1 < be16_to_cpu(leaf->hdr.count)) { | ||
477 | ASSERT(be32_to_cpu(leaf->ents[i].hashval) <= | ||
478 | be32_to_cpu(leaf->ents[i + 1].hashval)); | ||
479 | } | ||
480 | if (leaf->ents[i].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | ||
481 | stale++; | ||
482 | } | ||
483 | ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); | ||
484 | } | ||
485 | |||
486 | static void | 496 | static void |
487 | xfs_dir2_free_hdr_check( | 497 | xfs_dir2_free_hdr_check( |
488 | struct xfs_mount *mp, | 498 | struct xfs_mount *mp, |
@@ -510,15 +520,22 @@ xfs_dir2_leafn_lasthash( | |||
510 | struct xfs_buf *bp, /* leaf buffer */ | 520 | struct xfs_buf *bp, /* leaf buffer */ |
511 | int *count) /* count of entries in leaf */ | 521 | int *count) /* count of entries in leaf */ |
512 | { | 522 | { |
513 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 523 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
524 | struct xfs_dir2_leaf_entry *ents; | ||
525 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
526 | |||
527 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); | ||
528 | |||
529 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || | ||
530 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC); | ||
514 | 531 | ||
515 | leaf = bp->b_addr; | ||
516 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | ||
517 | if (count) | 532 | if (count) |
518 | *count = be16_to_cpu(leaf->hdr.count); | 533 | *count = leafhdr.count; |
519 | if (!leaf->hdr.count) | 534 | if (!leafhdr.count) |
520 | return 0; | 535 | return 0; |
521 | return be32_to_cpu(leaf->ents[be16_to_cpu(leaf->hdr.count) - 1].hashval); | 536 | |
537 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
538 | return be32_to_cpu(ents[leafhdr.count - 1].hashval); | ||
522 | } | 539 | } |
523 | 540 | ||
524 | /* | 541 | /* |
@@ -547,16 +564,19 @@ xfs_dir2_leafn_lookup_for_addname( | |||
547 | xfs_dir2_db_t newdb; /* new data block number */ | 564 | xfs_dir2_db_t newdb; /* new data block number */ |
548 | xfs_dir2_db_t newfdb; /* new free block number */ | 565 | xfs_dir2_db_t newfdb; /* new free block number */ |
549 | xfs_trans_t *tp; /* transaction pointer */ | 566 | xfs_trans_t *tp; /* transaction pointer */ |
567 | struct xfs_dir2_leaf_entry *ents; | ||
568 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
550 | 569 | ||
551 | dp = args->dp; | 570 | dp = args->dp; |
552 | tp = args->trans; | 571 | tp = args->trans; |
553 | mp = dp->i_mount; | 572 | mp = dp->i_mount; |
554 | leaf = bp->b_addr; | 573 | leaf = bp->b_addr; |
555 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 574 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
556 | #ifdef __KERNEL__ | 575 | ents = xfs_dir3_leaf_ents_p(leaf); |
557 | ASSERT(be16_to_cpu(leaf->hdr.count) > 0); | 576 | |
558 | #endif | 577 | xfs_dir3_leaf_check(mp, bp); |
559 | xfs_dir2_leafn_check(dp, bp); | 578 | ASSERT(leafhdr.count > 0); |
579 | |||
560 | /* | 580 | /* |
561 | * Look up the hash value in the leaf entries. | 581 | * Look up the hash value in the leaf entries. |
562 | */ | 582 | */ |
@@ -576,9 +596,9 @@ xfs_dir2_leafn_lookup_for_addname( | |||
576 | /* | 596 | /* |
577 | * Loop over leaf entries with the right hash value. | 597 | * Loop over leaf entries with the right hash value. |
578 | */ | 598 | */ |
579 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 599 | for (lep = &ents[index]; |
580 | be32_to_cpu(lep->hashval) == args->hashval; | 600 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
581 | lep++, index++) { | 601 | lep++, index++) { |
582 | /* | 602 | /* |
583 | * Skip stale leaf entries. | 603 | * Skip stale leaf entries. |
584 | */ | 604 | */ |
@@ -694,16 +714,19 @@ xfs_dir2_leafn_lookup_for_entry( | |||
694 | xfs_dir2_db_t newdb; /* new data block number */ | 714 | xfs_dir2_db_t newdb; /* new data block number */ |
695 | xfs_trans_t *tp; /* transaction pointer */ | 715 | xfs_trans_t *tp; /* transaction pointer */ |
696 | enum xfs_dacmp cmp; /* comparison result */ | 716 | enum xfs_dacmp cmp; /* comparison result */ |
717 | struct xfs_dir2_leaf_entry *ents; | ||
718 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
697 | 719 | ||
698 | dp = args->dp; | 720 | dp = args->dp; |
699 | tp = args->trans; | 721 | tp = args->trans; |
700 | mp = dp->i_mount; | 722 | mp = dp->i_mount; |
701 | leaf = bp->b_addr; | 723 | leaf = bp->b_addr; |
702 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 724 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
703 | #ifdef __KERNEL__ | 725 | ents = xfs_dir3_leaf_ents_p(leaf); |
704 | ASSERT(be16_to_cpu(leaf->hdr.count) > 0); | 726 | |
705 | #endif | 727 | xfs_dir3_leaf_check(mp, bp); |
706 | xfs_dir2_leafn_check(dp, bp); | 728 | ASSERT(leafhdr.count > 0); |
729 | |||
707 | /* | 730 | /* |
708 | * Look up the hash value in the leaf entries. | 731 | * Look up the hash value in the leaf entries. |
709 | */ | 732 | */ |
@@ -718,9 +741,9 @@ xfs_dir2_leafn_lookup_for_entry( | |||
718 | /* | 741 | /* |
719 | * Loop over leaf entries with the right hash value. | 742 | * Loop over leaf entries with the right hash value. |
720 | */ | 743 | */ |
721 | for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) && | 744 | for (lep = &ents[index]; |
722 | be32_to_cpu(lep->hashval) == args->hashval; | 745 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
723 | lep++, index++) { | 746 | lep++, index++) { |
724 | /* | 747 | /* |
725 | * Skip stale leaf entries. | 748 | * Skip stale leaf entries. |
726 | */ | 749 | */ |
@@ -792,8 +815,7 @@ xfs_dir2_leafn_lookup_for_entry( | |||
792 | return XFS_ERROR(EEXIST); | 815 | return XFS_ERROR(EEXIST); |
793 | } | 816 | } |
794 | } | 817 | } |
795 | ASSERT(index == be16_to_cpu(leaf->hdr.count) || | 818 | ASSERT(index == leafhdr.count || (args->op_flags & XFS_DA_OP_OKNOENT)); |
796 | (args->op_flags & XFS_DA_OP_OKNOENT)); | ||
797 | if (curbp) { | 819 | if (curbp) { |
798 | if (args->cmpresult == XFS_CMP_DIFFERENT) { | 820 | if (args->cmpresult == XFS_CMP_DIFFERENT) { |
799 | /* Giving back last used data block. */ | 821 | /* Giving back last used data block. */ |
@@ -838,52 +860,50 @@ xfs_dir2_leafn_lookup_int( | |||
838 | * Log entries and headers. Stale entries are preserved. | 860 | * Log entries and headers. Stale entries are preserved. |
839 | */ | 861 | */ |
840 | static void | 862 | static void |
841 | xfs_dir2_leafn_moveents( | 863 | xfs_dir3_leafn_moveents( |
842 | xfs_da_args_t *args, /* operation arguments */ | 864 | xfs_da_args_t *args, /* operation arguments */ |
843 | struct xfs_buf *bp_s, /* source leaf buffer */ | 865 | struct xfs_buf *bp_s, /* source */ |
844 | int start_s, /* source leaf index */ | 866 | struct xfs_dir3_icleaf_hdr *shdr, |
845 | struct xfs_buf *bp_d, /* destination leaf buffer */ | 867 | struct xfs_dir2_leaf_entry *sents, |
846 | int start_d, /* destination leaf index */ | 868 | int start_s,/* source leaf index */ |
847 | int count) /* count of leaves to copy */ | 869 | struct xfs_buf *bp_d, /* destination */ |
870 | struct xfs_dir3_icleaf_hdr *dhdr, | ||
871 | struct xfs_dir2_leaf_entry *dents, | ||
872 | int start_d,/* destination leaf index */ | ||
873 | int count) /* count of leaves to copy */ | ||
848 | { | 874 | { |
849 | xfs_dir2_leaf_t *leaf_d; /* destination leaf structure */ | 875 | struct xfs_trans *tp = args->trans; |
850 | xfs_dir2_leaf_t *leaf_s; /* source leaf structure */ | 876 | int stale; /* count stale leaves copied */ |
851 | int stale; /* count stale leaves copied */ | ||
852 | xfs_trans_t *tp; /* transaction pointer */ | ||
853 | 877 | ||
854 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); | 878 | trace_xfs_dir2_leafn_moveents(args, start_s, start_d, count); |
855 | 879 | ||
856 | /* | 880 | /* |
857 | * Silently return if nothing to do. | 881 | * Silently return if nothing to do. |
858 | */ | 882 | */ |
859 | if (count == 0) { | 883 | if (count == 0) |
860 | return; | 884 | return; |
861 | } | 885 | |
862 | tp = args->trans; | ||
863 | leaf_s = bp_s->b_addr; | ||
864 | leaf_d = bp_d->b_addr; | ||
865 | /* | 886 | /* |
866 | * If the destination index is not the end of the current | 887 | * If the destination index is not the end of the current |
867 | * destination leaf entries, open up a hole in the destination | 888 | * destination leaf entries, open up a hole in the destination |
868 | * to hold the new entries. | 889 | * to hold the new entries. |
869 | */ | 890 | */ |
870 | if (start_d < be16_to_cpu(leaf_d->hdr.count)) { | 891 | if (start_d < dhdr->count) { |
871 | memmove(&leaf_d->ents[start_d + count], &leaf_d->ents[start_d], | 892 | memmove(&dents[start_d + count], &dents[start_d], |
872 | (be16_to_cpu(leaf_d->hdr.count) - start_d) * | 893 | (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); |
873 | sizeof(xfs_dir2_leaf_entry_t)); | 894 | xfs_dir3_leaf_log_ents(tp, bp_d, start_d + count, |
874 | xfs_dir2_leaf_log_ents(tp, bp_d, start_d + count, | 895 | count + dhdr->count - 1); |
875 | count + be16_to_cpu(leaf_d->hdr.count) - 1); | ||
876 | } | 896 | } |
877 | /* | 897 | /* |
878 | * If the source has stale leaves, count the ones in the copy range | 898 | * If the source has stale leaves, count the ones in the copy range |
879 | * so we can update the header correctly. | 899 | * so we can update the header correctly. |
880 | */ | 900 | */ |
881 | if (leaf_s->hdr.stale) { | 901 | if (shdr->stale) { |
882 | int i; /* temp leaf index */ | 902 | int i; /* temp leaf index */ |
883 | 903 | ||
884 | for (i = start_s, stale = 0; i < start_s + count; i++) { | 904 | for (i = start_s, stale = 0; i < start_s + count; i++) { |
885 | if (leaf_s->ents[i].address == | 905 | if (sents[i].address == |
886 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) | 906 | cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) |
887 | stale++; | 907 | stale++; |
888 | } | 908 | } |
889 | } else | 909 | } else |
@@ -891,29 +911,27 @@ xfs_dir2_leafn_moveents( | |||
891 | /* | 911 | /* |
892 | * Copy the leaf entries from source to destination. | 912 | * Copy the leaf entries from source to destination. |
893 | */ | 913 | */ |
894 | memcpy(&leaf_d->ents[start_d], &leaf_s->ents[start_s], | 914 | memcpy(&dents[start_d], &sents[start_s], |
895 | count * sizeof(xfs_dir2_leaf_entry_t)); | 915 | count * sizeof(xfs_dir2_leaf_entry_t)); |
896 | xfs_dir2_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); | 916 | xfs_dir3_leaf_log_ents(tp, bp_d, start_d, start_d + count - 1); |
917 | |||
897 | /* | 918 | /* |
898 | * If there are source entries after the ones we copied, | 919 | * If there are source entries after the ones we copied, |
899 | * delete the ones we copied by sliding the next ones down. | 920 | * delete the ones we copied by sliding the next ones down. |
900 | */ | 921 | */ |
901 | if (start_s + count < be16_to_cpu(leaf_s->hdr.count)) { | 922 | if (start_s + count < shdr->count) { |
902 | memmove(&leaf_s->ents[start_s], &leaf_s->ents[start_s + count], | 923 | memmove(&sents[start_s], &sents[start_s + count], |
903 | count * sizeof(xfs_dir2_leaf_entry_t)); | 924 | count * sizeof(xfs_dir2_leaf_entry_t)); |
904 | xfs_dir2_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); | 925 | xfs_dir3_leaf_log_ents(tp, bp_s, start_s, start_s + count - 1); |
905 | } | 926 | } |
927 | |||
906 | /* | 928 | /* |
907 | * Update the headers and log them. | 929 | * Update the headers and log them. |
908 | */ | 930 | */ |
909 | be16_add_cpu(&leaf_s->hdr.count, -(count)); | 931 | shdr->count -= count; |
910 | be16_add_cpu(&leaf_s->hdr.stale, -(stale)); | 932 | shdr->stale -= stale; |
911 | be16_add_cpu(&leaf_d->hdr.count, count); | 933 | dhdr->count += count; |
912 | be16_add_cpu(&leaf_d->hdr.stale, stale); | 934 | dhdr->stale += stale; |
913 | xfs_dir2_leaf_log_header(tp, bp_s); | ||
914 | xfs_dir2_leaf_log_header(tp, bp_d); | ||
915 | xfs_dir2_leafn_check(args->dp, bp_s); | ||
916 | xfs_dir2_leafn_check(args->dp, bp_d); | ||
917 | } | 935 | } |
918 | 936 | ||
919 | /* | 937 | /* |
@@ -922,21 +940,25 @@ xfs_dir2_leafn_moveents( | |||
922 | */ | 940 | */ |
923 | int /* sort order */ | 941 | int /* sort order */ |
924 | xfs_dir2_leafn_order( | 942 | xfs_dir2_leafn_order( |
925 | struct xfs_buf *leaf1_bp, /* leaf1 buffer */ | 943 | struct xfs_buf *leaf1_bp, /* leaf1 buffer */ |
926 | struct xfs_buf *leaf2_bp) /* leaf2 buffer */ | 944 | struct xfs_buf *leaf2_bp) /* leaf2 buffer */ |
927 | { | 945 | { |
928 | xfs_dir2_leaf_t *leaf1; /* leaf1 structure */ | 946 | struct xfs_dir2_leaf *leaf1 = leaf1_bp->b_addr; |
929 | xfs_dir2_leaf_t *leaf2; /* leaf2 structure */ | 947 | struct xfs_dir2_leaf *leaf2 = leaf2_bp->b_addr; |
930 | 948 | struct xfs_dir2_leaf_entry *ents1; | |
931 | leaf1 = leaf1_bp->b_addr; | 949 | struct xfs_dir2_leaf_entry *ents2; |
932 | leaf2 = leaf2_bp->b_addr; | 950 | struct xfs_dir3_icleaf_hdr hdr1; |
933 | ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 951 | struct xfs_dir3_icleaf_hdr hdr2; |
934 | ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 952 | |
935 | if (be16_to_cpu(leaf1->hdr.count) > 0 && | 953 | xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); |
936 | be16_to_cpu(leaf2->hdr.count) > 0 && | 954 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); |
937 | (be32_to_cpu(leaf2->ents[0].hashval) < be32_to_cpu(leaf1->ents[0].hashval) || | 955 | ents1 = xfs_dir3_leaf_ents_p(leaf1); |
938 | be32_to_cpu(leaf2->ents[be16_to_cpu(leaf2->hdr.count) - 1].hashval) < | 956 | ents2 = xfs_dir3_leaf_ents_p(leaf2); |
939 | be32_to_cpu(leaf1->ents[be16_to_cpu(leaf1->hdr.count) - 1].hashval))) | 957 | |
958 | if (hdr1.count > 0 && hdr2.count > 0 && | ||
959 | (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || | ||
960 | be32_to_cpu(ents2[hdr2.count - 1].hashval) < | ||
961 | be32_to_cpu(ents1[hdr1.count - 1].hashval))) | ||
940 | return 1; | 962 | return 1; |
941 | return 0; | 963 | return 0; |
942 | } | 964 | } |
@@ -965,6 +987,10 @@ xfs_dir2_leafn_rebalance( | |||
965 | #endif | 987 | #endif |
966 | int oldsum; /* old total leaf count */ | 988 | int oldsum; /* old total leaf count */ |
967 | int swap; /* swapped leaf blocks */ | 989 | int swap; /* swapped leaf blocks */ |
990 | struct xfs_dir2_leaf_entry *ents1; | ||
991 | struct xfs_dir2_leaf_entry *ents2; | ||
992 | struct xfs_dir3_icleaf_hdr hdr1; | ||
993 | struct xfs_dir3_icleaf_hdr hdr2; | ||
968 | 994 | ||
969 | args = state->args; | 995 | args = state->args; |
970 | /* | 996 | /* |
@@ -979,11 +1005,17 @@ xfs_dir2_leafn_rebalance( | |||
979 | } | 1005 | } |
980 | leaf1 = blk1->bp->b_addr; | 1006 | leaf1 = blk1->bp->b_addr; |
981 | leaf2 = blk2->bp->b_addr; | 1007 | leaf2 = blk2->bp->b_addr; |
982 | oldsum = be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count); | 1008 | xfs_dir3_leaf_hdr_from_disk(&hdr1, leaf1); |
1009 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf2); | ||
1010 | ents1 = xfs_dir3_leaf_ents_p(leaf1); | ||
1011 | ents2 = xfs_dir3_leaf_ents_p(leaf2); | ||
1012 | |||
1013 | oldsum = hdr1.count + hdr2.count; | ||
983 | #ifdef DEBUG | 1014 | #ifdef DEBUG |
984 | oldstale = be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale); | 1015 | oldstale = hdr1.stale + hdr2.stale; |
985 | #endif | 1016 | #endif |
986 | mid = oldsum >> 1; | 1017 | mid = oldsum >> 1; |
1018 | |||
987 | /* | 1019 | /* |
988 | * If the old leaf count was odd then the new one will be even, | 1020 | * If the old leaf count was odd then the new one will be even, |
989 | * so we need to divide the new count evenly. | 1021 | * so we need to divide the new count evenly. |
@@ -991,10 +1023,10 @@ xfs_dir2_leafn_rebalance( | |||
991 | if (oldsum & 1) { | 1023 | if (oldsum & 1) { |
992 | xfs_dahash_t midhash; /* middle entry hash value */ | 1024 | xfs_dahash_t midhash; /* middle entry hash value */ |
993 | 1025 | ||
994 | if (mid >= be16_to_cpu(leaf1->hdr.count)) | 1026 | if (mid >= hdr1.count) |
995 | midhash = be32_to_cpu(leaf2->ents[mid - be16_to_cpu(leaf1->hdr.count)].hashval); | 1027 | midhash = be32_to_cpu(ents2[mid - hdr1.count].hashval); |
996 | else | 1028 | else |
997 | midhash = be32_to_cpu(leaf1->ents[mid].hashval); | 1029 | midhash = be32_to_cpu(ents1[mid].hashval); |
998 | isleft = args->hashval <= midhash; | 1030 | isleft = args->hashval <= midhash; |
999 | } | 1031 | } |
1000 | /* | 1032 | /* |
@@ -1008,30 +1040,42 @@ xfs_dir2_leafn_rebalance( | |||
1008 | * Calculate moved entry count. Positive means left-to-right, | 1040 | * Calculate moved entry count. Positive means left-to-right, |
1009 | * negative means right-to-left. Then move the entries. | 1041 | * negative means right-to-left. Then move the entries. |
1010 | */ | 1042 | */ |
1011 | count = be16_to_cpu(leaf1->hdr.count) - mid + (isleft == 0); | 1043 | count = hdr1.count - mid + (isleft == 0); |
1012 | if (count > 0) | 1044 | if (count > 0) |
1013 | xfs_dir2_leafn_moveents(args, blk1->bp, | 1045 | xfs_dir3_leafn_moveents(args, blk1->bp, &hdr1, ents1, |
1014 | be16_to_cpu(leaf1->hdr.count) - count, blk2->bp, 0, count); | 1046 | hdr1.count - count, blk2->bp, |
1047 | &hdr2, ents2, 0, count); | ||
1015 | else if (count < 0) | 1048 | else if (count < 0) |
1016 | xfs_dir2_leafn_moveents(args, blk2->bp, 0, blk1->bp, | 1049 | xfs_dir3_leafn_moveents(args, blk2->bp, &hdr2, ents2, 0, |
1017 | be16_to_cpu(leaf1->hdr.count), count); | 1050 | blk1->bp, &hdr1, ents1, |
1018 | ASSERT(be16_to_cpu(leaf1->hdr.count) + be16_to_cpu(leaf2->hdr.count) == oldsum); | 1051 | hdr1.count, count); |
1019 | ASSERT(be16_to_cpu(leaf1->hdr.stale) + be16_to_cpu(leaf2->hdr.stale) == oldstale); | 1052 | |
1053 | ASSERT(hdr1.count + hdr2.count == oldsum); | ||
1054 | ASSERT(hdr1.stale + hdr2.stale == oldstale); | ||
1055 | |||
1056 | /* log the changes made when moving the entries */ | ||
1057 | xfs_dir3_leaf_hdr_to_disk(leaf1, &hdr1); | ||
1058 | xfs_dir3_leaf_hdr_to_disk(leaf2, &hdr2); | ||
1059 | xfs_dir3_leaf_log_header(args->trans, blk1->bp); | ||
1060 | xfs_dir3_leaf_log_header(args->trans, blk2->bp); | ||
1061 | |||
1062 | xfs_dir3_leaf_check(args->dp->i_mount, blk1->bp); | ||
1063 | xfs_dir3_leaf_check(args->dp->i_mount, blk2->bp); | ||
1064 | |||
1020 | /* | 1065 | /* |
1021 | * Mark whether we're inserting into the old or new leaf. | 1066 | * Mark whether we're inserting into the old or new leaf. |
1022 | */ | 1067 | */ |
1023 | if (be16_to_cpu(leaf1->hdr.count) < be16_to_cpu(leaf2->hdr.count)) | 1068 | if (hdr1.count < hdr2.count) |
1024 | state->inleaf = swap; | 1069 | state->inleaf = swap; |
1025 | else if (be16_to_cpu(leaf1->hdr.count) > be16_to_cpu(leaf2->hdr.count)) | 1070 | else if (hdr1.count > hdr2.count) |
1026 | state->inleaf = !swap; | 1071 | state->inleaf = !swap; |
1027 | else | 1072 | else |
1028 | state->inleaf = | 1073 | state->inleaf = swap ^ (blk1->index <= hdr1.count); |
1029 | swap ^ (blk1->index <= be16_to_cpu(leaf1->hdr.count)); | ||
1030 | /* | 1074 | /* |
1031 | * Adjust the expected index for insertion. | 1075 | * Adjust the expected index for insertion. |
1032 | */ | 1076 | */ |
1033 | if (!state->inleaf) | 1077 | if (!state->inleaf) |
1034 | blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count); | 1078 | blk2->index = blk1->index - hdr1.count; |
1035 | 1079 | ||
1036 | /* | 1080 | /* |
1037 | * Finally sanity check just to make sure we are not returning a | 1081 | * Finally sanity check just to make sure we are not returning a |
@@ -1153,6 +1197,8 @@ xfs_dir2_leafn_remove( | |||
1153 | int needscan; /* need to rescan data frees */ | 1197 | int needscan; /* need to rescan data frees */ |
1154 | xfs_trans_t *tp; /* transaction pointer */ | 1198 | xfs_trans_t *tp; /* transaction pointer */ |
1155 | struct xfs_dir2_data_free *bf; /* bestfree table */ | 1199 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
1200 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1201 | struct xfs_dir2_leaf_entry *ents; | ||
1156 | 1202 | ||
1157 | trace_xfs_dir2_leafn_remove(args, index); | 1203 | trace_xfs_dir2_leafn_remove(args, index); |
1158 | 1204 | ||
@@ -1160,11 +1206,14 @@ xfs_dir2_leafn_remove( | |||
1160 | tp = args->trans; | 1206 | tp = args->trans; |
1161 | mp = dp->i_mount; | 1207 | mp = dp->i_mount; |
1162 | leaf = bp->b_addr; | 1208 | leaf = bp->b_addr; |
1163 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1209 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
1210 | ents = xfs_dir3_leaf_ents_p(leaf); | ||
1211 | |||
1164 | /* | 1212 | /* |
1165 | * Point to the entry we're removing. | 1213 | * Point to the entry we're removing. |
1166 | */ | 1214 | */ |
1167 | lep = &leaf->ents[index]; | 1215 | lep = &ents[index]; |
1216 | |||
1168 | /* | 1217 | /* |
1169 | * Extract the data block and offset from the entry. | 1218 | * Extract the data block and offset from the entry. |
1170 | */ | 1219 | */ |
@@ -1172,14 +1221,18 @@ xfs_dir2_leafn_remove( | |||
1172 | ASSERT(dblk->blkno == db); | 1221 | ASSERT(dblk->blkno == db); |
1173 | off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)); | 1222 | off = xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)); |
1174 | ASSERT(dblk->index == off); | 1223 | ASSERT(dblk->index == off); |
1224 | |||
1175 | /* | 1225 | /* |
1176 | * Kill the leaf entry by marking it stale. | 1226 | * Kill the leaf entry by marking it stale. |
1177 | * Log the leaf block changes. | 1227 | * Log the leaf block changes. |
1178 | */ | 1228 | */ |
1179 | be16_add_cpu(&leaf->hdr.stale, 1); | 1229 | leafhdr.stale++; |
1180 | xfs_dir2_leaf_log_header(tp, bp); | 1230 | xfs_dir3_leaf_hdr_to_disk(leaf, &leafhdr); |
1231 | xfs_dir3_leaf_log_header(tp, bp); | ||
1232 | |||
1181 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); | 1233 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
1182 | xfs_dir2_leaf_log_ents(tp, bp, index, index); | 1234 | xfs_dir3_leaf_log_ents(tp, bp, index, index); |
1235 | |||
1183 | /* | 1236 | /* |
1184 | * Make the data entry free. Keep track of the longest freespace | 1237 | * Make the data entry free. Keep track of the longest freespace |
1185 | * in the data block in case it changes. | 1238 | * in the data block in case it changes. |
@@ -1267,15 +1320,13 @@ xfs_dir2_leafn_remove( | |||
1267 | return error; | 1320 | return error; |
1268 | } | 1321 | } |
1269 | 1322 | ||
1270 | xfs_dir2_leafn_check(dp, bp); | 1323 | xfs_dir3_leaf_check(mp, bp); |
1271 | /* | 1324 | /* |
1272 | * Return indication of whether this leaf block is empty enough | 1325 | * Return indication of whether this leaf block is empty enough |
1273 | * to justify trying to join it with a neighbor. | 1326 | * to justify trying to join it with a neighbor. |
1274 | */ | 1327 | */ |
1275 | *rval = | 1328 | *rval = (xfs_dir3_leaf_hdr_size(leaf) + |
1276 | ((uint)sizeof(leaf->hdr) + | 1329 | (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < |
1277 | (uint)sizeof(leaf->ents[0]) * | ||
1278 | (be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale))) < | ||
1279 | mp->m_dir_magicpct; | 1330 | mp->m_dir_magicpct; |
1280 | return 0; | 1331 | return 0; |
1281 | } | 1332 | } |
@@ -1308,11 +1359,11 @@ xfs_dir2_leafn_split( | |||
1308 | /* | 1359 | /* |
1309 | * Initialize the new leaf block. | 1360 | * Initialize the new leaf block. |
1310 | */ | 1361 | */ |
1311 | error = xfs_dir2_leaf_init(args, xfs_dir2_da_to_db(mp, blkno), | 1362 | error = xfs_dir3_leaf_get_buf(args, xfs_dir2_da_to_db(mp, blkno), |
1312 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); | 1363 | &newblk->bp, XFS_DIR2_LEAFN_MAGIC); |
1313 | if (error) { | 1364 | if (error) |
1314 | return error; | 1365 | return error; |
1315 | } | 1366 | |
1316 | newblk->blkno = blkno; | 1367 | newblk->blkno = blkno; |
1317 | newblk->magic = XFS_DIR2_LEAFN_MAGIC; | 1368 | newblk->magic = XFS_DIR2_LEAFN_MAGIC; |
1318 | /* | 1369 | /* |
@@ -1336,8 +1387,8 @@ xfs_dir2_leafn_split( | |||
1336 | */ | 1387 | */ |
1337 | oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); | 1388 | oldblk->hashval = xfs_dir2_leafn_lasthash(oldblk->bp, NULL); |
1338 | newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); | 1389 | newblk->hashval = xfs_dir2_leafn_lasthash(newblk->bp, NULL); |
1339 | xfs_dir2_leafn_check(args->dp, oldblk->bp); | 1390 | xfs_dir3_leaf_check(mp, oldblk->bp); |
1340 | xfs_dir2_leafn_check(args->dp, newblk->bp); | 1391 | xfs_dir3_leaf_check(mp, newblk->bp); |
1341 | return error; | 1392 | return error; |
1342 | } | 1393 | } |
1343 | 1394 | ||
@@ -1363,9 +1414,10 @@ xfs_dir2_leafn_toosmall( | |||
1363 | int error; /* error return value */ | 1414 | int error; /* error return value */ |
1364 | int forward; /* sibling block direction */ | 1415 | int forward; /* sibling block direction */ |
1365 | int i; /* sibling counter */ | 1416 | int i; /* sibling counter */ |
1366 | xfs_da_blkinfo_t *info; /* leaf block header */ | ||
1367 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 1417 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
1368 | int rval; /* result from path_shift */ | 1418 | int rval; /* result from path_shift */ |
1419 | struct xfs_dir3_icleaf_hdr leafhdr; | ||
1420 | struct xfs_dir2_leaf_entry *ents; | ||
1369 | 1421 | ||
1370 | /* | 1422 | /* |
1371 | * Check for the degenerate case of the block being over 50% full. | 1423 | * Check for the degenerate case of the block being over 50% full. |
@@ -1373,11 +1425,13 @@ xfs_dir2_leafn_toosmall( | |||
1373 | * to coalesce with a sibling. | 1425 | * to coalesce with a sibling. |
1374 | */ | 1426 | */ |
1375 | blk = &state->path.blk[state->path.active - 1]; | 1427 | blk = &state->path.blk[state->path.active - 1]; |
1376 | info = blk->bp->b_addr; | 1428 | leaf = blk->bp->b_addr; |
1377 | ASSERT(info->magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1429 | xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); |
1378 | leaf = (xfs_dir2_leaf_t *)info; | 1430 | ents = xfs_dir3_leaf_ents_p(leaf); |
1379 | count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | 1431 | xfs_dir3_leaf_check(state->args->dp->i_mount, blk->bp); |
1380 | bytes = (uint)sizeof(leaf->hdr) + count * (uint)sizeof(leaf->ents[0]); | 1432 | |
1433 | count = leafhdr.count - leafhdr.stale; | ||
1434 | bytes = xfs_dir3_leaf_hdr_size(leaf) + count * sizeof(ents[0]); | ||
1381 | if (bytes > (state->blocksize >> 1)) { | 1435 | if (bytes > (state->blocksize >> 1)) { |
1382 | /* | 1436 | /* |
1383 | * Blk over 50%, don't try to join. | 1437 | * Blk over 50%, don't try to join. |
@@ -1396,7 +1450,7 @@ xfs_dir2_leafn_toosmall( | |||
1396 | * Make altpath point to the block we want to keep and | 1450 | * Make altpath point to the block we want to keep and |
1397 | * path point to the block we want to drop (this one). | 1451 | * path point to the block we want to drop (this one). |
1398 | */ | 1452 | */ |
1399 | forward = (info->forw != 0); | 1453 | forward = (leafhdr.forw != 0); |
1400 | memcpy(&state->altpath, &state->path, sizeof(state->path)); | 1454 | memcpy(&state->altpath, &state->path, sizeof(state->path)); |
1401 | error = xfs_da_path_shift(state, &state->altpath, forward, 0, | 1455 | error = xfs_da_path_shift(state, &state->altpath, forward, 0, |
1402 | &rval); | 1456 | &rval); |
@@ -1412,15 +1466,17 @@ xfs_dir2_leafn_toosmall( | |||
1412 | * We prefer coalescing with the lower numbered sibling so as | 1466 | * We prefer coalescing with the lower numbered sibling so as |
1413 | * to shrink a directory over time. | 1467 | * to shrink a directory over time. |
1414 | */ | 1468 | */ |
1415 | forward = be32_to_cpu(info->forw) < be32_to_cpu(info->back); | 1469 | forward = leafhdr.forw < leafhdr.back; |
1416 | for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { | 1470 | for (i = 0, bp = NULL; i < 2; forward = !forward, i++) { |
1417 | blkno = forward ? be32_to_cpu(info->forw) : be32_to_cpu(info->back); | 1471 | struct xfs_dir3_icleaf_hdr hdr2; |
1472 | |||
1473 | blkno = forward ? leafhdr.forw : leafhdr.back; | ||
1418 | if (blkno == 0) | 1474 | if (blkno == 0) |
1419 | continue; | 1475 | continue; |
1420 | /* | 1476 | /* |
1421 | * Read the sibling leaf block. | 1477 | * Read the sibling leaf block. |
1422 | */ | 1478 | */ |
1423 | error = xfs_dir2_leafn_read(state->args->trans, state->args->dp, | 1479 | error = xfs_dir3_leafn_read(state->args->trans, state->args->dp, |
1424 | blkno, -1, &bp); | 1480 | blkno, -1, &bp); |
1425 | if (error) | 1481 | if (error) |
1426 | return error; | 1482 | return error; |
@@ -1428,13 +1484,15 @@ xfs_dir2_leafn_toosmall( | |||
1428 | /* | 1484 | /* |
1429 | * Count bytes in the two blocks combined. | 1485 | * Count bytes in the two blocks combined. |
1430 | */ | 1486 | */ |
1431 | leaf = (xfs_dir2_leaf_t *)info; | 1487 | count = leafhdr.count - leafhdr.stale; |
1432 | count = be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | ||
1433 | bytes = state->blocksize - (state->blocksize >> 2); | 1488 | bytes = state->blocksize - (state->blocksize >> 2); |
1489 | |||
1434 | leaf = bp->b_addr; | 1490 | leaf = bp->b_addr; |
1435 | ASSERT(leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1491 | xfs_dir3_leaf_hdr_from_disk(&hdr2, leaf); |
1436 | count += be16_to_cpu(leaf->hdr.count) - be16_to_cpu(leaf->hdr.stale); | 1492 | ents = xfs_dir3_leaf_ents_p(leaf); |
1437 | bytes -= count * (uint)sizeof(leaf->ents[0]); | 1493 | count += hdr2.count - hdr2.stale; |
1494 | bytes -= count * sizeof(ents[0]); | ||
1495 | |||
1438 | /* | 1496 | /* |
1439 | * Fits with at least 25% to spare. | 1497 | * Fits with at least 25% to spare. |
1440 | */ | 1498 | */ |
@@ -1481,34 +1539,53 @@ xfs_dir2_leafn_unbalance( | |||
1481 | xfs_da_args_t *args; /* operation arguments */ | 1539 | xfs_da_args_t *args; /* operation arguments */ |
1482 | xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */ | 1540 | xfs_dir2_leaf_t *drop_leaf; /* dead leaf structure */ |
1483 | xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */ | 1541 | xfs_dir2_leaf_t *save_leaf; /* surviving leaf structure */ |
1542 | struct xfs_dir3_icleaf_hdr savehdr; | ||
1543 | struct xfs_dir3_icleaf_hdr drophdr; | ||
1544 | struct xfs_dir2_leaf_entry *sents; | ||
1545 | struct xfs_dir2_leaf_entry *dents; | ||
1484 | 1546 | ||
1485 | args = state->args; | 1547 | args = state->args; |
1486 | ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); | 1548 | ASSERT(drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); |
1487 | ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); | 1549 | ASSERT(save_blk->magic == XFS_DIR2_LEAFN_MAGIC); |
1488 | drop_leaf = drop_blk->bp->b_addr; | 1550 | drop_leaf = drop_blk->bp->b_addr; |
1489 | save_leaf = save_blk->bp->b_addr; | 1551 | save_leaf = save_blk->bp->b_addr; |
1490 | ASSERT(drop_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1552 | |
1491 | ASSERT(save_leaf->hdr.info.magic == cpu_to_be16(XFS_DIR2_LEAFN_MAGIC)); | 1553 | xfs_dir3_leaf_hdr_from_disk(&savehdr, save_leaf); |
1554 | xfs_dir3_leaf_hdr_from_disk(&drophdr, drop_leaf); | ||
1555 | sents = xfs_dir3_leaf_ents_p(save_leaf); | ||
1556 | dents = xfs_dir3_leaf_ents_p(drop_leaf); | ||
1557 | |||
1492 | /* | 1558 | /* |
1493 | * If there are any stale leaf entries, take this opportunity | 1559 | * If there are any stale leaf entries, take this opportunity |
1494 | * to purge them. | 1560 | * to purge them. |
1495 | */ | 1561 | */ |
1496 | if (drop_leaf->hdr.stale) | 1562 | if (drophdr.stale) |
1497 | xfs_dir2_leaf_compact(args, drop_blk->bp); | 1563 | xfs_dir3_leaf_compact(args, &drophdr, drop_blk->bp); |
1498 | if (save_leaf->hdr.stale) | 1564 | if (savehdr.stale) |
1499 | xfs_dir2_leaf_compact(args, save_blk->bp); | 1565 | xfs_dir3_leaf_compact(args, &savehdr, save_blk->bp); |
1566 | |||
1500 | /* | 1567 | /* |
1501 | * Move the entries from drop to the appropriate end of save. | 1568 | * Move the entries from drop to the appropriate end of save. |
1502 | */ | 1569 | */ |
1503 | drop_blk->hashval = be32_to_cpu(drop_leaf->ents[be16_to_cpu(drop_leaf->hdr.count) - 1].hashval); | 1570 | drop_blk->hashval = be32_to_cpu(dents[drophdr.count - 1].hashval); |
1504 | if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) | 1571 | if (xfs_dir2_leafn_order(save_blk->bp, drop_blk->bp)) |
1505 | xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, 0, | 1572 | xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, |
1506 | be16_to_cpu(drop_leaf->hdr.count)); | 1573 | save_blk->bp, &savehdr, sents, 0, |
1574 | drophdr.count); | ||
1507 | else | 1575 | else |
1508 | xfs_dir2_leafn_moveents(args, drop_blk->bp, 0, save_blk->bp, | 1576 | xfs_dir3_leafn_moveents(args, drop_blk->bp, &drophdr, dents, 0, |
1509 | be16_to_cpu(save_leaf->hdr.count), be16_to_cpu(drop_leaf->hdr.count)); | 1577 | save_blk->bp, &savehdr, sents, |
1510 | save_blk->hashval = be32_to_cpu(save_leaf->ents[be16_to_cpu(save_leaf->hdr.count) - 1].hashval); | 1578 | savehdr.count, drophdr.count); |
1511 | xfs_dir2_leafn_check(args->dp, save_blk->bp); | 1579 | save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); |
1580 | |||
1581 | /* log the changes made when moving the entries */ | ||
1582 | xfs_dir3_leaf_hdr_to_disk(save_leaf, &savehdr); | ||
1583 | xfs_dir3_leaf_hdr_to_disk(drop_leaf, &drophdr); | ||
1584 | xfs_dir3_leaf_log_header(args->trans, save_blk->bp); | ||
1585 | xfs_dir3_leaf_log_header(args->trans, drop_blk->bp); | ||
1586 | |||
1587 | xfs_dir3_leaf_check(args->dp->i_mount, save_blk->bp); | ||
1588 | xfs_dir3_leaf_check(args->dp->i_mount, drop_blk->bp); | ||
1512 | } | 1589 | } |
1513 | 1590 | ||
1514 | /* | 1591 | /* |
@@ -2113,13 +2190,15 @@ xfs_dir2_node_replace( | |||
2113 | * and locked it. But paranoia is good. | 2190 | * and locked it. But paranoia is good. |
2114 | */ | 2191 | */ |
2115 | if (rval == EEXIST) { | 2192 | if (rval == EEXIST) { |
2193 | struct xfs_dir2_leaf_entry *ents; | ||
2116 | /* | 2194 | /* |
2117 | * Find the leaf entry. | 2195 | * Find the leaf entry. |
2118 | */ | 2196 | */ |
2119 | blk = &state->path.blk[state->path.active - 1]; | 2197 | blk = &state->path.blk[state->path.active - 1]; |
2120 | ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); | 2198 | ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); |
2121 | leaf = blk->bp->b_addr; | 2199 | leaf = blk->bp->b_addr; |
2122 | lep = &leaf->ents[blk->index]; | 2200 | ents = xfs_dir3_leaf_ents_p(leaf); |
2201 | lep = &ents[blk->index]; | ||
2123 | ASSERT(state->extravalid); | 2202 | ASSERT(state->extravalid); |
2124 | /* | 2203 | /* |
2125 | * Point to the data entry. | 2204 | * Point to the data entry. |
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h index 910e64413316..932565d6ef2a 100644 --- a/fs/xfs/xfs_dir2_priv.h +++ b/fs/xfs/xfs_dir2_priv.h | |||
@@ -77,24 +77,25 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp, | |||
77 | xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); | 77 | xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp); |
78 | 78 | ||
79 | /* xfs_dir2_leaf.c */ | 79 | /* xfs_dir2_leaf.c */ |
80 | extern const struct xfs_buf_ops xfs_dir2_leafn_buf_ops; | 80 | extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; |
81 | 81 | ||
82 | extern int xfs_dir2_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, | 82 | extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp, |
83 | xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp); | 83 | xfs_dablk_t fbno, xfs_daddr_t mappedbno, struct xfs_buf **bpp); |
84 | extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args, | 84 | extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args, |
85 | struct xfs_buf *dbp); | 85 | struct xfs_buf *dbp); |
86 | extern int xfs_dir2_leaf_addname(struct xfs_da_args *args); | 86 | extern int xfs_dir2_leaf_addname(struct xfs_da_args *args); |
87 | extern void xfs_dir2_leaf_compact(struct xfs_da_args *args, | 87 | extern void xfs_dir3_leaf_compact(struct xfs_da_args *args, |
88 | struct xfs_buf *bp); | 88 | struct xfs_dir3_icleaf_hdr *leafhdr, struct xfs_buf *bp); |
89 | extern void xfs_dir2_leaf_compact_x1(struct xfs_buf *bp, int *indexp, | 89 | extern void xfs_dir3_leaf_compact_x1(struct xfs_dir3_icleaf_hdr *leafhdr, |
90 | struct xfs_dir2_leaf_entry *ents, int *indexp, | ||
90 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); | 91 | int *lowstalep, int *highstalep, int *lowlogp, int *highlogp); |
91 | extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent, | 92 | extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent, |
92 | size_t bufsize, xfs_off_t *offset, filldir_t filldir); | 93 | size_t bufsize, xfs_off_t *offset, filldir_t filldir); |
93 | extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno, | 94 | extern int xfs_dir3_leaf_get_buf(struct xfs_da_args *args, xfs_dir2_db_t bno, |
94 | struct xfs_buf **bpp, int magic); | 95 | struct xfs_buf **bpp, __uint16_t magic); |
95 | extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, | 96 | extern void xfs_dir3_leaf_log_ents(struct xfs_trans *tp, struct xfs_buf *bp, |
96 | int first, int last); | 97 | int first, int last); |
97 | extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp, | 98 | extern void xfs_dir3_leaf_log_header(struct xfs_trans *tp, |
98 | struct xfs_buf *bp); | 99 | struct xfs_buf *bp); |
99 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); | 100 | extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args); |
100 | extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); | 101 | extern int xfs_dir2_leaf_removename(struct xfs_da_args *args); |
@@ -104,11 +105,18 @@ extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args, | |||
104 | extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args, | 105 | extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args, |
105 | struct xfs_buf *lbp, xfs_dir2_db_t db); | 106 | struct xfs_buf *lbp, xfs_dir2_db_t db); |
106 | extern struct xfs_dir2_leaf_entry * | 107 | extern struct xfs_dir2_leaf_entry * |
107 | xfs_dir2_leaf_find_entry(struct xfs_dir2_leaf *leaf, int index, int compact, | 108 | xfs_dir3_leaf_find_entry(struct xfs_dir3_icleaf_hdr *leafhdr, |
108 | int lowstale, int highstale, | 109 | struct xfs_dir2_leaf_entry *ents, int index, int compact, |
109 | int *lfloglow, int *lfloghigh); | 110 | int lowstale, int highstale, int *lfloglow, int *lfloghigh); |
110 | extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); | 111 | extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state); |
111 | 112 | ||
113 | extern void xfs_dir3_leaf_hdr_from_disk(struct xfs_dir3_icleaf_hdr *to, | ||
114 | struct xfs_dir2_leaf *from); | ||
115 | extern void xfs_dir3_leaf_hdr_to_disk(struct xfs_dir2_leaf *to, | ||
116 | struct xfs_dir3_icleaf_hdr *from); | ||
117 | extern bool xfs_dir3_leaf_check_int(struct xfs_mount *mp, | ||
118 | struct xfs_dir3_icleaf_hdr *hdr, struct xfs_dir2_leaf *leaf); | ||
119 | |||
112 | /* xfs_dir2_node.c */ | 120 | /* xfs_dir2_node.c */ |
113 | extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, | 121 | extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args, |
114 | struct xfs_buf *lbp); | 122 | struct xfs_buf *lbp); |