|
4 | 4 | */
|
5 | 5 |
|
6 | 6 | #include <linux/bsearch.h>
|
| 7 | +#include <linux/falloc.h> |
7 | 8 | #include <linux/fs.h>
|
8 | 9 | #include <linux/file.h>
|
9 | 10 | #include <linux/sort.h>
|
@@ -5405,13 +5406,45 @@ static int send_update_extent(struct send_ctx *sctx,
|
5405 | 5406 | return ret;
|
5406 | 5407 | }
|
5407 | 5408 |
|
| 5409 | +static int send_fallocate(struct send_ctx *sctx, u32 mode, u64 offset, u64 len) |
| 5410 | +{ |
| 5411 | + struct fs_path *path; |
| 5412 | + int ret; |
| 5413 | + |
| 5414 | + path = get_cur_inode_path(sctx); |
| 5415 | + if (IS_ERR(path)) |
| 5416 | + return PTR_ERR(path); |
| 5417 | + |
| 5418 | + ret = begin_cmd(sctx, BTRFS_SEND_C_FALLOCATE); |
| 5419 | + if (ret < 0) |
| 5420 | + return ret; |
| 5421 | + |
| 5422 | + TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH, path); |
| 5423 | + TLV_PUT_U32(sctx, BTRFS_SEND_A_FALLOCATE_MODE, mode); |
| 5424 | + TLV_PUT_U64(sctx, BTRFS_SEND_A_FILE_OFFSET, offset); |
| 5425 | + TLV_PUT_U64(sctx, BTRFS_SEND_A_SIZE, len); |
| 5426 | + |
| 5427 | + ret = send_cmd(sctx); |
| 5428 | + |
| 5429 | +tlv_put_failure: |
| 5430 | + return ret; |
| 5431 | +} |
| 5432 | + |
5408 | 5433 | static int send_hole(struct send_ctx *sctx, u64 end)
|
5409 | 5434 | {
|
5410 | 5435 | struct fs_path *p = NULL;
|
5411 | 5436 | u64 read_size = max_send_read_size(sctx);
|
5412 | 5437 | u64 offset = sctx->cur_inode_last_extent;
|
5413 | 5438 | int ret = 0;
|
5414 | 5439 |
|
| 5440 | + /* |
| 5441 | + * Starting with send stream v2 we have fallocate and can use it to |
| 5442 | + * punch holes instead of sending writes full of zeroes. |
| 5443 | + */ |
| 5444 | + if (proto_cmd_ok(sctx, BTRFS_SEND_C_FALLOCATE)) |
| 5445 | + return send_fallocate(sctx, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, |
| 5446 | + offset, end - offset); |
| 5447 | + |
5415 | 5448 | /*
|
5416 | 5449 | * A hole that starts at EOF or beyond it. Since we do not yet support
|
5417 | 5450 | * fallocate (for extent preallocation and hole punching), sending a
|
|
0 commit comments