diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-10-27 18:01:54 -0400 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:17 -0500 |
commit | e2356a3f02cfdbce735465a2b40b6dc72a764c26 (patch) | |
tree | e4824c8d19dc2772beb56a134498a3e88acb9923 /fs/ocfs2/xattr.c | |
parent | ba937127596ec2c61437006741f7d29999284de4 (diff) |
ocfs2: Use buckets in ocfs2_xattr_bucket_find().
Change the ocfs2_xattr_bucket_find() function to use ocfs2_xattr_bucket
as its abstraction. This makes for more efficient reads, as buckets are
linear blocks, and also has improved caching characteristics. It also
reads better.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 89 |
1 files changed, 31 insertions, 58 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 766494ed6e11..46986c635eb8 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -2248,7 +2248,7 @@ typedef int (xattr_bucket_func)(struct inode *inode, | |||
2248 | void *para); | 2248 | void *para); |
2249 | 2249 | ||
2250 | static int ocfs2_find_xe_in_bucket(struct inode *inode, | 2250 | static int ocfs2_find_xe_in_bucket(struct inode *inode, |
2251 | struct buffer_head *header_bh, | 2251 | struct ocfs2_xattr_bucket *bucket, |
2252 | int name_index, | 2252 | int name_index, |
2253 | const char *name, | 2253 | const char *name, |
2254 | u32 name_hash, | 2254 | u32 name_hash, |
@@ -2256,11 +2256,9 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode, | |||
2256 | int *found) | 2256 | int *found) |
2257 | { | 2257 | { |
2258 | int i, ret = 0, cmp = 1, block_off, new_offset; | 2258 | int i, ret = 0, cmp = 1, block_off, new_offset; |
2259 | struct ocfs2_xattr_header *xh = | 2259 | struct ocfs2_xattr_header *xh = bucket_xh(bucket); |
2260 | (struct ocfs2_xattr_header *)header_bh->b_data; | ||
2261 | size_t name_len = strlen(name); | 2260 | size_t name_len = strlen(name); |
2262 | struct ocfs2_xattr_entry *xe = NULL; | 2261 | struct ocfs2_xattr_entry *xe = NULL; |
2263 | struct buffer_head *name_bh = NULL; | ||
2264 | char *xe_name; | 2262 | char *xe_name; |
2265 | 2263 | ||
2266 | /* | 2264 | /* |
@@ -2291,19 +2289,8 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode, | |||
2291 | break; | 2289 | break; |
2292 | } | 2290 | } |
2293 | 2291 | ||
2294 | ret = ocfs2_read_block(inode, header_bh->b_blocknr + block_off, | 2292 | xe_name = bucket_block(bucket, block_off) + new_offset; |
2295 | &name_bh); | 2293 | if (!memcmp(name, xe_name, name_len)) { |
2296 | if (ret) { | ||
2297 | mlog_errno(ret); | ||
2298 | break; | ||
2299 | } | ||
2300 | xe_name = name_bh->b_data + new_offset; | ||
2301 | |||
2302 | cmp = memcmp(name, xe_name, name_len); | ||
2303 | brelse(name_bh); | ||
2304 | name_bh = NULL; | ||
2305 | |||
2306 | if (cmp == 0) { | ||
2307 | *xe_index = i; | 2294 | *xe_index = i; |
2308 | *found = 1; | 2295 | *found = 1; |
2309 | ret = 0; | 2296 | ret = 0; |
@@ -2333,39 +2320,42 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |||
2333 | struct ocfs2_xattr_search *xs) | 2320 | struct ocfs2_xattr_search *xs) |
2334 | { | 2321 | { |
2335 | int ret, found = 0; | 2322 | int ret, found = 0; |
2336 | struct buffer_head *bh = NULL; | ||
2337 | struct buffer_head *lower_bh = NULL; | ||
2338 | struct ocfs2_xattr_header *xh = NULL; | 2323 | struct ocfs2_xattr_header *xh = NULL; |
2339 | struct ocfs2_xattr_entry *xe = NULL; | 2324 | struct ocfs2_xattr_entry *xe = NULL; |
2340 | u16 index = 0; | 2325 | u16 index = 0; |
2341 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 2326 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
2342 | int low_bucket = 0, bucket, high_bucket; | 2327 | int low_bucket = 0, bucket, high_bucket; |
2328 | struct ocfs2_xattr_bucket *search; | ||
2343 | u32 last_hash; | 2329 | u32 last_hash; |
2344 | u64 blkno; | 2330 | u64 blkno, lower_blkno = 0; |
2345 | 2331 | ||
2346 | ret = ocfs2_read_block(inode, p_blkno, &bh); | 2332 | search = ocfs2_xattr_bucket_new(inode); |
2333 | if (!search) { | ||
2334 | ret = -ENOMEM; | ||
2335 | mlog_errno(ret); | ||
2336 | goto out; | ||
2337 | } | ||
2338 | |||
2339 | ret = ocfs2_read_xattr_bucket(search, p_blkno); | ||
2347 | if (ret) { | 2340 | if (ret) { |
2348 | mlog_errno(ret); | 2341 | mlog_errno(ret); |
2349 | goto out; | 2342 | goto out; |
2350 | } | 2343 | } |
2351 | 2344 | ||
2352 | xh = (struct ocfs2_xattr_header *)bh->b_data; | 2345 | xh = bucket_xh(search); |
2353 | high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1; | 2346 | high_bucket = le16_to_cpu(xh->xh_num_buckets) - 1; |
2354 | |||
2355 | while (low_bucket <= high_bucket) { | 2347 | while (low_bucket <= high_bucket) { |
2356 | brelse(bh); | 2348 | ocfs2_xattr_bucket_relse(search); |
2357 | bh = NULL; | ||
2358 | bucket = (low_bucket + high_bucket) / 2; | ||
2359 | 2349 | ||
2350 | bucket = (low_bucket + high_bucket) / 2; | ||
2360 | blkno = p_blkno + bucket * blk_per_bucket; | 2351 | blkno = p_blkno + bucket * blk_per_bucket; |
2361 | 2352 | ret = ocfs2_read_xattr_bucket(search, blkno); | |
2362 | ret = ocfs2_read_block(inode, blkno, &bh); | ||
2363 | if (ret) { | 2353 | if (ret) { |
2364 | mlog_errno(ret); | 2354 | mlog_errno(ret); |
2365 | goto out; | 2355 | goto out; |
2366 | } | 2356 | } |
2367 | 2357 | ||
2368 | xh = (struct ocfs2_xattr_header *)bh->b_data; | 2358 | xh = bucket_xh(search); |
2369 | xe = &xh->xh_entries[0]; | 2359 | xe = &xh->xh_entries[0]; |
2370 | if (name_hash < le32_to_cpu(xe->xe_name_hash)) { | 2360 | if (name_hash < le32_to_cpu(xe->xe_name_hash)) { |
2371 | high_bucket = bucket - 1; | 2361 | high_bucket = bucket - 1; |
@@ -2382,10 +2372,8 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |||
2382 | 2372 | ||
2383 | last_hash = le32_to_cpu(xe->xe_name_hash); | 2373 | last_hash = le32_to_cpu(xe->xe_name_hash); |
2384 | 2374 | ||
2385 | /* record lower_bh which may be the insert place. */ | 2375 | /* record lower_blkno which may be the insert place. */ |
2386 | brelse(lower_bh); | 2376 | lower_blkno = blkno; |
2387 | lower_bh = bh; | ||
2388 | bh = NULL; | ||
2389 | 2377 | ||
2390 | if (name_hash > le32_to_cpu(xe->xe_name_hash)) { | 2378 | if (name_hash > le32_to_cpu(xe->xe_name_hash)) { |
2391 | low_bucket = bucket + 1; | 2379 | low_bucket = bucket + 1; |
@@ -2393,7 +2381,7 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |||
2393 | } | 2381 | } |
2394 | 2382 | ||
2395 | /* the searched xattr should reside in this bucket if exists. */ | 2383 | /* the searched xattr should reside in this bucket if exists. */ |
2396 | ret = ocfs2_find_xe_in_bucket(inode, lower_bh, | 2384 | ret = ocfs2_find_xe_in_bucket(inode, search, |
2397 | name_index, name, name_hash, | 2385 | name_index, name, name_hash, |
2398 | &index, &found); | 2386 | &index, &found); |
2399 | if (ret) { | 2387 | if (ret) { |
@@ -2408,35 +2396,21 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |||
2408 | * When the xattr's hash value is in the gap of 2 buckets, we will | 2396 | * When the xattr's hash value is in the gap of 2 buckets, we will |
2409 | * always set it to the previous bucket. | 2397 | * always set it to the previous bucket. |
2410 | */ | 2398 | */ |
2411 | if (!lower_bh) { | 2399 | if (!lower_blkno) |
2412 | /* | 2400 | lower_blkno = p_blkno; |
2413 | * We can't find any bucket whose first name_hash is less | 2401 | |
2414 | * than the find name_hash. | 2402 | /* This should be in cache - we just read it during the search */ |
2415 | */ | 2403 | ret = ocfs2_read_xattr_bucket(xs->bucket, lower_blkno); |
2416 | BUG_ON(bh->b_blocknr != p_blkno); | 2404 | if (ret) { |
2417 | lower_bh = bh; | 2405 | mlog_errno(ret); |
2418 | bh = NULL; | 2406 | goto out; |
2419 | } | 2407 | } |
2420 | xs->bucket->bu_bhs[0] = lower_bh; | ||
2421 | lower_bh = NULL; | ||
2422 | 2408 | ||
2423 | xs->header = bucket_xh(xs->bucket); | 2409 | xs->header = bucket_xh(xs->bucket); |
2424 | xs->base = bucket_block(xs->bucket, 0); | 2410 | xs->base = bucket_block(xs->bucket, 0); |
2425 | xs->end = xs->base + inode->i_sb->s_blocksize; | 2411 | xs->end = xs->base + inode->i_sb->s_blocksize; |
2426 | 2412 | ||
2427 | if (found) { | 2413 | if (found) { |
2428 | /* | ||
2429 | * If we have found the xattr enty, read all the blocks in | ||
2430 | * this bucket. | ||
2431 | */ | ||
2432 | ret = ocfs2_read_blocks(inode, bucket_blkno(xs->bucket) + 1, | ||
2433 | blk_per_bucket - 1, &xs->bucket->bu_bhs[1], | ||
2434 | 0); | ||
2435 | if (ret) { | ||
2436 | mlog_errno(ret); | ||
2437 | goto out; | ||
2438 | } | ||
2439 | |||
2440 | xs->here = &xs->header->xh_entries[index]; | 2414 | xs->here = &xs->header->xh_entries[index]; |
2441 | mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, | 2415 | mlog(0, "find xattr %s in bucket %llu, entry = %u\n", name, |
2442 | (unsigned long long)bucket_blkno(xs->bucket), index); | 2416 | (unsigned long long)bucket_blkno(xs->bucket), index); |
@@ -2444,8 +2418,7 @@ static int ocfs2_xattr_bucket_find(struct inode *inode, | |||
2444 | ret = -ENODATA; | 2418 | ret = -ENODATA; |
2445 | 2419 | ||
2446 | out: | 2420 | out: |
2447 | brelse(bh); | 2421 | ocfs2_xattr_bucket_free(search); |
2448 | brelse(lower_bh); | ||
2449 | return ret; | 2422 | return ret; |
2450 | } | 2423 | } |
2451 | 2424 | ||