osandov / rpms / btrfs-progs

Forked from rpms/btrfs-progs 2 years ago
Clone
dbfe2d
From 3e92b1e0b97146516f4287f5e42428a3b7dc4a3d Mon Sep 17 00:00:00 2001
dbfe2d
From: Boris Burkov <boris@bur.io>
dbfe2d
Date: Fri, 21 Aug 2020 00:40:07 -0700
dbfe2d
Subject: [PATCH] btrfs-progs: receive: process fallocate commands
dbfe2d
dbfe2d
Send stream v2 can emit fallocate commands, so receive must support them
dbfe2d
as well. The implementation simply passes along the arguments to the
dbfe2d
syscall. Note that mode is encoded as a u32 in send stream but fallocate
dbfe2d
takes an int, so there is a unsigned->signed conversion there.
dbfe2d
dbfe2d
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
dbfe2d
Signed-off-by: Boris Burkov <boris@bur.io>
dbfe2d
---
dbfe2d
 cmds/receive-dump.c  |  9 +++++++++
dbfe2d
 cmds/receive.c       | 25 +++++++++++++++++++++++++
dbfe2d
 common/send-stream.c |  9 +++++++++
dbfe2d
 common/send-stream.h |  2 ++
dbfe2d
 4 files changed, 45 insertions(+)
dbfe2d
dbfe2d
diff --git a/cmds/receive-dump.c b/cmds/receive-dump.c
dbfe2d
index 83701b62..fa397bcf 100644
dbfe2d
--- a/cmds/receive-dump.c
dbfe2d
+++ b/cmds/receive-dump.c
dbfe2d
@@ -331,6 +331,14 @@ static int print_encoded_write(const char *path, const void *data, u64 offset,
dbfe2d
 			  unencoded_offset, compression, encryption);
dbfe2d
 }
dbfe2d
 
dbfe2d
+static int print_fallocate(const char *path, int mode, u64 offset, u64 len,
dbfe2d
+			   void *user)
dbfe2d
+{
dbfe2d
+	return PRINT_DUMP(user, path, "fallocate",
dbfe2d
+			  "mode=%d offset=%llu len=%llu",
dbfe2d
+			  mode, offset, len);
dbfe2d
+}
dbfe2d
+
dbfe2d
 struct btrfs_send_ops btrfs_print_send_ops = {
dbfe2d
 	.subvol = print_subvol,
dbfe2d
 	.snapshot = print_snapshot,
dbfe2d
@@ -354,4 +362,5 @@ struct btrfs_send_ops btrfs_print_send_ops = {
dbfe2d
 	.utimes = print_utimes,
dbfe2d
 	.update_extent = print_update_extent,
dbfe2d
 	.encoded_write = print_encoded_write,
dbfe2d
+	.fallocate = print_fallocate,
dbfe2d
 };
dbfe2d
diff --git a/cmds/receive.c b/cmds/receive.c
dbfe2d
index 5fd939ce..4893d693 100644
dbfe2d
--- a/cmds/receive.c
dbfe2d
+++ b/cmds/receive.c
dbfe2d
@@ -1260,6 +1260,30 @@ static int process_encoded_write(const char *path, const void *data, u64 offset,
dbfe2d
 				    compression);
dbfe2d
 }
dbfe2d
 
dbfe2d
+static int process_fallocate(const char *path, int mode, u64 offset, u64 len,
dbfe2d
+			     void *user)
dbfe2d
+{
dbfe2d
+	int ret;
dbfe2d
+	struct btrfs_receive *rctx = user;
dbfe2d
+	char full_path[PATH_MAX];
dbfe2d
+
dbfe2d
+	ret = path_cat_out(full_path, rctx->full_subvol_path, path);
dbfe2d
+	if (ret < 0) {
dbfe2d
+		error("fallocate: path invalid: %s", path);
dbfe2d
+		return ret;
dbfe2d
+	}
dbfe2d
+	ret = open_inode_for_write(rctx, full_path);
dbfe2d
+	if (ret < 0)
dbfe2d
+		return ret;
dbfe2d
+	ret = fallocate(rctx->write_fd, mode, offset, len);
dbfe2d
+	if (ret < 0) {
dbfe2d
+		ret = -errno;
dbfe2d
+		error("fallocate: fallocate on %s failed: %m", path);
dbfe2d
+		return ret;
dbfe2d
+	}
dbfe2d
+	return 0;
dbfe2d
+}
dbfe2d
+
dbfe2d
 static struct btrfs_send_ops send_ops = {
dbfe2d
 	.subvol = process_subvol,
dbfe2d
 	.snapshot = process_snapshot,
dbfe2d
@@ -1283,6 +1307,7 @@ static struct btrfs_send_ops send_ops = {
dbfe2d
 	.utimes = process_utimes,
dbfe2d
 	.update_extent = process_update_extent,
dbfe2d
 	.encoded_write = process_encoded_write,
dbfe2d
+	.fallocate = process_fallocate,
dbfe2d
 };
dbfe2d
 
dbfe2d
 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
dbfe2d
diff --git a/common/send-stream.c b/common/send-stream.c
dbfe2d
index ce7c40f5..2d0aa624 100644
dbfe2d
--- a/common/send-stream.c
dbfe2d
+++ b/common/send-stream.c
dbfe2d
@@ -373,6 +373,7 @@ static int read_and_process_cmd(struct btrfs_send_stream *sctx)
dbfe2d
 	u64 unencoded_offset;
dbfe2d
 	int len;
dbfe2d
 	int xattr_len;
dbfe2d
+	int fallocate_mode;
dbfe2d
 
dbfe2d
 	ret = read_cmd(sctx);
dbfe2d
 	if (ret)
dbfe2d
@@ -537,6 +538,14 @@ static int read_and_process_cmd(struct btrfs_send_stream *sctx)
dbfe2d
 	case BTRFS_SEND_C_END:
dbfe2d
 		ret = 1;
dbfe2d
 		break;
dbfe2d
+	case BTRFS_SEND_C_FALLOCATE:
dbfe2d
+		TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
dbfe2d
+		TLV_GET_U32(sctx, BTRFS_SEND_A_FALLOCATE_MODE, &fallocate_mode);
dbfe2d
+		TLV_GET_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, &offset);
dbfe2d
+		TLV_GET_U64(sctx, BTRFS_SEND_A_SIZE, &tmp);
dbfe2d
+		ret = sctx->ops->fallocate(path, fallocate_mode, offset, tmp,
dbfe2d
+					   sctx->user);
dbfe2d
+		break;
dbfe2d
 	}
dbfe2d
 
dbfe2d
 tlv_get_failed:
dbfe2d
diff --git a/common/send-stream.h b/common/send-stream.h
dbfe2d
index 44abbc9d..61a88d3d 100644
dbfe2d
--- a/common/send-stream.h
dbfe2d
+++ b/common/send-stream.h
dbfe2d
@@ -57,6 +57,8 @@ struct btrfs_send_ops {
dbfe2d
 			     u64 len, u64 unencoded_file_len, u64 unencoded_len,
dbfe2d
 			     u64 unencoded_offset, u32 compression,
dbfe2d
 			     u32 encryption, void *user);
dbfe2d
+	int (*fallocate)(const char *path, int mode, u64 offset, u64 len,
dbfe2d
+			 void *user);
dbfe2d
 };
dbfe2d
 
dbfe2d
 int btrfs_read_and_process_send_stream(int fd,
dbfe2d
-- 
dbfe2d
2.35.1
dbfe2d