diff mbox

[3/7] Btrfs: introduce a function to get extra mirror from replace

Message ID 1487381301-865-4-git-send-email-bo.li.liu@oracle.com (mailing list archive)
State New, archived
Headers show

Commit Message

Liu Bo Feb. 18, 2017, 1:28 a.m. UTC
As the part of getting extra mirror in __btrfs_map_block is
self-independent, this puts it into a separate function.

Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
 fs/btrfs/volumes.c | 161 +++++++++++++++++++++++++++++------------------------
 1 file changed, 89 insertions(+), 72 deletions(-)

Comments

Qu Wenruo Feb. 20, 2017, 6:26 a.m. UTC | #1
At 02/18/2017 09:28 AM, Liu Bo wrote:
> As the part of getting extra mirror in __btrfs_map_block is
> self-independent, this puts it into a separate function.
>
> Signed-off-by: Liu Bo <bo.li.liu@oracle.com>

Looks good to me.

Reviewed-by: Qu Wenruo <quwenruo@cn.fujitsu.com>

Thanks,
Qu
> ---
>  fs/btrfs/volumes.c | 161 +++++++++++++++++++++++++++++------------------------
>  1 file changed, 89 insertions(+), 72 deletions(-)
>
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 96228f3..f62efc7 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -140,6 +140,11 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info);
>  static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
>  static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
>  static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
> +static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
> +			     enum btrfs_map_op op,
> +			     u64 logical, u64 *length,
> +			     struct btrfs_bio **bbio_ret,
> +			     int mirror_num, int need_raid_map);
>
>  DEFINE_MUTEX(uuid_mutex);
>  static LIST_HEAD(fs_uuids);
> @@ -5463,6 +5468,83 @@ static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
>  	return ret;
>  }
>
> +/*
> + * In dev-replace case, for repair case (that's the only case where the mirror
> + * is selected explicitly when calling btrfs_map_block), blocks left of the
> + * left cursor can also be read from the target drive.
> + *
> + * For REQ_GET_READ_MIRRORS, the target drive is added as the last one to the
> + * array of stripes.
> + * For READ, it also needs to be supported using the same mirror number.
> + *
> + * If the requested block is not left of the left cursor, EIO is returned. This
> + * can happen because btrfs_num_copies() returns one more in the dev-replace
> + * case.
> + */
> +static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
> +					 u64 logical, u64 length,
> +					 u64 srcdev_devid, int *mirror_num,
> +					 u64 *physical)
> +{
> +	struct btrfs_bio *bbio = NULL;
> +	int num_stripes;
> +	int index_srcdev = 0;
> +	int found = 0;
> +	u64 physical_of_found = 0;
> +	int i;
> +	int ret = 0;
> +
> +	ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
> +				logical, &length, &bbio, 0, 0);
> +	if (ret) {
> +		ASSERT(bbio == NULL);
> +		return ret;
> +	}
> +
> +	num_stripes = bbio->num_stripes;
> +	if (*mirror_num > num_stripes) {
> +		/*
> +		 * BTRFS_MAP_GET_READ_MIRRORS does not contain this mirror,
> +		 * that means that the requested area is not left of the left
> +		 * cursor
> +		 */
> +		btrfs_put_bbio(bbio);
> +		return -EIO;
> +	}
> +
> +	/*
> +	 * process the rest of the function using the mirror_num of the source
> +	 * drive. Therefore look it up first.  At the end, patch the device
> +	 * pointer to the one of the target drive.
> +	 */
> +	for (i = 0; i < num_stripes; i++) {
> +		if (bbio->stripes[i].dev->devid != srcdev_devid)
> +			continue;
> +
> +		/*
> +		 * In case of DUP, in order to keep it simple, only add the
> +		 * mirror with the lowest physical address
> +		 */
> +		if (found &&
> +		    physical_of_found <= bbio->stripes[i].physical)
> +			continue;
> +
> +		index_srcdev = i;
> +		found = 1;
> +		physical_of_found = bbio->stripes[i].physical;
> +	}
> +
> +	btrfs_put_bbio(bbio);
> +
> +	ASSERT(found);
> +	if (!found)
> +		return -EIO;
> +
> +	*mirror_num = index_srcdev + 1;
> +	*physical = physical_of_found;
> +	return ret;
> +}
> +
>  static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
>  			     enum btrfs_map_op op,
>  			     u64 logical, u64 *length,
> @@ -5567,79 +5649,14 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
>  	if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 &&
>  	    op != BTRFS_MAP_WRITE && op != BTRFS_MAP_GET_READ_MIRRORS &&
>  	    dev_replace->tgtdev != NULL) {
> -		/*
> -		 * in dev-replace case, for repair case (that's the only
> -		 * case where the mirror is selected explicitly when
> -		 * calling btrfs_map_block), blocks left of the left cursor
> -		 * can also be read from the target drive.
> -		 * For REQ_GET_READ_MIRRORS, the target drive is added as
> -		 * the last one to the array of stripes. For READ, it also
> -		 * needs to be supported using the same mirror number.
> -		 * If the requested block is not left of the left cursor,
> -		 * EIO is returned. This can happen because btrfs_num_copies()
> -		 * returns one more in the dev-replace case.
> -		 */
> -		u64 tmp_length = *length;
> -		struct btrfs_bio *tmp_bbio = NULL;
> -		int tmp_num_stripes;
> -		u64 srcdev_devid = dev_replace->srcdev->devid;
> -		int index_srcdev = 0;
> -		int found = 0;
> -		u64 physical_of_found = 0;
> -
> -		ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
> -			     logical, &tmp_length, &tmp_bbio, 0, 0);
> -		if (ret) {
> -			WARN_ON(tmp_bbio != NULL);
> -			goto out;
> -		}
> -
> -		tmp_num_stripes = tmp_bbio->num_stripes;
> -		if (mirror_num > tmp_num_stripes) {
> -			/*
> -			 * BTRFS_MAP_GET_READ_MIRRORS does not contain this
> -			 * mirror, that means that the requested area
> -			 * is not left of the left cursor
> -			 */
> -			ret = -EIO;
> -			btrfs_put_bbio(tmp_bbio);
> -			goto out;
> -		}
> -
> -		/*
> -		 * process the rest of the function using the mirror_num
> -		 * of the source drive. Therefore look it up first.
> -		 * At the end, patch the device pointer to the one of the
> -		 * target drive.
> -		 */
> -		for (i = 0; i < tmp_num_stripes; i++) {
> -			if (tmp_bbio->stripes[i].dev->devid != srcdev_devid)
> -				continue;
> -
> -			/*
> -			 * In case of DUP, in order to keep it simple, only add
> -			 * the mirror with the lowest physical address
> -			 */
> -			if (found &&
> -			    physical_of_found <= tmp_bbio->stripes[i].physical)
> -				continue;
> -
> -			index_srcdev = i;
> -			found = 1;
> -			physical_of_found = tmp_bbio->stripes[i].physical;
> -		}
> -
> -		btrfs_put_bbio(tmp_bbio);
> -
> -		if (!found) {
> -			WARN_ON(1);
> -			ret = -EIO;
> +		ret = get_extra_mirror_from_replace(fs_info, logical, *length,
> +						    dev_replace->srcdev->devid,
> +						    &mirror_num,
> +					    &physical_to_patch_in_first_stripe);
> +		if (ret)
>  			goto out;
> -		}
> -
> -		mirror_num = index_srcdev + 1;
> -		patch_the_first_stripe_for_dev_replace = 1;
> -		physical_to_patch_in_first_stripe = physical_of_found;
> +		else
> +			patch_the_first_stripe_for_dev_replace = 1;
>  	} else if (mirror_num > map->num_stripes) {
>  		mirror_num = 0;
>  	}
>


--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 96228f3..f62efc7 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -140,6 +140,11 @@  static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info);
 static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
+static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+			     enum btrfs_map_op op,
+			     u64 logical, u64 *length,
+			     struct btrfs_bio **bbio_ret,
+			     int mirror_num, int need_raid_map);
 
 DEFINE_MUTEX(uuid_mutex);
 static LIST_HEAD(fs_uuids);
@@ -5463,6 +5468,83 @@  static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
 	return ret;
 }
 
+/*
+ * In dev-replace case, for repair case (that's the only case where the mirror
+ * is selected explicitly when calling btrfs_map_block), blocks left of the
+ * left cursor can also be read from the target drive.
+ *
+ * For REQ_GET_READ_MIRRORS, the target drive is added as the last one to the
+ * array of stripes.
+ * For READ, it also needs to be supported using the same mirror number.
+ *
+ * If the requested block is not left of the left cursor, EIO is returned. This
+ * can happen because btrfs_num_copies() returns one more in the dev-replace
+ * case.
+ */
+static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+					 u64 logical, u64 length,
+					 u64 srcdev_devid, int *mirror_num,
+					 u64 *physical)
+{
+	struct btrfs_bio *bbio = NULL;
+	int num_stripes;
+	int index_srcdev = 0;
+	int found = 0;
+	u64 physical_of_found = 0;
+	int i;
+	int ret = 0;
+
+	ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
+				logical, &length, &bbio, 0, 0);
+	if (ret) {
+		ASSERT(bbio == NULL);
+		return ret;
+	}
+
+	num_stripes = bbio->num_stripes;
+	if (*mirror_num > num_stripes) {
+		/*
+		 * BTRFS_MAP_GET_READ_MIRRORS does not contain this mirror,
+		 * that means that the requested area is not left of the left
+		 * cursor
+		 */
+		btrfs_put_bbio(bbio);
+		return -EIO;
+	}
+
+	/*
+	 * process the rest of the function using the mirror_num of the source
+	 * drive. Therefore look it up first.  At the end, patch the device
+	 * pointer to the one of the target drive.
+	 */
+	for (i = 0; i < num_stripes; i++) {
+		if (bbio->stripes[i].dev->devid != srcdev_devid)
+			continue;
+
+		/*
+		 * In case of DUP, in order to keep it simple, only add the
+		 * mirror with the lowest physical address
+		 */
+		if (found &&
+		    physical_of_found <= bbio->stripes[i].physical)
+			continue;
+
+		index_srcdev = i;
+		found = 1;
+		physical_of_found = bbio->stripes[i].physical;
+	}
+
+	btrfs_put_bbio(bbio);
+
+	ASSERT(found);
+	if (!found)
+		return -EIO;
+
+	*mirror_num = index_srcdev + 1;
+	*physical = physical_of_found;
+	return ret;
+}
+
 static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
 			     enum btrfs_map_op op,
 			     u64 logical, u64 *length,
@@ -5567,79 +5649,14 @@  static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
 	if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 &&
 	    op != BTRFS_MAP_WRITE && op != BTRFS_MAP_GET_READ_MIRRORS &&
 	    dev_replace->tgtdev != NULL) {
-		/*
-		 * in dev-replace case, for repair case (that's the only
-		 * case where the mirror is selected explicitly when
-		 * calling btrfs_map_block), blocks left of the left cursor
-		 * can also be read from the target drive.
-		 * For REQ_GET_READ_MIRRORS, the target drive is added as
-		 * the last one to the array of stripes. For READ, it also
-		 * needs to be supported using the same mirror number.
-		 * If the requested block is not left of the left cursor,
-		 * EIO is returned. This can happen because btrfs_num_copies()
-		 * returns one more in the dev-replace case.
-		 */
-		u64 tmp_length = *length;
-		struct btrfs_bio *tmp_bbio = NULL;
-		int tmp_num_stripes;
-		u64 srcdev_devid = dev_replace->srcdev->devid;
-		int index_srcdev = 0;
-		int found = 0;
-		u64 physical_of_found = 0;
-
-		ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
-			     logical, &tmp_length, &tmp_bbio, 0, 0);
-		if (ret) {
-			WARN_ON(tmp_bbio != NULL);
-			goto out;
-		}
-
-		tmp_num_stripes = tmp_bbio->num_stripes;
-		if (mirror_num > tmp_num_stripes) {
-			/*
-			 * BTRFS_MAP_GET_READ_MIRRORS does not contain this
-			 * mirror, that means that the requested area
-			 * is not left of the left cursor
-			 */
-			ret = -EIO;
-			btrfs_put_bbio(tmp_bbio);
-			goto out;
-		}
-
-		/*
-		 * process the rest of the function using the mirror_num
-		 * of the source drive. Therefore look it up first.
-		 * At the end, patch the device pointer to the one of the
-		 * target drive.
-		 */
-		for (i = 0; i < tmp_num_stripes; i++) {
-			if (tmp_bbio->stripes[i].dev->devid != srcdev_devid)
-				continue;
-
-			/*
-			 * In case of DUP, in order to keep it simple, only add
-			 * the mirror with the lowest physical address
-			 */
-			if (found &&
-			    physical_of_found <= tmp_bbio->stripes[i].physical)
-				continue;
-
-			index_srcdev = i;
-			found = 1;
-			physical_of_found = tmp_bbio->stripes[i].physical;
-		}
-
-		btrfs_put_bbio(tmp_bbio);
-
-		if (!found) {
-			WARN_ON(1);
-			ret = -EIO;
+		ret = get_extra_mirror_from_replace(fs_info, logical, *length,
+						    dev_replace->srcdev->devid,
+						    &mirror_num,
+					    &physical_to_patch_in_first_stripe);
+		if (ret)
 			goto out;
-		}
-
-		mirror_num = index_srcdev + 1;
-		patch_the_first_stripe_for_dev_replace = 1;
-		physical_to_patch_in_first_stripe = physical_of_found;
+		else
+			patch_the_first_stripe_for_dev_replace = 1;
 	} else if (mirror_num > map->num_stripes) {
 		mirror_num = 0;
 	}