diff mbox

[v3,16/22] btrfs-progs: convert: Introduce function to migrate reserved ranges

Message ID 1454043812-7893-17-git-send-email-quwenruo@cn.fujitsu.com (mailing list archive)
State Accepted
Headers show

Commit Message

Qu Wenruo Jan. 29, 2016, 5:03 a.m. UTC
Introduce new function, migrate_reserved_ranges() to migrate used fs
data in btrfs reserved space.

Unlike old implement, which will need to relocate all the complicated
csum and reference relocation, previous patches already ensure such
reserved ranges won't be allocated.
So here we only need copy these data out and create new
extent/csum/reference.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
---
 btrfs-convert.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 2 deletions(-)

Comments

Liu Bo May 28, 2016, 3:16 a.m. UTC | #1
On Fri, Jan 29, 2016 at 01:03:26PM +0800, Qu Wenruo wrote:
> Introduce new function, migrate_reserved_ranges() to migrate used fs
> data in btrfs reserved space.
> 
> Unlike old implement, which will need to relocate all the complicated
> csum and reference relocation, previous patches already ensure such
> reserved ranges won't be allocated.
> So here we only need copy these data out and create new
> extent/csum/reference.
> 
> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
> Signed-off-by: David Sterba <dsterba@suse.com>
> ---
>  btrfs-convert.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 122 insertions(+), 2 deletions(-)
> 
> diff --git a/btrfs-convert.c b/btrfs-convert.c
> index 16e2309..f6126db 100644
> --- a/btrfs-convert.c
> +++ b/btrfs-convert.c
> @@ -1679,6 +1679,123 @@ static int create_image_file_range_v2(struct btrfs_trans_handle *trans,
>  	return ret;
>  }
>  
> +
> +/*
> + * Relocate old fs data in one reserved ranges
> + *
> + * Since all old fs data in reserved range is not covered by any chunk nor
> + * data extent, we don't need to handle any reference but add new
> + * extent/reference, which makes codes more clear
> + */
> +static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
> +				      struct btrfs_root *root,
> +				      struct cache_tree *used,
> +				      struct btrfs_inode_item *inode, int fd,
> +				      u64 ino, u64 start, u64 len, int datacsum)
> +{
> +	u64 cur_off = start;
> +	u64 cur_len = len;
> +	struct cache_extent *cache;
> +	struct btrfs_key key;
> +	struct extent_buffer *eb;
> +	int ret = 0;
> +
> +	while (cur_off < start + len) {
> +		cache = lookup_cache_extent(used, cur_off, cur_len);
> +		if (!cache)
> +			break;
> +		cur_off = max(cache->start, cur_off);
> +		cur_len = min(cache->start + cache->size, start + len) -
> +			  cur_off;
> +		BUG_ON(cur_len < root->sectorsize);
> +
> +		/* reserve extent for the data */
> +		ret = btrfs_reserve_extent(trans, root, cur_len, 0, 0, (u64)-1,
> +					   &key, 1);
> +		if (ret < 0)
> +			break;
> +
> +		eb = malloc(sizeof(*eb) + cur_len);
> +		if (!eb) {
> +			ret = -ENOMEM;
> +			break;
> +		}
> +
> +		ret = pread(fd, eb->data, cur_len, cur_off);
> +		if (ret < cur_len) {
> +			ret = (ret < 0 ? ret : -EIO);
> +			free(eb);
> +			break;
> +		}
> +		eb->start = key.objectid;
> +		eb->len = key.offset;
> +
> +		/* Write the data */
> +		ret = write_and_map_eb(trans, root, eb);
> +		free(eb);
> +		if (ret < 0)
> +			break;

With write_data_to_disk(), we don't have to create eb for write.

Thanks,

-liubo
> +
> +		/* Now handle extent item and file extent things */
> +		ret = btrfs_record_file_extent(trans, root, ino, inode, cur_off,
> +					       key.objectid, key.offset);
> +		if (ret < 0)
> +			break;
> +		/* Finally, insert csum items */
> +		if (datacsum)
> +			ret = csum_disk_extent(trans, root, key.objectid,
> +					       key.offset);
> +
> +		cur_off += key.offset;
> +		cur_len = start + len - cur_off;
> +	}
> +	return ret;
> +}
> +
> +/*
> + * Relocate the used ext2 data in reserved ranges
> + * [0,1M)
> + * [btrfs_sb_offset(1), +BTRFS_STRIPE_LEN)
> + * [btrfs_sb_offset(2), +BTRFS_STRIPE_LEN)
> + */
> +static int migrate_reserved_ranges(struct btrfs_trans_handle *trans,
> +				   struct btrfs_root *root,
> +				   struct cache_tree *used,
> +				   struct btrfs_inode_item *inode, int fd,
> +				   u64 ino, u64 total_bytes, int datacsum)
> +{
> +	u64 cur_off;
> +	u64 cur_len;
> +	int ret = 0;
> +
> +	/* 0 ~ 1M */
> +	cur_off = 0;
> +	cur_len = 1024 * 1024;
> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
> +					 cur_off, cur_len, datacsum);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* second sb(fisrt sb is included in 0~1M) */
> +	cur_off = btrfs_sb_offset(1);
> +	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
> +	if (cur_off < total_bytes)
> +		return ret;
> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
> +					 cur_off, cur_len, datacsum);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Last sb */
> +	cur_off = btrfs_sb_offset(2);
> +	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
> +	if (cur_off < total_bytes)
> +		return ret;
> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
> +					 cur_off, cur_len, datacsum);
> +	return ret;
> +}
> +
>  static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
>  				int ensure_size);
>  
> @@ -1687,11 +1804,10 @@ static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
>   *
>   * This is completely fs independent as we have cctx->used, only
>   * need to create file extents point to all the posistions.
> - * TODO: Add handler for reserved ranges in next patch
>   */
>  static int create_image_v2(struct btrfs_root *root,
>  			   struct btrfs_mkfs_config *cfg,
> -			   struct btrfs_convert_context *cctx,
> +			   struct btrfs_convert_context *cctx, int fd,
>  			   u64 size, char *name, int datacsum)
>  {
>  	struct btrfs_inode_item buf;
> @@ -1769,6 +1885,10 @@ static int create_image_v2(struct btrfs_root *root,
>  			goto out;
>  		cur += len;
>  	}
> +	/* Handle the reserved ranges */
> +	ret = migrate_reserved_ranges(trans, root, &cctx->used, &buf, fd, ino,
> +				      cfg->num_bytes, datacsum);
> +
>  
>  	key.objectid = ino;
>  	key.type = BTRFS_INODE_ITEM_KEY;
> -- 
> 2.7.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
--
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
Qu Wenruo May 29, 2016, 11:07 a.m. UTC | #2
On 05/28/2016 11:16 AM, Liu Bo wrote:
> On Fri, Jan 29, 2016 at 01:03:26PM +0800, Qu Wenruo wrote:
>> Introduce new function, migrate_reserved_ranges() to migrate used fs
>> data in btrfs reserved space.
>>
>> Unlike old implement, which will need to relocate all the complicated
>> csum and reference relocation, previous patches already ensure such
>> reserved ranges won't be allocated.
>> So here we only need copy these data out and create new
>> extent/csum/reference.
>>
>> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
>> Signed-off-by: David Sterba <dsterba@suse.com>
>> ---
>>  btrfs-convert.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 122 insertions(+), 2 deletions(-)
>>
>> diff --git a/btrfs-convert.c b/btrfs-convert.c
>> index 16e2309..f6126db 100644
>> --- a/btrfs-convert.c
>> +++ b/btrfs-convert.c
>> @@ -1679,6 +1679,123 @@ static int create_image_file_range_v2(struct btrfs_trans_handle *trans,
>>  	return ret;
>>  }
>>
>> +
>> +/*
>> + * Relocate old fs data in one reserved ranges
>> + *
>> + * Since all old fs data in reserved range is not covered by any chunk nor
>> + * data extent, we don't need to handle any reference but add new
>> + * extent/reference, which makes codes more clear
>> + */
>> +static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
>> +				      struct btrfs_root *root,
>> +				      struct cache_tree *used,
>> +				      struct btrfs_inode_item *inode, int fd,
>> +				      u64 ino, u64 start, u64 len, int datacsum)
>> +{
>> +	u64 cur_off = start;
>> +	u64 cur_len = len;
>> +	struct cache_extent *cache;
>> +	struct btrfs_key key;
>> +	struct extent_buffer *eb;
>> +	int ret = 0;
>> +
>> +	while (cur_off < start + len) {
>> +		cache = lookup_cache_extent(used, cur_off, cur_len);
>> +		if (!cache)
>> +			break;
>> +		cur_off = max(cache->start, cur_off);
>> +		cur_len = min(cache->start + cache->size, start + len) -
>> +			  cur_off;
>> +		BUG_ON(cur_len < root->sectorsize);
>> +
>> +		/* reserve extent for the data */
>> +		ret = btrfs_reserve_extent(trans, root, cur_len, 0, 0, (u64)-1,
>> +					   &key, 1);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		eb = malloc(sizeof(*eb) + cur_len);
>> +		if (!eb) {
>> +			ret = -ENOMEM;
>> +			break;
>> +		}
>> +
>> +		ret = pread(fd, eb->data, cur_len, cur_off);
>> +		if (ret < cur_len) {
>> +			ret = (ret < 0 ? ret : -EIO);
>> +			free(eb);
>> +			break;
>> +		}
>> +		eb->start = key.objectid;
>> +		eb->len = key.offset;
>> +
>> +		/* Write the data */
>> +		ret = write_and_map_eb(trans, root, eb);
>> +		free(eb);
>> +		if (ret < 0)
>> +			break;
>
> With write_data_to_disk(), we don't have to create eb for write.
>
> Thanks,
>
> -liubo

Nice advice.

I didn't remember whether write_data_to_disk() was there when the 
patchset was written, but always a good idea to get rid of the temporary eb.

Thanks,
Qu

>> +
>> +		/* Now handle extent item and file extent things */
>> +		ret = btrfs_record_file_extent(trans, root, ino, inode, cur_off,
>> +					       key.objectid, key.offset);
>> +		if (ret < 0)
>> +			break;
>> +		/* Finally, insert csum items */
>> +		if (datacsum)
>> +			ret = csum_disk_extent(trans, root, key.objectid,
>> +					       key.offset);
>> +
>> +		cur_off += key.offset;
>> +		cur_len = start + len - cur_off;
>> +	}
>> +	return ret;
>> +}
>> +
>> +/*
>> + * Relocate the used ext2 data in reserved ranges
>> + * [0,1M)
>> + * [btrfs_sb_offset(1), +BTRFS_STRIPE_LEN)
>> + * [btrfs_sb_offset(2), +BTRFS_STRIPE_LEN)
>> + */
>> +static int migrate_reserved_ranges(struct btrfs_trans_handle *trans,
>> +				   struct btrfs_root *root,
>> +				   struct cache_tree *used,
>> +				   struct btrfs_inode_item *inode, int fd,
>> +				   u64 ino, u64 total_bytes, int datacsum)
>> +{
>> +	u64 cur_off;
>> +	u64 cur_len;
>> +	int ret = 0;
>> +
>> +	/* 0 ~ 1M */
>> +	cur_off = 0;
>> +	cur_len = 1024 * 1024;
>> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
>> +					 cur_off, cur_len, datacsum);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* second sb(fisrt sb is included in 0~1M) */
>> +	cur_off = btrfs_sb_offset(1);
>> +	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
>> +	if (cur_off < total_bytes)
>> +		return ret;
>> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
>> +					 cur_off, cur_len, datacsum);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* Last sb */
>> +	cur_off = btrfs_sb_offset(2);
>> +	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
>> +	if (cur_off < total_bytes)
>> +		return ret;
>> +	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
>> +					 cur_off, cur_len, datacsum);
>> +	return ret;
>> +}
>> +
>>  static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
>>  				int ensure_size);
>>
>> @@ -1687,11 +1804,10 @@ static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
>>   *
>>   * This is completely fs independent as we have cctx->used, only
>>   * need to create file extents point to all the posistions.
>> - * TODO: Add handler for reserved ranges in next patch
>>   */
>>  static int create_image_v2(struct btrfs_root *root,
>>  			   struct btrfs_mkfs_config *cfg,
>> -			   struct btrfs_convert_context *cctx,
>> +			   struct btrfs_convert_context *cctx, int fd,
>>  			   u64 size, char *name, int datacsum)
>>  {
>>  	struct btrfs_inode_item buf;
>> @@ -1769,6 +1885,10 @@ static int create_image_v2(struct btrfs_root *root,
>>  			goto out;
>>  		cur += len;
>>  	}
>> +	/* Handle the reserved ranges */
>> +	ret = migrate_reserved_ranges(trans, root, &cctx->used, &buf, fd, ino,
>> +				      cfg->num_bytes, datacsum);
>> +
>>
>>  	key.objectid = ino;
>>  	key.type = BTRFS_INODE_ITEM_KEY;
>> --
>> 2.7.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
> --
> 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
>
--
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/btrfs-convert.c b/btrfs-convert.c
index 16e2309..f6126db 100644
--- a/btrfs-convert.c
+++ b/btrfs-convert.c
@@ -1679,6 +1679,123 @@  static int create_image_file_range_v2(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
+
+/*
+ * Relocate old fs data in one reserved ranges
+ *
+ * Since all old fs data in reserved range is not covered by any chunk nor
+ * data extent, we don't need to handle any reference but add new
+ * extent/reference, which makes codes more clear
+ */
+static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
+				      struct btrfs_root *root,
+				      struct cache_tree *used,
+				      struct btrfs_inode_item *inode, int fd,
+				      u64 ino, u64 start, u64 len, int datacsum)
+{
+	u64 cur_off = start;
+	u64 cur_len = len;
+	struct cache_extent *cache;
+	struct btrfs_key key;
+	struct extent_buffer *eb;
+	int ret = 0;
+
+	while (cur_off < start + len) {
+		cache = lookup_cache_extent(used, cur_off, cur_len);
+		if (!cache)
+			break;
+		cur_off = max(cache->start, cur_off);
+		cur_len = min(cache->start + cache->size, start + len) -
+			  cur_off;
+		BUG_ON(cur_len < root->sectorsize);
+
+		/* reserve extent for the data */
+		ret = btrfs_reserve_extent(trans, root, cur_len, 0, 0, (u64)-1,
+					   &key, 1);
+		if (ret < 0)
+			break;
+
+		eb = malloc(sizeof(*eb) + cur_len);
+		if (!eb) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		ret = pread(fd, eb->data, cur_len, cur_off);
+		if (ret < cur_len) {
+			ret = (ret < 0 ? ret : -EIO);
+			free(eb);
+			break;
+		}
+		eb->start = key.objectid;
+		eb->len = key.offset;
+
+		/* Write the data */
+		ret = write_and_map_eb(trans, root, eb);
+		free(eb);
+		if (ret < 0)
+			break;
+
+		/* Now handle extent item and file extent things */
+		ret = btrfs_record_file_extent(trans, root, ino, inode, cur_off,
+					       key.objectid, key.offset);
+		if (ret < 0)
+			break;
+		/* Finally, insert csum items */
+		if (datacsum)
+			ret = csum_disk_extent(trans, root, key.objectid,
+					       key.offset);
+
+		cur_off += key.offset;
+		cur_len = start + len - cur_off;
+	}
+	return ret;
+}
+
+/*
+ * Relocate the used ext2 data in reserved ranges
+ * [0,1M)
+ * [btrfs_sb_offset(1), +BTRFS_STRIPE_LEN)
+ * [btrfs_sb_offset(2), +BTRFS_STRIPE_LEN)
+ */
+static int migrate_reserved_ranges(struct btrfs_trans_handle *trans,
+				   struct btrfs_root *root,
+				   struct cache_tree *used,
+				   struct btrfs_inode_item *inode, int fd,
+				   u64 ino, u64 total_bytes, int datacsum)
+{
+	u64 cur_off;
+	u64 cur_len;
+	int ret = 0;
+
+	/* 0 ~ 1M */
+	cur_off = 0;
+	cur_len = 1024 * 1024;
+	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
+					 cur_off, cur_len, datacsum);
+	if (ret < 0)
+		return ret;
+
+	/* second sb(fisrt sb is included in 0~1M) */
+	cur_off = btrfs_sb_offset(1);
+	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
+	if (cur_off < total_bytes)
+		return ret;
+	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
+					 cur_off, cur_len, datacsum);
+	if (ret < 0)
+		return ret;
+
+	/* Last sb */
+	cur_off = btrfs_sb_offset(2);
+	cur_len = min(total_bytes, cur_off + BTRFS_STRIPE_LEN) - cur_off;
+	if (cur_off < total_bytes)
+		return ret;
+	ret = migrate_one_reserved_range(trans, root, used, inode, fd, ino,
+					 cur_off, cur_len, datacsum);
+	return ret;
+}
+
 static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
 				int ensure_size);
 
@@ -1687,11 +1804,10 @@  static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
  *
  * This is completely fs independent as we have cctx->used, only
  * need to create file extents point to all the posistions.
- * TODO: Add handler for reserved ranges in next patch
  */
 static int create_image_v2(struct btrfs_root *root,
 			   struct btrfs_mkfs_config *cfg,
-			   struct btrfs_convert_context *cctx,
+			   struct btrfs_convert_context *cctx, int fd,
 			   u64 size, char *name, int datacsum)
 {
 	struct btrfs_inode_item buf;
@@ -1769,6 +1885,10 @@  static int create_image_v2(struct btrfs_root *root,
 			goto out;
 		cur += len;
 	}
+	/* Handle the reserved ranges */
+	ret = migrate_reserved_ranges(trans, root, &cctx->used, &buf, fd, ino,
+				      cfg->num_bytes, datacsum);
+
 
 	key.objectid = ino;
 	key.type = BTRFS_INODE_ITEM_KEY;