]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Joel Becker <joel.becker@oracle.com> |
2 | Date: Mon, 27 Oct 2008 15:01:54 -0700 | |
3 | Subject: ocfs2: Use buckets in ocfs2_xattr_bucket_find(). | |
4 | Patch-mainline: 2.6.29 | |
5 | ||
6 | Change the ocfs2_xattr_bucket_find() function to use ocfs2_xattr_bucket | |
7 | as its abstraction. This makes for more efficient reads, as buckets are | |
8 | linear blocks, and also has improved caching characteristics. It also | |
9 | reads better. | |
10 | ||
11 | Signed-off-by: Joel Becker <joel.becker@oracle.com> | |
12 | Signed-off-by: Mark Fasheh <mfasheh@suse.com> | |
13 | --- | |
14 | fs/ocfs2/xattr.c | 89 +++++++++++++++++++----------------------------------- | |
15 | 1 files changed, 31 insertions(+), 58 deletions(-) | |
16 | ||
17 | diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c | |
18 | index 766494e..46986c6 100644 | |
19 | --- a/fs/ocfs2/xattr.c | |
20 | +++ b/fs/ocfs2/xattr.c | |
21 | @@ -2248,7 +2248,7 @@ typedef int (xattr_bucket_func)(struct inode *inode, | |
22 | void *para); | |
23 | ||
24 | static int ocfs2_find_xe_in_bucket(struct inode *inode, | |
25 | - struct buffer_head *header_bh, | |
26 | + struct ocfs2_xattr_bucket *bucket, | |
27 | int name_index, | |
28 | const char *name, | |
29 | u32 name_hash, | |
30 | @@ -2256,11 +2256,9 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode, | |
31 | int *found) | |
32 | { | |
33 | int i, ret = 0, cmp = 1, block_off, new_offset; | |
34 | - struct ocfs2_xattr_header *xh = | |
35 | - (struct ocfs2_xattr_header *)header_bh->b_data; | |
36 | + struct ocfs2_xattr_header *xh = bucket_xh(bucket); | |
37 | size_t name_len = strlen(name); | |
38 | struct ocfs2_xattr_entry *xe = NULL; | |
39 | - struct buffer_head *name_bh = NULL; | |
40 | char *xe_name; | |
41 | ||
42 | /* | |
43 | @@ -2291,19 +2289,8 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode, | |
44 | break; | |
45 | } | |
46 | ||
47 | - ret = ocfs2_read_block(inode, header_bh->b_blocknr + block_off, | |
48 | - &name_bh); | |
49 | - if (ret) { | |
50 | - mlog_errno(ret); | |
51 | - break; | |
52 | - } | |
53 | - xe_name = name_bh->b_data + new_offset; | |
54 | - | |
55 | - cmp = memcmp(name, xe_name, name_len); | |
56 | - brelse(name_bh); | |
57 | - name_bh = NULL; | |
58 | - | |
59 | - if (cmp == 0) { | |
60 | + xe_name = bucket_block(bucket, block_off) + new_offset; | |
61 | + if (!memcmp(name, xe_name, name_len)) { | |
62 | *xe_index = i; | |
63 | *found = 1; | |
64 | ret = 0; | |
65 | @@ -2333,39 +2320,42 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |
66 | struct ocfs2_xattr_search *xs) | |
67 | { | |
68 | int ret, found = 0; | |
69 | - struct buffer_head *bh = NULL; | |
70 | - struct buffer_head *lower_bh = NULL; | |
71 | struct ocfs2_xattr_header *xh = NULL; | |
72 | struct ocfs2_xattr_entry *xe = NULL; | |
73 | u16 index = 0; | |
74 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | |
75 | int low_bucket = 0, bucket, high_bucket; | |
76 | + struct ocfs2_xattr_bucket *search; | |
77 | u32 last_hash; | |
78 | - u64 blkno; | |
79 | + u64 blkno, lower_blkno = 0; | |
80 | ||
81 | - ret = ocfs2_read_block(inode, p_blkno, &bh); | |
82 | + search = ocfs2_xattr_bucket_new(inode); | |
83 | + if (!search) { | |
84 | + ret = -ENOMEM; | |
85 | + mlog_errno(ret); | |
86 | + goto out; | |
87 | + } | |
88 | + | |
89 | + ret = ocfs2_read_xattr_bucket(search, p_blkno); | |
90 | if (ret) { | |
91 | mlog_errno(ret); | |
92 | goto out; | |
93 | } | |
94 | ||
95 | - xh = (struct ocfs2_xattr_header *)bh->b_data; | |
96 | + xh = bucket_xh(search); | |
97 | high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1; | |
98 | - | |
99 | while (low_bucket <= high_bucket) { | |
100 | - brelse(bh); | |
101 | - bh = NULL; | |
102 | - bucket = (low_bucket + high_bucket) / 2; | |
103 | + ocfs2_xattr_bucket_relse(search); | |
104 | ||
105 | + bucket = (low_bucket + high_bucket) / 2; | |
106 | blkno = p_blkno + bucket * blk_per_bucket; | |
107 | - | |
108 | - ret = ocfs2_read_block(inode, blkno, &bh); | |
109 | + ret = ocfs2_read_xattr_bucket(search, blkno); | |
110 | if (ret) { | |
111 | mlog_errno(ret); | |
112 | goto out; | |
113 | } | |
114 | ||
115 | - xh = (struct ocfs2_xattr_header *)bh->b_data; | |
116 | + xh = bucket_xh(search); | |
117 | xe = &xh->xh_entries[0]; | |
118 | if (name_hash < le32_to_cpu(xe->xe_name_hash)) { | |
119 | high_bucket = bucket - 1; | |
120 | @@ -2382,10 +2372,8 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |
121 | ||
122 | last_hash = le32_to_cpu(xe->xe_name_hash); | |
123 | ||
124 | - /* record lower_bh which may be the insert place. */ | |
125 | - brelse(lower_bh); | |
126 | - lower_bh = bh; | |
127 | - bh = NULL; | |
128 | + /* record lower_blkno which may be the insert place. */ | |
129 | + lower_blkno = blkno; | |
130 | ||
131 | if (name_hash > le32_to_cpu(xe->xe_name_hash)) { | |
132 | low_bucket = bucket + 1; | |
133 | @@ -2393,7 +2381,7 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |
134 | } | |
135 | ||
136 | /* the searched xattr should reside in this bucket if exists. */ | |
137 | - ret = ocfs2_find_xe_in_bucket(inode, lower_bh, | |
138 | + ret = ocfs2_find_xe_in_bucket(inode, search, | |
139 | name_index, name, name_hash, | |
140 | &index, &found); | |
141 | if (ret) { | |
142 | @@ -2408,35 +2396,21 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |
143 | * When the xattr's hash value is in the gap of 2 buckets, we will | |
144 | * always set it to the previous bucket. | |
145 | */ | |
146 | - if (!lower_bh) { | |
147 | - /* | |
148 | - * We can't find any bucket whose first name_hash is less | |
149 | - * than the find name_hash. | |
150 | - */ | |
151 | - BUG_ON(bh->b_blocknr != p_blkno); | |
152 | - lower_bh = bh; | |
153 | - bh = NULL; | |
154 | + if (!lower_blkno) | |
155 | + lower_blkno = p_blkno; | |
156 | + | |
157 | + /* This should be in cache - we just read it during the search */ | |
158 | + ret = ocfs2_read_xattr_bucket(xs->bucket, lower_blkno); | |
159 | + if (ret) { | |
160 | + mlog_errno(ret); | |
161 | + goto out; | |
162 | } | |
163 | - xs->bucket->bu_bhs[0] = lower_bh; | |
164 | - lower_bh = NULL; | |
165 | ||
166 | xs->header = bucket_xh(xs->bucket); | |
167 | xs->base = bucket_block(xs->bucket, 0); | |
168 | xs->end = xs->base + inode->i_sb->s_blocksize; | |
169 | ||
170 | if (found) { | |
171 | - /* | |
172 | - * If we have found the xattr enty, read all the blocks in | |
173 | - * this bucket. | |
174 | - */ | |
175 | - ret = ocfs2_read_blocks(inode, bucket_blkno(xs->bucket) + 1, | |
176 | - blk_per_bucket - 1, &xs->bucket->bu_bhs[1], | |
177 | - 0); | |
178 | - if (ret) { | |
179 | - mlog_errno(ret); | |
180 | - goto out; | |
181 | - } | |
182 | - | |
183 | xs->here = &xs->header->xh_entries[index]; | |
184 | mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, | |
185 | (unsigned long long)bucket_blkno(xs->bucket), index); | |
186 | @@ -2444,8 +2418,7 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |
187 | ret = -ENODATA; | |
188 | ||
189 | out: | |
190 | - brelse(bh); | |
191 | - brelse(lower_bh); | |
192 | + ocfs2_xattr_bucket_free(search); | |
193 | return ret; | |
194 | } | |
195 | ||
196 | -- | |
197 | 1.5.6 | |
198 |