|
@@ -455,3 +455,64 @@ out:
|
|
|
*/
|
|
|
return ret;
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ * XXX: helper to validate and adjust moving goal.
|
|
|
+ */
|
|
|
+static int ocfs2_validate_and_adjust_move_goal(struct inode *inode,
|
|
|
+ struct ocfs2_move_extents *range)
|
|
|
+{
|
|
|
+ int ret, goal_bit = 0;
|
|
|
+
|
|
|
+ struct buffer_head *gd_bh = NULL;
|
|
|
+ struct ocfs2_group_desc *bg;
|
|
|
+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
|
|
|
+ int c_to_b = 1 << (osb->s_clustersize_bits -
|
|
|
+ inode->i_sb->s_blocksize_bits);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * validate goal sits within global_bitmap, and return the victim
|
|
|
+ * group desc
|
|
|
+ */
|
|
|
+ ret = ocfs2_find_victim_alloc_group(inode, range->me_goal,
|
|
|
+ GLOBAL_BITMAP_SYSTEM_INODE,
|
|
|
+ OCFS2_INVALID_SLOT,
|
|
|
+ &goal_bit, &gd_bh);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ bg = (struct ocfs2_group_desc *)gd_bh->b_data;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * make goal become cluster aligned.
|
|
|
+ */
|
|
|
+ if (range->me_goal % c_to_b)
|
|
|
+ range->me_goal = range->me_goal / c_to_b * c_to_b;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * moving goal is not allowd to start with a group desc blok(#0 blk)
|
|
|
+ * let's compromise to the latter cluster.
|
|
|
+ */
|
|
|
+ if (range->me_goal == le64_to_cpu(bg->bg_blkno))
|
|
|
+ range->me_goal += c_to_b;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * movement is not gonna cross two groups.
|
|
|
+ */
|
|
|
+ if ((le16_to_cpu(bg->bg_bits) - goal_bit) * osb->s_clustersize <
|
|
|
+ range->me_len) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ /*
|
|
|
+ * more exact validations/adjustments will be performed later during
|
|
|
+ * moving operation for each extent range.
|
|
|
+ */
|
|
|
+ mlog(0, "extents get ready to be moved to #%llu block\n",
|
|
|
+ range->me_goal);
|
|
|
+
|
|
|
+out:
|
|
|
+ brelse(gd_bh);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|