All of lore.kernel.org
 help / color / mirror / Atom feed
From: Filipe David Borba Manana <fdmanana@gmail.com>
To: linux-btrfs@vger.kernel.org
Cc: Filipe David Borba Manana <fdmanana@gmail.com>
Subject: [PATCH 3/4] Btrfs: send, use fallocate command to punch holes
Date: Tue, 15 Apr 2014 17:40:20 +0100	[thread overview]
Message-ID: <1397580021-26598-3-git-send-email-fdmanana@gmail.com> (raw)
In-Reply-To: <1397580021-26598-1-git-send-email-fdmanana@gmail.com>

Instead of sending a write command with a data buffer filled with 0 value bytes,
use the fallocate command, introduced in the send stream version 2, to tell the
receiver to punch a file hole using the fallocate system call.

Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
---
 fs/btrfs/send.c | 51 +++++++++++++++++++++++++++++++--------------------
 fs/btrfs/send.h |  4 ++++
 2 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 0cff503..26a09ba 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -564,6 +564,7 @@ static int tlv_put(struct send_ctx *sctx, u16 attr, const void *data, int len)
 		return tlv_put(sctx, attr, &__tmp, sizeof(__tmp));	\
 	}
 
+TLV_PUT_DEFINE_INT(32)
 TLV_PUT_DEFINE_INT(64)
 
 static int tlv_put_string(struct send_ctx *sctx, u16 attr,
@@ -4479,15 +4480,14 @@ out:
 	return ret;
 }
 
-static int send_hole(struct send_ctx *sctx, u64 end)
+static int send_fallocate(struct send_ctx *sctx, u32 flags,
+			  u64 offset, u64 len)
 {
 	struct fs_path *p = NULL;
-	u64 offset = sctx->cur_inode_last_extent;
-	u64 len;
 	int ret = 0;
 
 	if (sctx->phase == SEND_PHASE_COMPUTE_DATA_SIZE) {
-		sctx->total_data_size += end - offset;
+		sctx->total_data_size += len;
 		return 0;
 	}
 
@@ -4496,27 +4496,32 @@ static int send_hole(struct send_ctx *sctx, u64 end)
 		return -ENOMEM;
 	ret = get_cur_path(sctx, sctx->cur_ino, sctx->cur_inode_gen, p);
 	if (ret < 0)
-		goto tlv_put_failure;
-	memset(sctx->read_buf, 0, BTRFS_SEND_READ_SIZE);
-	while (offset < end) {
-		len = min_t(u64, end - offset, BTRFS_SEND_READ_SIZE);
+		goto out;
+
+	ret = begin_cmd(sctx, BTRFS_SEND_C_FALLOCATE);
+	if (ret < 0)
+		goto out;
+	TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
+	TLV_PUT_U32(sctx, BTRFS_SEND_A_FALLOCATE_FLAGS, flags);
+	TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset);
+	TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, len);
+	ret = send_cmd(sctx);
 
-		ret = begin_cmd(sctx, BTRFS_SEND_C_WRITE);
-		if (ret < 0)
-			break;
-		TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, p);
-		TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset);
-		TLV_PUT(sctx, BTRFS_SEND_A_DATA, sctx->read_buf, len);
-		ret = send_cmd(sctx);
-		if (ret < 0)
-			break;
-		offset += len;
-	}
 tlv_put_failure:
+out:
 	fs_path_free(p);
 	return ret;
 }
 
+static int send_hole(struct send_ctx *sctx, u64 end)
+{
+	u64 offset = sctx->cur_inode_last_extent;
+	u64 len = end - offset;
+
+	return send_fallocate(sctx, BTRFS_SEND_PUNCH_HOLE_FALLOC_FLAGS,
+			      offset, len);
+}
+
 static int send_write_or_clone(struct send_ctx *sctx,
 			       struct btrfs_path *path,
 			       struct btrfs_key *key,
@@ -4547,7 +4552,8 @@ static int send_write_or_clone(struct send_ctx *sctx,
 		len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
 	}
 
-	if (offset + len > sctx->cur_inode_size)
+	if (offset < sctx->cur_inode_size &&
+	    offset + len > sctx->cur_inode_size)
 		len = sctx->cur_inode_size - offset;
 	if (len == 0) {
 		ret = 0;
@@ -4564,6 +4570,11 @@ static int send_write_or_clone(struct send_ctx *sctx,
 		ret = send_clone(sctx, offset, len, clone_root);
 	} else if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA) {
 		ret = send_update_extent(sctx, offset, len);
+	} else if (btrfs_file_extent_disk_bytenr(path->nodes[0], ei) == 0 &&
+		   type != BTRFS_FILE_EXTENT_INLINE &&
+		   offset < sctx->cur_inode_size) {
+		ret = send_fallocate(sctx, BTRFS_SEND_PUNCH_HOLE_FALLOC_FLAGS,
+				     offset, len);
 	} else {
 		while (pos < len) {
 			l = len - pos;
diff --git a/fs/btrfs/send.h b/fs/btrfs/send.h
index 7b5df08..a03f66c 100644
--- a/fs/btrfs/send.h
+++ b/fs/btrfs/send.h
@@ -140,6 +140,10 @@ enum {
 #define BTRFS_SEND_A_FALLOCATE_FLAG_KEEP_SIZE   (1 << 0)
 #define BTRFS_SEND_A_FALLOCATE_FLAG_PUNCH_HOLE  (1 << 1)
 
+#define BTRFS_SEND_PUNCH_HOLE_FALLOC_FLAGS        \
+	(BTRFS_SEND_A_FALLOCATE_FLAG_KEEP_SIZE |  \
+	 BTRFS_SEND_A_FALLOCATE_FLAG_PUNCH_HOLE)
+
 #ifdef __KERNEL__
 long btrfs_ioctl_send(struct file *mnt_file, void __user *arg);
 #endif
-- 
1.9.1


  parent reply	other threads:[~2014-04-15 15:40 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-15 16:40 [PATCH 1/4] Btrfs: send, bump stream version Filipe David Borba Manana
2014-04-15 16:40 ` [PATCH 2/4] Btrfs: send, implement total data size command to allow for progress estimation Filipe David Borba Manana
2014-04-16 14:50   ` [PATCH 2/4 v2] " Filipe David Borba Manana
2014-04-15 16:40 ` Filipe David Borba Manana [this message]
2014-04-16 14:51   ` [PATCH 3/4 v2] Btrfs: send, use fallocate command to punch holes Filipe David Borba Manana
2014-04-16 16:16   ` [PATCH 3/4 v3] " Filipe David Borba Manana
2014-04-15 16:40 ` [PATCH 4/4] Btrfs: send, use fallocate command to allocate extents Filipe David Borba Manana
2014-04-16 14:52   ` [PATCH 4/4 v2] " Filipe David Borba Manana
2014-04-16 17:56   ` [PATCH 4/4 v3] " Filipe David Borba Manana
2014-04-15 17:28 ` [PATCH 1/4] Btrfs: send, bump stream version Mark Fasheh
2014-04-15 17:34   ` Filipe David Manana
2014-04-15 17:41     ` Mark Fasheh
2014-04-15 17:57       ` Filipe David Manana
2014-04-15 18:04         ` Mark Fasheh
2014-04-15 18:10           ` Josef Bacik
2014-04-15 18:30             ` Filipe David Manana
2014-04-15 19:35               ` Mark Fasheh
2014-04-15 19:49                 ` Filipe David Manana
2014-04-18 17:18                   ` David Sterba
2014-04-18 19:58                     ` Filipe David Manana
2014-04-16 14:48 ` [PATCH 1/4 v2] " Filipe David Borba Manana
2014-04-20 14:01   ` [PATCH 1/6 v3] " Filipe David Borba Manana
2014-06-23 12:00 ` [PATCH 1/6 v5] " Filipe David Borba Manana

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=1397580021-26598-3-git-send-email-fdmanana@gmail.com \
    --to=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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.