diff options
author | Tristan Ye <tristan.ye@oracle.com> | 2011-03-18 02:35:35 -0400 |
---|---|---|
committer | Tristan Ye <tristan.ye@oracle.com> | 2011-05-25 03:17:10 -0400 |
commit | 1c06b9126130aa4a917bba81c39579ed08a67b4e (patch) | |
tree | 553ebd98601d3edcae182002f72246a04094d9c6 /fs/ocfs2/move_extents.c | |
parent | 202ee5facb2c55f36a4324a4f56d8bdf3617a579 (diff) |
Ocfs2/move_extents: find the victim alloc group, where the given #blk fits.
This function tries locate the right alloc group, where a given physical block
resides, it returns the caller a buffer_head of victim group descriptor, and also
the offset of block in this group, by passing the block number.
Signed-off-by: Tristan Ye <tristan.ye@oracle.com>
Diffstat (limited to 'fs/ocfs2/move_extents.c')
-rw-r--r-- | fs/ocfs2/move_extents.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 78db10d4c7f1..68e00b47332b 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
@@ -351,3 +351,107 @@ out: | |||
351 | 351 | ||
352 | return ret; | 352 | return ret; |
353 | } | 353 | } |
354 | |||
355 | /* | ||
356 | * find the victim alloc group, where #blkno fits. | ||
357 | */ | ||
358 | static int ocfs2_find_victim_alloc_group(struct inode *inode, | ||
359 | u64 vict_blkno, | ||
360 | int type, int slot, | ||
361 | int *vict_bit, | ||
362 | struct buffer_head **ret_bh) | ||
363 | { | ||
364 | int ret, i, blocks_per_unit = 1; | ||
365 | u64 blkno; | ||
366 | char namebuf[40]; | ||
367 | |||
368 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
369 | struct buffer_head *ac_bh = NULL, *gd_bh = NULL; | ||
370 | struct ocfs2_chain_list *cl; | ||
371 | struct ocfs2_chain_rec *rec; | ||
372 | struct ocfs2_dinode *ac_dinode; | ||
373 | struct ocfs2_group_desc *bg; | ||
374 | |||
375 | ocfs2_sprintf_system_inode_name(namebuf, sizeof(namebuf), type, slot); | ||
376 | ret = ocfs2_lookup_ino_from_name(osb->sys_root_inode, namebuf, | ||
377 | strlen(namebuf), &blkno); | ||
378 | if (ret) { | ||
379 | ret = -ENOENT; | ||
380 | goto out; | ||
381 | } | ||
382 | |||
383 | ret = ocfs2_read_blocks_sync(osb, blkno, 1, &ac_bh); | ||
384 | if (ret) { | ||
385 | mlog_errno(ret); | ||
386 | goto out; | ||
387 | } | ||
388 | |||
389 | ac_dinode = (struct ocfs2_dinode *)ac_bh->b_data; | ||
390 | cl = &(ac_dinode->id2.i_chain); | ||
391 | rec = &(cl->cl_recs[0]); | ||
392 | |||
393 | if (type == GLOBAL_BITMAP_SYSTEM_INODE) | ||
394 | blocks_per_unit <<= (osb->s_clustersize_bits - | ||
395 | inode->i_sb->s_blocksize_bits); | ||
396 | /* | ||
397 | * 'vict_blkno' was out of the valid range. | ||
398 | */ | ||
399 | if ((vict_blkno < le64_to_cpu(rec->c_blkno)) || | ||
400 | (vict_blkno >= (le32_to_cpu(ac_dinode->id1.bitmap1.i_total) * | ||
401 | blocks_per_unit))) { | ||
402 | ret = -EINVAL; | ||
403 | goto out; | ||
404 | } | ||
405 | |||
406 | for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i++) { | ||
407 | |||
408 | rec = &(cl->cl_recs[i]); | ||
409 | if (!rec) | ||
410 | continue; | ||
411 | |||
412 | bg = NULL; | ||
413 | |||
414 | do { | ||
415 | if (!bg) | ||
416 | blkno = le64_to_cpu(rec->c_blkno); | ||
417 | else | ||
418 | blkno = le64_to_cpu(bg->bg_next_group); | ||
419 | |||
420 | if (gd_bh) { | ||
421 | brelse(gd_bh); | ||
422 | gd_bh = NULL; | ||
423 | } | ||
424 | |||
425 | ret = ocfs2_read_blocks_sync(osb, blkno, 1, &gd_bh); | ||
426 | if (ret) { | ||
427 | mlog_errno(ret); | ||
428 | goto out; | ||
429 | } | ||
430 | |||
431 | bg = (struct ocfs2_group_desc *)gd_bh->b_data; | ||
432 | |||
433 | if (vict_blkno < (le64_to_cpu(bg->bg_blkno) + | ||
434 | le16_to_cpu(bg->bg_bits))) { | ||
435 | |||
436 | *ret_bh = gd_bh; | ||
437 | *vict_bit = (vict_blkno - blkno) / | ||
438 | blocks_per_unit; | ||
439 | mlog(0, "find the victim group: #%llu, " | ||
440 | "total_bits: %u, vict_bit: %u\n", | ||
441 | blkno, le16_to_cpu(bg->bg_bits), | ||
442 | *vict_bit); | ||
443 | goto out; | ||
444 | } | ||
445 | |||
446 | } while (le64_to_cpu(bg->bg_next_group)); | ||
447 | } | ||
448 | |||
449 | ret = -EINVAL; | ||
450 | out: | ||
451 | brelse(ac_bh); | ||
452 | |||
453 | /* | ||
454 | * caller has to release the gd_bh properly. | ||
455 | */ | ||
456 | return ret; | ||
457 | } | ||