btrfs-progs: receive: process fallocate commands

Send stream v2 can emit fallocate commands, so receive must support them
as well. The implementation simply passes along the arguments to the
syscall. Note that mode is encoded as a u32 in send stream but fallocate
takes an int, so there is a unsigned->signed conversion there.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Boris Burkov 2022-03-17 10:25:50 -07:00 committed by David Sterba
parent d20e759fc9
commit 54db5c0397
4 changed files with 45 additions and 0 deletions

View File

@ -331,6 +331,14 @@ static int print_encoded_write(const char *path, const void *data, u64 offset,
unencoded_offset, compression, encryption);
}
static int print_fallocate(const char *path, int mode, u64 offset, u64 len,
void *user)
{
return PRINT_DUMP(user, path, "fallocate",
"mode=%d offset=%llu len=%llu",
mode, offset, len);
}
struct btrfs_send_ops btrfs_print_send_ops = {
.subvol = print_subvol,
.snapshot = print_snapshot,
@ -354,4 +362,5 @@ struct btrfs_send_ops btrfs_print_send_ops = {
.utimes = print_utimes,
.update_extent = print_update_extent,
.encoded_write = print_encoded_write,
.fallocate = print_fallocate,
};

View File

@ -1260,6 +1260,30 @@ static int process_encoded_write(const char *path, const void *data, u64 offset,
compression);
}
static int process_fallocate(const char *path, int mode, u64 offset, u64 len,
void *user)
{
int ret;
struct btrfs_receive *rctx = user;
char full_path[PATH_MAX];
ret = path_cat_out(full_path, rctx->full_subvol_path, path);
if (ret < 0) {
error("fallocate: path invalid: %s", path);
return ret;
}
ret = open_inode_for_write(rctx, full_path);
if (ret < 0)
return ret;
ret = fallocate(rctx->write_fd, mode, offset, len);
if (ret < 0) {
ret = -errno;
error("fallocate: fallocate on %s failed: %m", path);
return ret;
}
return 0;
}
static struct btrfs_send_ops send_ops = {
.subvol = process_subvol,
.snapshot = process_snapshot,
@ -1283,6 +1307,7 @@ static struct btrfs_send_ops send_ops = {
.utimes = process_utimes,
.update_extent = process_update_extent,
.encoded_write = process_encoded_write,
.fallocate = process_fallocate,
};
static int do_receive(struct btrfs_receive *rctx, const char *tomnt,

View File

@ -374,6 +374,7 @@ static int read_and_process_cmd(struct btrfs_send_stream *sctx)
u64 unencoded_offset;
int len;
int xattr_len;
int fallocate_mode;
ret = read_cmd(sctx);
if (ret)
@ -538,6 +539,14 @@ static int read_and_process_cmd(struct btrfs_send_stream *sctx)
case BTRFS_SEND_C_END:
ret = 1;
break;
case BTRFS_SEND_C_FALLOCATE:
TLV_GET_STRING(sctx, BTRFS_SEND_A_PATH, &path);
TLV_GET_U32(sctx, BTRFS_SEND_A_FALLOCATE_MODE, &fallocate_mode);
TLV_GET_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, &offset);
TLV_GET_U64(sctx, BTRFS_SEND_A_SIZE, &tmp);
ret = sctx->ops->fallocate(path, fallocate_mode, offset, tmp,
sctx->user);
break;
}
tlv_get_failed:

View File

@ -57,6 +57,8 @@ struct btrfs_send_ops {
u64 len, u64 unencoded_file_len, u64 unencoded_len,
u64 unencoded_offset, u32 compression,
u32 encryption, void *user);
int (*fallocate)(const char *path, int mode, u64 offset, u64 len,
void *user);
};
int btrfs_read_and_process_send_stream(int fd,