aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/move_extents.c
diff options
context:
space:
mode:
authorTristan Ye <tristan.ye@oracle.com>2011-03-18 02:35:35 -0400
committerTristan Ye <tristan.ye@oracle.com>2011-05-25 03:17:10 -0400
commit1c06b9126130aa4a917bba81c39579ed08a67b4e (patch)
tree553ebd98601d3edcae182002f72246a04094d9c6 /fs/ocfs2/move_extents.c
parent202ee5facb2c55f36a4324a4f56d8bdf3617a579 (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.c104
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 */
358static 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;
450out:
451 brelse(ac_bh);
452
453 /*
454 * caller has to release the gd_bh properly.
455 */
456 return ret;
457}