linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Konstantinos Skarlatos <k.skarlatos@gmail.com>
To: Filipe David Borba Manana <fdmanana@gmail.com>,
	linux-btrfs@vger.kernel.org
Subject: Re: [RFC PATCH] Btrfs: send, add calculate data size flag to allow for progress estimation
Date: Fri, 04 Apr 2014 17:52:50 +0300	[thread overview]
Message-ID: <533EC742.5050505@gmail.com> (raw)
In-Reply-To: <1396624841-1363-1-git-send-email-fdmanana@gmail.com>

On 4/4/2014 6:20 μμ, Filipe David Borba Manana wrote:
> This new send flag makes send calculate first the amount of new file data (in bytes)
> the send root has relatively to the parent root, or for the case of a non-incremental
> send, the total amount of file data we will send through the send stream. In other words,
> it computes the sum of the lengths of all write and clone operations that will be sent
> through the send stream.
>
> This data size value is sent in a new command, named BTRFS_SEND_C_TOTAL_DATA_SIZE, that
> immediately follows a BTRFS_SEND_C_SUBVOL or BTRFS_SEND_C_SNAPSHOT command, and precedes
> any command that changes a file or the filesystem hierarchy. Upon receiving a write or
> clone command, the receiving end can increment a counter by the data length of that
> command and therefore report progress by comparing the counter's value with the data size
> value received in the BTRFS_SEND_C_TOTAL_DATA_SIZE command.
>
> The approach is simple, before the normal operation of send, do a scan in the file system
> tree for new inodes and file extent items, just like in send's normal operation, and keep
> incrementing a counter with new inodes' size and the size of file extents that are going
> to be written or cloned. This is actually a simpler and more lightweight tree scan/processing
> than the one we do when sending the changes, as it doesn't process inode references nor does
> any lookups in the extent tree for example.
>
> After modifying btrfs-progs to understand this new command and report progress, here's an
> example (the -o flag tells btrfs send to pass the new flag to the kernel's send ioctl):
>
>      $ btrfs send -o /mnt/sdd/base | btrfs receive /mnt/sdc
>      At subvol /mnt/sdd/base
>      At subvol base
>      About to receive 9211507211 bytes
>      Subvolume/snapshot /mnt/sdc//base, progress  24.73%, 2278015008 bytes received (9211507211 total bytes)
>
>      $ btrfs send -o -p /mnt/sdd/base /mnt/sdd/incr | btrfs receive /mnt/sdc
>      At subvol /mnt/sdd/incr
>      At snapshot incr
>      About to receive 9211747739 bytes
>      Subvolume/snapshot /mnt/sdc//incr, progress  63.42%, 5843024211 bytes received (9211747739 total bytes)
Hi, as a user of send i can say that this feature is very useful. Is it 
possible to add current speed indication (MB/sec)?

>
> Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
> ---
>   fs/btrfs/send.c            | 194 +++++++++++++++++++++++++++++++++++++--------
>   fs/btrfs/send.h            |   1 +
>   include/uapi/linux/btrfs.h |  13 ++-
>   3 files changed, 175 insertions(+), 33 deletions(-)
>
> diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
> index c81e0d9..fa378c7 100644
> --- a/fs/btrfs/send.c
> +++ b/fs/btrfs/send.c
> @@ -81,7 +81,13 @@ struct clone_root {
>   #define SEND_CTX_MAX_NAME_CACHE_SIZE 128
>   #define SEND_CTX_NAME_CACHE_CLEAN_SIZE (SEND_CTX_MAX_NAME_CACHE_SIZE * 2)
>   
> +enum btrfs_send_phase {
> +	SEND_PHASE_STREAM_CHANGES,
> +	SEND_PHASE_COMPUTE_DATA_SIZE,
> +};
> +
>   struct send_ctx {
> +	enum btrfs_send_phase phase;
>   	struct file *send_filp;
>   	loff_t send_off;
>   	char *send_buf;
> @@ -116,6 +122,7 @@ struct send_ctx {
>   	u64 cur_inode_last_extent;
>   
>   	u64 send_progress;
> +	u64 total_data_size;
>   
>   	struct list_head new_refs;
>   	struct list_head deleted_refs;
> @@ -687,6 +694,8 @@ static int send_rename(struct send_ctx *sctx,
>   {
>   	int ret;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_rename %s -> %s\n", from->start, to->start);
>   
>   	ret = begin_cmd(sctx, BTRFS_SEND_C_RENAME);
> @@ -711,6 +720,8 @@ static int send_link(struct send_ctx *sctx,
>   {
>   	int ret;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_link %s -> %s\n", path->start, lnk->start);
>   
>   	ret = begin_cmd(sctx, BTRFS_SEND_C_LINK);
> @@ -734,6 +745,8 @@ static int send_unlink(struct send_ctx *sctx, struct fs_path *path)
>   {
>   	int ret;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_unlink %s\n", path->start);
>   
>   	ret = begin_cmd(sctx, BTRFS_SEND_C_UNLINK);
> @@ -756,6 +769,8 @@ static int send_rmdir(struct send_ctx *sctx, struct fs_path *path)
>   {
>   	int ret;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_rmdir %s\n", path->start);
>   
>   	ret = begin_cmd(sctx, BTRFS_SEND_C_RMDIR);
> @@ -2286,6 +2301,9 @@ static int send_truncate(struct send_ctx *sctx, u64 ino, u64 gen, u64 size)
>   	int ret = 0;
>   	struct fs_path *p;
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +		return 0;
> +
>   verbose_printk("btrfs: send_truncate %llu size=%llu\n", ino, size);
>   
>   	p = fs_path_alloc();
> @@ -2315,6 +2333,8 @@ static int send_chmod(struct send_ctx *sctx, u64 ino, u64 gen, u64 mode)
>   	int ret = 0;
>   	struct fs_path *p;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_chmod %llu mode=%llu\n", ino, mode);
>   
>   	p = fs_path_alloc();
> @@ -2344,6 +2364,8 @@ static int send_chown(struct send_ctx *sctx, u64 ino, u64 gen, u64 uid, u64 gid)
>   	int ret = 0;
>   	struct fs_path *p;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_chown %llu uid=%llu, gid=%llu\n", ino, uid, gid);
>   
>   	p = fs_path_alloc();
> @@ -2379,6 +2401,8 @@ static int send_utimes(struct send_ctx *sctx, u64 ino, u64 gen)
>   	struct btrfs_key key;
>   	int slot;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_utimes %llu\n", ino);
>   
>   	p = fs_path_alloc();
> @@ -2441,6 +2465,8 @@ static int send_create_inode(struct send_ctx *sctx, u64 ino)
>   	u64 mode;
>   	u64 rdev;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_create_inode %llu\n", ino);
>   
>   	p = fs_path_alloc();
> @@ -2588,6 +2614,8 @@ static int send_create_inode_if_needed(struct send_ctx *sctx)
>   {
>   	int ret;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	if (S_ISDIR(sctx->cur_inode_mode)) {
>   		ret = did_create_dir(sctx, sctx->cur_ino);
>   		if (ret < 0)
> @@ -2693,6 +2721,8 @@ static int orphanize_inode(struct send_ctx *sctx, u64 ino, u64 gen,
>   	int ret;
>   	struct fs_path *orphan;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	orphan = fs_path_alloc();
>   	if (!orphan)
>   		return -ENOMEM;
> @@ -3061,6 +3091,8 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm)
>   	int ret;
>   	u64 ancestor = 0;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	name = fs_path_alloc();
>   	from_path = fs_path_alloc();
>   	if (!name || !from_path) {
> @@ -3315,6 +3347,9 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move)
>   	int is_orphan = 0;
>   	u64 last_dir_ino_rm = 0;
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +		return 0;
> +
>   verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
>   
>   	/*
> @@ -3823,6 +3858,8 @@ static int process_all_refs(struct send_ctx *sctx,
>   	iterate_inode_ref_t cb;
>   	int pending_move = 0;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	path = alloc_path_for_send();
>   	if (!path)
>   		return -ENOMEM;
> @@ -4142,6 +4179,8 @@ static int process_all_new_xattrs(struct send_ctx *sctx)
>   	struct extent_buffer *eb;
>   	int slot;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	path = alloc_path_for_send();
>   	if (!path)
>   		return -ENOMEM;
> @@ -4272,6 +4311,8 @@ static int send_write(struct send_ctx *sctx, u64 offset, u32 len)
>   	struct fs_path *p;
>   	ssize_t num_read = 0;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	p = fs_path_alloc();
>   	if (!p)
>   		return -ENOMEM;
> @@ -4307,6 +4348,22 @@ out:
>   	return num_read;
>   }
>   
> +static int send_total_data_size(struct send_ctx *sctx, u64 data_size)
> +{
> +	int ret;
> +
> +	ret = begin_cmd(sctx, BTRFS_SEND_C_TOTAL_DATA_SIZE);
> +	if (ret < 0)
> +		goto out;
> +
> +	TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, data_size);
> +	ret = send_cmd(sctx);
> +
> +tlv_put_failure:
> +out:
> +	return ret;
> +}
> +
>   /*
>    * Send a clone command to user space.
>    */
> @@ -4318,6 +4375,8 @@ static int send_clone(struct send_ctx *sctx,
>   	struct fs_path *p;
>   	u64 gen;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   verbose_printk("btrfs: send_clone offset=%llu, len=%d, clone_root=%llu, "
>   	       "clone_inode=%llu, clone_offset=%llu\n", offset, len,
>   		clone_root->root->objectid, clone_root->ino,
> @@ -4376,6 +4435,8 @@ static int send_update_extent(struct send_ctx *sctx,
>   	int ret = 0;
>   	struct fs_path *p;
>   
> +	ASSERT(sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE);
> +
>   	p = fs_path_alloc();
>   	if (!p)
>   		return -ENOMEM;
> @@ -4407,6 +4468,11 @@ static int send_hole(struct send_ctx *sctx, u64 end)
>   	u64 len;
>   	int ret = 0;
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE) {
> +		sctx->total_data_size += end - offset;
> +		return 0;
> +	}
> +
>   	p = fs_path_alloc();
>   	if (!p)
>   		return -ENOMEM;
> @@ -4470,6 +4536,12 @@ static int send_write_or_clone(struct send_ctx *sctx,
>   		goto out;
>   	}
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE) {
> +		if (offset < sctx->cur_inode_size)
> +			sctx->total_data_size += len;
> +		goto out;
> +	}
> +
>   	if (clone_root && IS_ALIGNED(offset + len, bs)) {
>   		ret = send_clone(sctx, offset, len, clone_root);
>   	} else if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) {
> @@ -4803,10 +4875,12 @@ static int process_extent(struct send_ctx *sctx,
>   		}
>   	}
>   
> -	ret = find_extent_clone(sctx, path, key->objectid, key->offset,
> -			sctx->cur_inode_size, &found_clone);
> -	if (ret != -ENOENT && ret < 0)
> -		goto out;
> +	if (sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE) {
> +		ret = find_extent_clone(sctx, path, key->objectid, key->offset,
> +					sctx->cur_inode_size, &found_clone);
> +		if (ret != -ENOENT && ret < 0)
> +			goto out;
> +	}
>   
>   	ret = send_write_or_clone(sctx, path, key, found_clone);
>   	if (ret)
> @@ -4936,6 +5010,9 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
>   	if (!at_end && sctx->cmp_key->objectid == sctx->cur_ino)
>   		goto out;
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +		goto truncate_inode;
> +
>   	ret = get_inode_info(sctx->send_root, sctx->cur_ino, NULL, NULL,
>   			&left_mode, &left_uid, &left_gid, NULL);
>   	if (ret < 0)
> @@ -4958,6 +5035,7 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
>   			need_chmod = 1;
>   	}
>   
> +truncate_inode:
>   	if (S_ISREG(sctx->cur_inode_mode)) {
>   		if (need_send_hole(sctx)) {
>   			if (sctx->cur_inode_last_extent == (u64)-1 ||
> @@ -4997,7 +5075,8 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
>   	 * If other directory inodes depended on our current directory
>   	 * inode's move/rename, now do their move/rename operations.
>   	 */
> -	if (!is_waiting_for_move(sctx, sctx->cur_ino)) {
> +	if (sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE &&
> +	    !is_waiting_for_move(sctx, sctx->cur_ino)) {
>   		ret = apply_children_dir_moves(sctx);
>   		if (ret)
>   			goto out;
> @@ -5081,7 +5160,8 @@ static int changed_inode(struct send_ctx *sctx,
>   				sctx->left_path->nodes[0], left_ii);
>   		sctx->cur_inode_rdev = btrfs_inode_rdev(
>   				sctx->left_path->nodes[0], left_ii);
> -		if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID)
> +		if (sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID &&
> +		    sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE)
>   			ret = send_create_inode_if_needed(sctx);
>   	} else if (result == BTRFS_COMPARE_TREE_DELETED) {
>   		sctx->cur_inode_gen = right_gen;
> @@ -5103,17 +5183,19 @@ static int changed_inode(struct send_ctx *sctx,
>   			/*
>   			 * First, process the inode as if it was deleted.
>   			 */
> -			sctx->cur_inode_gen = right_gen;
> -			sctx->cur_inode_new = 0;
> -			sctx->cur_inode_deleted = 1;
> -			sctx->cur_inode_size = btrfs_inode_size(
> +			if (sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE) {
> +				sctx->cur_inode_gen = right_gen;
> +				sctx->cur_inode_new = 0;
> +				sctx->cur_inode_deleted = 1;
> +				sctx->cur_inode_size = btrfs_inode_size(
>   					sctx->right_path->nodes[0], right_ii);
> -			sctx->cur_inode_mode = btrfs_inode_mode(
> +				sctx->cur_inode_mode = btrfs_inode_mode(
>   					sctx->right_path->nodes[0], right_ii);
> -			ret = process_all_refs(sctx,
> -					BTRFS_COMPARE_TREE_DELETED);
> -			if (ret < 0)
> -				goto out;
> +				ret = process_all_refs(sctx,
> +						   BTRFS_COMPARE_TREE_DELETED);
> +				if (ret < 0)
> +					goto out;
> +			}
>   
>   			/*
>   			 * Now process the inode as if it was new.
> @@ -5127,29 +5209,38 @@ static int changed_inode(struct send_ctx *sctx,
>   					sctx->left_path->nodes[0], left_ii);
>   			sctx->cur_inode_rdev = btrfs_inode_rdev(
>   					sctx->left_path->nodes[0], left_ii);
> -			ret = send_create_inode_if_needed(sctx);
> -			if (ret < 0)
> -				goto out;
> -
> -			ret = process_all_refs(sctx, BTRFS_COMPARE_TREE_NEW);
> -			if (ret < 0)
> -				goto out;
> +			if (sctx->phase != SEND_PHASE_COMPUTE_DATA_SIZE) {
> +				ret = send_create_inode_if_needed(sctx);
> +				if (ret < 0)
> +					goto out;
> +				ret = process_all_refs(sctx,
> +						       BTRFS_COMPARE_TREE_NEW);
> +				if (ret < 0)
> +					goto out;
> +			}
>   			/*
>   			 * Advance send_progress now as we did not get into
>   			 * process_recorded_refs_if_needed in the new_gen case.
>   			 */
>   			sctx->send_progress = sctx->cur_ino + 1;
>   
> -			/*
> -			 * Now process all extents and xattrs of the inode as if
> -			 * they were all new.
> -			 */
> -			ret = process_all_extents(sctx);
> -			if (ret < 0)
> -				goto out;
> -			ret = process_all_new_xattrs(sctx);
> -			if (ret < 0)
> -				goto out;
> +			if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE) {
> +				if (S_ISREG(sctx->cur_inode_mode))
> +					sctx->total_data_size +=
> +						sctx->cur_inode_size;
> +				/* TODO: maybe account for xattrs one day too */
> +			} else {
> +				/*
> +				 * Now process all extents and xattrs of the
> +				 * inode as if they were all new.
> +				 */
> +				ret = process_all_extents(sctx);
> +				if (ret < 0)
> +					goto out;
> +				ret = process_all_new_xattrs(sctx);
> +				if (ret < 0)
> +					goto out;
> +			}
>   		} else {
>   			sctx->cur_inode_gen = left_gen;
>   			sctx->cur_inode_new = 0;
> @@ -5183,6 +5274,9 @@ static int changed_ref(struct send_ctx *sctx,
>   
>   	BUG_ON(sctx->cur_ino != sctx->cmp_key->objectid);
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +		return 0;
> +
>   	if (!sctx->cur_inode_new_gen &&
>   	    sctx->cur_ino != BTRFS_FIRST_FREE_OBJECTID) {
>   		if (result == BTRFS_COMPARE_TREE_NEW)
> @@ -5208,6 +5302,9 @@ static int changed_xattr(struct send_ctx *sctx,
>   
>   	BUG_ON(sctx->cur_ino != sctx->cmp_key->objectid);
>   
> +	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +		return 0;
> +
>   	if (!sctx->cur_inode_new_gen && !sctx->cur_inode_deleted) {
>   		if (result == BTRFS_COMPARE_TREE_NEW)
>   			ret = process_new_xattr(sctx);
> @@ -5317,6 +5414,8 @@ static int changed_cb(struct btrfs_root *left_root,
>   	if (result == BTRFS_COMPARE_TREE_SAME) {
>   		if (key->type == BTRFS_INODE_REF_KEY ||
>   		    key->type == BTRFS_INODE_EXTREF_KEY) {
> +			if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE)
> +				return 0;
>   			ret = compare_refs(sctx, left_path, key);
>   			if (!ret)
>   				return 0;
> @@ -5468,6 +5567,24 @@ out:
>   	return ret;
>   }
>   
> +static int compute_total_data_size(struct send_ctx *sctx)
> +{
> +	int ret;
> +
> +	sctx->total_data_size = 0;
> +
> +	if (sctx->parent_root) {
> +		ret = btrfs_compare_trees(sctx->send_root, sctx->parent_root,
> +					  changed_cb, sctx);
> +		if (!ret)
> +			ret = finish_inode_if_needed(sctx, 1);
> +	} else {
> +		ret = full_send_tree(sctx);
> +	}
> +
> +	return ret;
> +}
> +
>   static int send_subvol(struct send_ctx *sctx)
>   {
>   	int ret;
> @@ -5482,6 +5599,19 @@ static int send_subvol(struct send_ctx *sctx)
>   	if (ret < 0)
>   		goto out;
>   
> +	if (sctx->flags & BTRFS_SEND_FLAG_CALCULATE_DATA_SIZE) {
> +		sctx->phase = SEND_PHASE_COMPUTE_DATA_SIZE;
> +		ret = compute_total_data_size(sctx);
> +		if (ret < 0)
> +			goto out;
> +		ret = send_total_data_size(sctx, sctx->total_data_size);
> +		if (ret < 0)
> +			goto out;
> +		sctx->phase = SEND_PHASE_STREAM_CHANGES;
> +		sctx->cur_ino = 0;
> +		sctx->send_progress = 0;
> +	}
> +
>   	if (sctx->parent_root) {
>   		ret = btrfs_compare_trees(sctx->send_root, sctx->parent_root,
>   				changed_cb, sctx);
> diff --git a/fs/btrfs/send.h b/fs/btrfs/send.h
> index 48d425a..febeb72 100644
> --- a/fs/btrfs/send.h
> +++ b/fs/btrfs/send.h
> @@ -87,6 +87,7 @@ enum btrfs_send_cmd {
>   
>   	BTRFS_SEND_C_END,
>   	BTRFS_SEND_C_UPDATE_EXTENT,
> +	BTRFS_SEND_C_TOTAL_DATA_SIZE,
>   	__BTRFS_SEND_C_MAX,
>   };
>   #define BTRFS_SEND_C_MAX (__BTRFS_SEND_C_MAX - 1)
> diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
> index b4d6909..afc1529 100644
> --- a/include/uapi/linux/btrfs.h
> +++ b/include/uapi/linux/btrfs.h
> @@ -464,10 +464,21 @@ struct btrfs_ioctl_received_subvol_args {
>    */
>   #define BTRFS_SEND_FLAG_OMIT_END_CMD		0x4
>   
> +/*
> + * Calculate the amount (in bytes) of new file data between the send and
> + * parent snapshots, or in case of a full send, the total amount of file data
> + * we will send.
> + * This corresponds to the sum of the data lengths of each write and clone
> + * commands that are sent through the send stream. The receiving end can use
> + * this information to compute progress.
> + */
> +#define BTRFS_SEND_FLAG_CALCULATE_DATA_SIZE	0x8
> +
>   #define BTRFS_SEND_FLAG_MASK \
>   	(BTRFS_SEND_FLAG_NO_FILE_DATA | \
>   	 BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \
> -	 BTRFS_SEND_FLAG_OMIT_END_CMD)
> +	 BTRFS_SEND_FLAG_OMIT_END_CMD | \
> +	 BTRFS_SEND_FLAG_CALCULATE_DATA_SIZE)
>   
>   struct btrfs_ioctl_send_args {
>   	__s64 send_fd;			/* in */


  reply	other threads:[~2014-04-04 14:52 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-04 15:20 [RFC PATCH] Btrfs: send, add calculate data size flag to allow for progress estimation Filipe David Borba Manana
2014-04-04 14:52 ` Konstantinos Skarlatos [this message]
2014-04-04 15:59   ` Filipe David Manana
2014-04-04 15:53 ` David Sterba
2014-04-04 16:01   ` Filipe David Manana
2014-04-04 16:32     ` David Sterba
2014-04-06  0:18 ` Marc MERLIN
2014-04-06 16:57   ` Filipe David Manana
2014-04-06 17:20     ` Marc MERLIN
2014-04-07 15:25 ` Josef Bacik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=533EC742.5050505@gmail.com \
    --to=k.skarlatos@gmail.com \
    --cc=fdmanana@gmail.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).