aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ocfs2/xattr.c89
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
2250static int ocfs2_find_xe_in_bucket(struct inode *inode, 2250static 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
2446out: 2420out:
2447 brelse(bh); 2421 ocfs2_xattr_bucket_free(search);
2448 brelse(lower_bh);
2449 return ret; 2422 return ret;
2450} 2423}
2451 2424