diff options
| -rw-r--r-- | fs/ocfs2/xattr.c | 351 |
1 files changed, 328 insertions, 23 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index fb17f7fe4c66..acccdfabd2d6 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -99,12 +99,25 @@ struct ocfs2_xattr_search { | |||
| 99 | */ | 99 | */ |
| 100 | struct buffer_head *xattr_bh; | 100 | struct buffer_head *xattr_bh; |
| 101 | struct ocfs2_xattr_header *header; | 101 | struct ocfs2_xattr_header *header; |
| 102 | struct ocfs2_xattr_bucket bucket; | ||
| 102 | void *base; | 103 | void *base; |
| 103 | void *end; | 104 | void *end; |
| 104 | struct ocfs2_xattr_entry *here; | 105 | struct ocfs2_xattr_entry *here; |
| 105 | int not_found; | 106 | int not_found; |
| 106 | }; | 107 | }; |
| 107 | 108 | ||
| 109 | static int ocfs2_xattr_bucket_get_name_value(struct inode *inode, | ||
| 110 | struct ocfs2_xattr_header *xh, | ||
| 111 | int index, | ||
| 112 | int *block_off, | ||
| 113 | int *new_offset); | ||
| 114 | |||
| 115 | static int ocfs2_xattr_index_block_find(struct inode *inode, | ||
| 116 | struct buffer_head *root_bh, | ||
| 117 | int name_index, | ||
| 118 | const char *name, | ||
| 119 | struct ocfs2_xattr_search *xs); | ||
| 120 | |||
| 108 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | 121 | static int ocfs2_xattr_tree_list_index_block(struct inode *inode, |
| 109 | struct ocfs2_xattr_tree_root *xt, | 122 | struct ocfs2_xattr_tree_root *xt, |
| 110 | char *buffer, | 123 | char *buffer, |
| @@ -604,7 +617,7 @@ static int ocfs2_xattr_find_entry(int name_index, | |||
| 604 | } | 617 | } |
| 605 | 618 | ||
| 606 | static int ocfs2_xattr_get_value_outside(struct inode *inode, | 619 | static int ocfs2_xattr_get_value_outside(struct inode *inode, |
| 607 | struct ocfs2_xattr_search *xs, | 620 | struct ocfs2_xattr_value_root *xv, |
| 608 | void *buffer, | 621 | void *buffer, |
| 609 | size_t len) | 622 | size_t len) |
| 610 | { | 623 | { |
| @@ -613,12 +626,8 @@ static int ocfs2_xattr_get_value_outside(struct inode *inode, | |||
| 613 | int i, ret = 0; | 626 | int i, ret = 0; |
| 614 | size_t cplen, blocksize; | 627 | size_t cplen, blocksize; |
| 615 | struct buffer_head *bh = NULL; | 628 | struct buffer_head *bh = NULL; |
| 616 | struct ocfs2_xattr_value_root *xv; | ||
| 617 | struct ocfs2_extent_list *el; | 629 | struct ocfs2_extent_list *el; |
| 618 | 630 | ||
| 619 | xv = (struct ocfs2_xattr_value_root *) | ||
| 620 | (xs->base + le16_to_cpu(xs->here->xe_name_offset) + | ||
| 621 | OCFS2_XATTR_SIZE(xs->here->xe_name_len)); | ||
| 622 | el = &xv->xr_list; | 631 | el = &xv->xr_list; |
| 623 | clusters = le32_to_cpu(xv->xr_clusters); | 632 | clusters = le32_to_cpu(xv->xr_clusters); |
| 624 | bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); | 633 | bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); |
| @@ -668,6 +677,7 @@ static int ocfs2_xattr_ibody_get(struct inode *inode, | |||
| 668 | { | 677 | { |
| 669 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 678 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 670 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 679 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
| 680 | struct ocfs2_xattr_value_root *xv; | ||
| 671 | size_t size; | 681 | size_t size; |
| 672 | int ret = 0; | 682 | int ret = 0; |
| 673 | 683 | ||
| @@ -692,7 +702,11 @@ static int ocfs2_xattr_ibody_get(struct inode *inode, | |||
| 692 | le16_to_cpu(xs->here->xe_name_offset) + | 702 | le16_to_cpu(xs->here->xe_name_offset) + |
| 693 | OCFS2_XATTR_SIZE(xs->here->xe_name_len), size); | 703 | OCFS2_XATTR_SIZE(xs->here->xe_name_len), size); |
| 694 | } else { | 704 | } else { |
| 695 | ret = ocfs2_xattr_get_value_outside(inode, xs, | 705 | xv = (struct ocfs2_xattr_value_root *) |
| 706 | (xs->base + le16_to_cpu( | ||
| 707 | xs->here->xe_name_offset) + | ||
| 708 | OCFS2_XATTR_SIZE(xs->here->xe_name_len)); | ||
| 709 | ret = ocfs2_xattr_get_value_outside(inode, xv, | ||
| 696 | buffer, size); | 710 | buffer, size); |
| 697 | if (ret < 0) { | 711 | if (ret < 0) { |
| 698 | mlog_errno(ret); | 712 | mlog_errno(ret); |
| @@ -714,12 +728,15 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 714 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 728 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
| 715 | struct buffer_head *blk_bh = NULL; | 729 | struct buffer_head *blk_bh = NULL; |
| 716 | struct ocfs2_xattr_block *xb; | 730 | struct ocfs2_xattr_block *xb; |
| 731 | struct ocfs2_xattr_value_root *xv; | ||
| 717 | size_t size; | 732 | size_t size; |
| 718 | int ret = -ENODATA; | 733 | int ret = -ENODATA, name_offset, name_len, block_off, i; |
| 719 | 734 | ||
| 720 | if (!di->i_xattr_loc) | 735 | if (!di->i_xattr_loc) |
| 721 | return ret; | 736 | return ret; |
| 722 | 737 | ||
| 738 | memset(&xs->bucket, 0, sizeof(xs->bucket)); | ||
| 739 | |||
| 723 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), | 740 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), |
| 724 | le64_to_cpu(di->i_xattr_loc), | 741 | le64_to_cpu(di->i_xattr_loc), |
| 725 | &blk_bh, OCFS2_BH_CACHED, inode); | 742 | &blk_bh, OCFS2_BH_CACHED, inode); |
| @@ -736,12 +753,19 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 736 | 753 | ||
| 737 | xs->xattr_bh = blk_bh; | 754 | xs->xattr_bh = blk_bh; |
| 738 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; | 755 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
| 739 | xs->header = &xb->xb_attrs.xb_header; | ||
| 740 | xs->base = (void *)xs->header; | ||
| 741 | xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; | ||
| 742 | xs->here = xs->header->xh_entries; | ||
| 743 | 756 | ||
| 744 | ret = ocfs2_xattr_find_entry(name_index, name, xs); | 757 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
| 758 | xs->header = &xb->xb_attrs.xb_header; | ||
| 759 | xs->base = (void *)xs->header; | ||
| 760 | xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; | ||
| 761 | xs->here = xs->header->xh_entries; | ||
| 762 | |||
| 763 | ret = ocfs2_xattr_find_entry(name_index, name, xs); | ||
| 764 | } else | ||
| 765 | ret = ocfs2_xattr_index_block_find(inode, blk_bh, | ||
| 766 | name_index, | ||
| 767 | name, xs); | ||
| 768 | |||
| 745 | if (ret) | 769 | if (ret) |
| 746 | goto cleanup; | 770 | goto cleanup; |
| 747 | size = le64_to_cpu(xs->here->xe_value_size); | 771 | size = le64_to_cpu(xs->here->xe_value_size); |
| @@ -749,12 +773,26 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 749 | ret = -ERANGE; | 773 | ret = -ERANGE; |
| 750 | if (size > buffer_size) | 774 | if (size > buffer_size) |
| 751 | goto cleanup; | 775 | goto cleanup; |
| 776 | |||
| 777 | name_offset = le16_to_cpu(xs->here->xe_name_offset); | ||
| 778 | name_len = OCFS2_XATTR_SIZE(xs->here->xe_name_len); | ||
| 779 | i = xs->here - xs->header->xh_entries; | ||
| 780 | |||
| 781 | if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) { | ||
| 782 | ret = ocfs2_xattr_bucket_get_name_value(inode, | ||
| 783 | xs->bucket.xh, | ||
| 784 | i, | ||
| 785 | &block_off, | ||
| 786 | &name_offset); | ||
| 787 | xs->base = xs->bucket.bhs[block_off]->b_data; | ||
| 788 | } | ||
| 752 | if (ocfs2_xattr_is_local(xs->here)) { | 789 | if (ocfs2_xattr_is_local(xs->here)) { |
| 753 | memcpy(buffer, (void *)xs->base + | 790 | memcpy(buffer, (void *)xs->base + |
| 754 | le16_to_cpu(xs->here->xe_name_offset) + | 791 | name_offset + name_len, size); |
| 755 | OCFS2_XATTR_SIZE(xs->here->xe_name_len), size); | ||
| 756 | } else { | 792 | } else { |
| 757 | ret = ocfs2_xattr_get_value_outside(inode, xs, | 793 | xv = (struct ocfs2_xattr_value_root *) |
| 794 | (xs->base + name_offset + name_len); | ||
| 795 | ret = ocfs2_xattr_get_value_outside(inode, xv, | ||
| 758 | buffer, size); | 796 | buffer, size); |
| 759 | if (ret < 0) { | 797 | if (ret < 0) { |
| 760 | mlog_errno(ret); | 798 | mlog_errno(ret); |
| @@ -764,8 +802,11 @@ static int ocfs2_xattr_block_get(struct inode *inode, | |||
| 764 | } | 802 | } |
| 765 | ret = size; | 803 | ret = size; |
| 766 | cleanup: | 804 | cleanup: |
| 767 | brelse(blk_bh); | 805 | for (i = 0; i < OCFS2_XATTR_MAX_BLOCKS_PER_BUCKET; i++) |
| 806 | brelse(xs->bucket.bhs[i]); | ||
| 807 | memset(&xs->bucket, 0, sizeof(xs->bucket)); | ||
| 768 | 808 | ||
| 809 | brelse(blk_bh); | ||
| 769 | return ret; | 810 | return ret; |
| 770 | } | 811 | } |
| 771 | 812 | ||
| @@ -1679,6 +1720,7 @@ static int ocfs2_xattr_block_find(struct inode *inode, | |||
| 1679 | { | 1720 | { |
| 1680 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 1721 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
| 1681 | struct buffer_head *blk_bh = NULL; | 1722 | struct buffer_head *blk_bh = NULL; |
| 1723 | struct ocfs2_xattr_block *xb; | ||
| 1682 | int ret = 0; | 1724 | int ret = 0; |
| 1683 | 1725 | ||
| 1684 | if (!di->i_xattr_loc) | 1726 | if (!di->i_xattr_loc) |
| @@ -1699,20 +1741,26 @@ static int ocfs2_xattr_block_find(struct inode *inode, | |||
| 1699 | } | 1741 | } |
| 1700 | 1742 | ||
| 1701 | xs->xattr_bh = blk_bh; | 1743 | xs->xattr_bh = blk_bh; |
| 1702 | xs->header = &((struct ocfs2_xattr_block *)blk_bh->b_data)-> | 1744 | xb = (struct ocfs2_xattr_block *)blk_bh->b_data; |
| 1703 | xb_attrs.xb_header; | 1745 | |
| 1704 | xs->base = (void *)xs->header; | 1746 | if (!(le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED)) { |
| 1705 | xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; | 1747 | xs->header = &xb->xb_attrs.xb_header; |
| 1706 | xs->here = xs->header->xh_entries; | 1748 | xs->base = (void *)xs->header; |
| 1749 | xs->end = (void *)(blk_bh->b_data) + blk_bh->b_size; | ||
| 1750 | xs->here = xs->header->xh_entries; | ||
| 1751 | |||
| 1752 | ret = ocfs2_xattr_find_entry(name_index, name, xs); | ||
| 1753 | } else | ||
| 1754 | ret = ocfs2_xattr_index_block_find(inode, blk_bh, | ||
| 1755 | name_index, | ||
| 1756 | name, xs); | ||
| 1707 | 1757 | ||
| 1708 | ret = ocfs2_xattr_find_entry(name_index, name, xs); | ||
| 1709 | if (ret && ret != -ENODATA) { | 1758 | if (ret && ret != -ENODATA) { |
| 1710 | xs->xattr_bh = NULL; | 1759 | xs->xattr_bh = NULL; |
| 1711 | goto cleanup; | 1760 | goto cleanup; |
| 1712 | } | 1761 | } |
| 1713 | xs->not_found = ret; | 1762 | xs->not_found = ret; |
| 1714 | return 0; | 1763 | return 0; |
| 1715 | |||
| 1716 | cleanup: | 1764 | cleanup: |
| 1717 | brelse(blk_bh); | 1765 | brelse(blk_bh); |
| 1718 | 1766 | ||
| @@ -1941,6 +1989,18 @@ cleanup: | |||
| 1941 | return ret; | 1989 | return ret; |
| 1942 | } | 1990 | } |
| 1943 | 1991 | ||
| 1992 | static inline u32 ocfs2_xattr_hash_by_name(struct inode *inode, | ||
| 1993 | int name_index, | ||
| 1994 | const char *suffix_name) | ||
| 1995 | { | ||
| 1996 | struct xattr_handler *handler = ocfs2_xattr_handler(name_index); | ||
| 1997 | char *prefix = handler->prefix; | ||
| 1998 | int prefix_len = strlen(handler->prefix); | ||
| 1999 | |||
| 2000 | return ocfs2_xattr_name_hash(inode, prefix, prefix_len, | ||
| 2001 | (char *)suffix_name, strlen(suffix_name)); | ||
| 2002 | } | ||
| 2003 | |||
| 1944 | /* | 2004 | /* |
| 1945 | * Find the xattr extent rec which may contains name_hash. | 2005 | * Find the xattr extent rec which may contains name_hash. |
| 1946 | * e_cpos will be the first name hash of the xattr rec. | 2006 | * e_cpos will be the first name hash of the xattr rec. |
| @@ -2010,6 +2070,251 @@ typedef int (xattr_bucket_func)(struct inode *inode, | |||
| 2010 | struct ocfs2_xattr_bucket *bucket, | 2070 | struct ocfs2_xattr_bucket *bucket, |
| 2011 | void *para); | 2071 | void *para); |
| 2012 | 2072 | ||
| 2073 | static int ocfs2_find_xe_in_bucket(struct inode *inode, | ||
| 2074 | struct buffer_head *header_bh, | ||
| 2075 | int name_index, | ||
| 2076 | const char *name, | ||
| 2077 | u32 name_hash, | ||
| 2078 | u16 *xe_index, | ||
| 2079 | int *found) | ||
| 2080 | { | ||
| 2081 | int i, ret = 0, cmp = 1, block_off, new_offset; | ||
| 2082 | struct ocfs2_xattr_header *xh = | ||
| 2083 | (struct ocfs2_xattr_header *)header_bh->b_data; | ||
| 2084 | size_t name_len = strlen(name); | ||
| 2085 | struct ocfs2_xattr_entry *xe = NULL; | ||
| 2086 | struct buffer_head *name_bh = NULL; | ||
| 2087 | char *xe_name; | ||
| 2088 | |||
| 2089 | /* | ||
| 2090 | * We don't use binary search in the bucket because there | ||
| 2091 | * may be multiple entries with the same name hash. | ||
| 2092 | */ | ||
| 2093 | for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { | ||
| 2094 | xe = &xh->xh_entries[i]; | ||
| 2095 | |||
| 2096 | if (name_hash > le32_to_cpu(xe->xe_name_hash)) | ||
| 2097 | continue; | ||
| 2098 | else if (name_hash < le32_to_cpu(xe->xe_name_hash)) | ||
| 2099 | break; | ||
| 2100 | |||
| 2101 | cmp = name_index - ocfs2_xattr_get_type(xe); | ||
| 2102 | if (!cmp) | ||
| 2103 | cmp = name_len - xe->xe_name_len; | ||
| 2104 | if (cmp) | ||
| 2105 | continue; | ||
| 2106 | |||
| 2107 | ret = ocfs2_xattr_bucket_get_name_value(inode, | ||
| 2108 | xh, | ||
| 2109 | i, | ||
| 2110 | &block_off, | ||
| 2111 | &new_offset); | ||
| 2112 | if (ret) { | ||
| 2113 | mlog_errno(ret); | ||
| 2114 | break; | ||
| 2115 | } | ||
| 2116 | |||
| 2117 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), | ||
| 2118 | header_bh->b_blocknr + block_off, | ||
| 2119 | &name_bh, OCFS2_BH_CACHED, inode); | ||
| 2120 | if (ret) { | ||
| 2121 | mlog_errno(ret); | ||
| 2122 | break; | ||
| 2123 | } | ||
| 2124 | xe_name = name_bh->b_data + new_offset; | ||
| 2125 | |||
| 2126 | cmp = memcmp(name, xe_name, name_len); | ||
| 2127 | brelse(name_bh); | ||
| 2128 | name_bh = NULL; | ||
| 2129 | |||
| 2130 | if (cmp == 0) { | ||
| 2131 | *xe_index = i; | ||
| 2132 | *found = 1; | ||
| 2133 | ret = 0; | ||
| 2134 | break; | ||
| 2135 | } | ||
| 2136 | } | ||
| 2137 | |||
| 2138 | return ret; | ||
| 2139 | } | ||
| 2140 | |||
| 2141 | /* | ||
| 2142 | * Find the specified xattr entry in a series of buckets. | ||
| 2143 | * This series start from p_blkno and last for num_clusters. | ||
| 2144 | * The ocfs2_xattr_header.xh_num_buckets of the first bucket contains | ||
| 2145 | * the num of the valid buckets. | ||
| 2146 | * | ||
| 2147 | * Return the buffer_head this xattr should reside in. And if the xattr's | ||
| 2148 | * hash is in the gap of 2 buckets, return the lower bucket. | ||
| 2149 | */ | ||
| 2150 | static int ocfs2_xattr_bucket_find(struct inode *inode, | ||
| 2151 | int name_index, | ||
| 2152 | const char *name, | ||
| 2153 | u32 name_hash, | ||
| 2154 | u64 p_blkno, | ||
| 2155 | u32 first_hash, | ||
| 2156 | u32 num_clusters, | ||
| 2157 | struct ocfs2_xattr_search *xs) | ||
| 2158 | { | ||
| 2159 | int ret, found = 0; | ||
| 2160 | struct buffer_head *bh = NULL; | ||
| 2161 | struct buffer_head *lower_bh = NULL; | ||
| 2162 | struct ocfs2_xattr_header *xh = NULL; | ||
| 2163 | struct ocfs2_xattr_entry *xe = NULL; | ||
| 2164 | u16 index = 0; | ||
| 2165 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
| 2166 | int low_bucket = 0, bucket, high_bucket; | ||
| 2167 | u32 last_hash; | ||
| 2168 | u64 blkno; | ||
| 2169 | |||
| 2170 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, | ||
| 2171 | &bh, OCFS2_BH_CACHED, inode); | ||
| 2172 | if (ret) { | ||
| 2173 | mlog_errno(ret); | ||
| 2174 | goto out; | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | xh = (struct ocfs2_xattr_header *)bh->b_data; | ||
| 2178 | high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1; | ||
| 2179 | |||
| 2180 | while (low_bucket <= high_bucket) { | ||
| 2181 | brelse(bh); | ||
| 2182 | bh = NULL; | ||
| 2183 | bucket = (low_bucket + high_bucket) / 2; | ||
| 2184 | |||
| 2185 | blkno = p_blkno + bucket * blk_per_bucket; | ||
| 2186 | |||
| 2187 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno, | ||
| 2188 | &bh, OCFS2_BH_CACHED, inode); | ||
| 2189 | if (ret) { | ||
| 2190 | mlog_errno(ret); | ||
| 2191 | goto out; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | xh = (struct ocfs2_xattr_header *)bh->b_data; | ||
| 2195 | xe = &xh->xh_entries[0]; | ||
| 2196 | if (name_hash < le32_to_cpu(xe->xe_name_hash)) { | ||
| 2197 | high_bucket = bucket - 1; | ||
| 2198 | continue; | ||
| 2199 | } | ||
| 2200 | |||
| 2201 | /* | ||
| 2202 | * Check whether the hash of the last entry in our | ||
| 2203 | * bucket is larger than the search one. | ||
| 2204 | */ | ||
| 2205 | xe = &xh->xh_entries[le16_to_cpu(xh->xh_count) - 1]; | ||
| 2206 | last_hash = le32_to_cpu(xe->xe_name_hash); | ||
| 2207 | |||
| 2208 | /* record lower_bh which may be the insert place. */ | ||
| 2209 | brelse(lower_bh); | ||
| 2210 | lower_bh = bh; | ||
| 2211 | bh = NULL; | ||
| 2212 | |||
| 2213 | if (name_hash > le32_to_cpu(xe->xe_name_hash)) { | ||
| 2214 | low_bucket = bucket + 1; | ||
| 2215 | continue; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | /* the searched xattr should reside in this bucket if exists. */ | ||
| 2219 | ret = ocfs2_find_xe_in_bucket(inode, lower_bh, | ||
| 2220 | name_index, name, name_hash, | ||
| 2221 | &index, &found); | ||
| 2222 | if (ret) { | ||
| 2223 | mlog_errno(ret); | ||
| 2224 | goto out; | ||
| 2225 | } | ||
| 2226 | break; | ||
| 2227 | } | ||
| 2228 | |||
| 2229 | /* | ||
| 2230 | * Record the bucket we have found. | ||
| 2231 | * When the xattr's hash value is in the gap of 2 buckets, we will | ||
| 2232 | * always set it to the previous bucket. | ||
| 2233 | */ | ||
| 2234 | if (!lower_bh) { | ||
| 2235 | /* | ||
| 2236 | * We can't find any bucket whose first name_hash is less | ||
| 2237 | * than the find name_hash. | ||
| 2238 | */ | ||
| 2239 | BUG_ON(bh->b_blocknr != p_blkno); | ||
| 2240 | lower_bh = bh; | ||
| 2241 | bh = NULL; | ||
| 2242 | } | ||
| 2243 | xs->bucket.bhs[0] = lower_bh; | ||
| 2244 | xs->bucket.xh = (struct ocfs2_xattr_header *) | ||
| 2245 | xs->bucket.bhs[0]->b_data; | ||
| 2246 | lower_bh = NULL; | ||
| 2247 | |||
| 2248 | xs->header = xs->bucket.xh; | ||
| 2249 | xs->base = xs->bucket.bhs[0]->b_data; | ||
| 2250 | xs->end = xs->base + inode->i_sb->s_blocksize; | ||
| 2251 | |||
| 2252 | if (found) { | ||
| 2253 | /* | ||
| 2254 | * If we have found the xattr enty, read all the blocks in | ||
| 2255 | * this bucket. | ||
| 2256 | */ | ||
| 2257 | ret = ocfs2_read_blocks(OCFS2_SB(inode->i_sb), | ||
| 2258 | xs->bucket.bhs[0]->b_blocknr + 1, | ||
| 2259 | blk_per_bucket - 1, &xs->bucket.bhs[1], | ||
| 2260 | OCFS2_BH_CACHED, inode); | ||
| 2261 | if (ret) { | ||
| 2262 | mlog_errno(ret); | ||
| 2263 | goto out; | ||
| 2264 | } | ||
| 2265 | |||
| 2266 | xs->here = &xs->header->xh_entries[index]; | ||
| 2267 | mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, | ||
| 2268 | (unsigned long long)xs->bucket.bhs[0]->b_blocknr, index); | ||
| 2269 | } else | ||
| 2270 | ret = -ENODATA; | ||
| 2271 | |||
| 2272 | out: | ||
| 2273 | brelse(bh); | ||
| 2274 | brelse(lower_bh); | ||
| 2275 | return ret; | ||
| 2276 | } | ||
| 2277 | |||
| 2278 | static int ocfs2_xattr_index_block_find(struct inode *inode, | ||
| 2279 | struct buffer_head *root_bh, | ||
| 2280 | int name_index, | ||
| 2281 | const char *name, | ||
| 2282 | struct ocfs2_xattr_search *xs) | ||
| 2283 | { | ||
| 2284 | int ret; | ||
| 2285 | struct ocfs2_xattr_block *xb = | ||
| 2286 | (struct ocfs2_xattr_block *)root_bh->b_data; | ||
| 2287 | struct ocfs2_xattr_tree_root *xb_root = &xb->xb_attrs.xb_root; | ||
| 2288 | struct ocfs2_extent_list *el = &xb_root->xt_list; | ||
| 2289 | u64 p_blkno = 0; | ||
| 2290 | u32 first_hash, num_clusters = 0; | ||
| 2291 | u32 name_hash = ocfs2_xattr_hash_by_name(inode, name_index, name); | ||
| 2292 | |||
| 2293 | if (le16_to_cpu(el->l_next_free_rec) == 0) | ||
| 2294 | return -ENODATA; | ||
| 2295 | |||
| 2296 | mlog(0, "find xattr %s, hash = %u, index = %d in xattr tree\n", | ||
| 2297 | name, name_hash, name_index); | ||
| 2298 | |||
| 2299 | ret = ocfs2_xattr_get_rec(inode, name_hash, &p_blkno, &first_hash, | ||
| 2300 | &num_clusters, el); | ||
| 2301 | if (ret) { | ||
| 2302 | mlog_errno(ret); | ||
| 2303 | goto out; | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | BUG_ON(p_blkno == 0 || num_clusters == 0 || first_hash > name_hash); | ||
| 2307 | |||
| 2308 | mlog(0, "find xattr extent rec %u clusters from %llu, the first hash " | ||
| 2309 | "in the rec is %u\n", num_clusters, p_blkno, first_hash); | ||
| 2310 | |||
| 2311 | ret = ocfs2_xattr_bucket_find(inode, name_index, name, name_hash, | ||
| 2312 | p_blkno, first_hash, num_clusters, xs); | ||
| 2313 | |||
| 2314 | out: | ||
| 2315 | return ret; | ||
| 2316 | } | ||
| 2317 | |||
| 2013 | static int ocfs2_iterate_xattr_buckets(struct inode *inode, | 2318 | static int ocfs2_iterate_xattr_buckets(struct inode *inode, |
| 2014 | u64 blkno, | 2319 | u64 blkno, |
| 2015 | u32 clusters, | 2320 | u32 clusters, |
