|
@@ -112,6 +112,7 @@ struct send_ctx {
|
|
|
u64 cur_inode_mode;
|
|
|
u64 cur_inode_rdev;
|
|
|
u64 cur_inode_last_extent;
|
|
|
+ u64 cur_inode_next_write_offset;
|
|
|
|
|
|
u64 send_progress;
|
|
|
|
|
@@ -5030,6 +5031,7 @@ static int send_hole(struct send_ctx *sctx, u64 end)
|
|
|
break;
|
|
|
offset += len;
|
|
|
}
|
|
|
+ sctx->cur_inode_next_write_offset = offset;
|
|
|
tlv_put_failure:
|
|
|
fs_path_free(p);
|
|
|
return ret;
|
|
@@ -5265,6 +5267,7 @@ static int send_write_or_clone(struct send_ctx *sctx,
|
|
|
} else {
|
|
|
ret = send_extent_data(sctx, offset, len);
|
|
|
}
|
|
|
+ sctx->cur_inode_next_write_offset = offset + len;
|
|
|
out:
|
|
|
return ret;
|
|
|
}
|
|
@@ -5789,6 +5792,7 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
|
|
|
u64 right_gid;
|
|
|
int need_chmod = 0;
|
|
|
int need_chown = 0;
|
|
|
+ int need_truncate = 1;
|
|
|
int pending_move = 0;
|
|
|
int refs_processed = 0;
|
|
|
|
|
@@ -5826,9 +5830,13 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
|
|
|
need_chown = 1;
|
|
|
if (!S_ISLNK(sctx->cur_inode_mode))
|
|
|
need_chmod = 1;
|
|
|
+ if (sctx->cur_inode_next_write_offset == sctx->cur_inode_size)
|
|
|
+ need_truncate = 0;
|
|
|
} else {
|
|
|
+ u64 old_size;
|
|
|
+
|
|
|
ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
|
|
|
- NULL, NULL, &right_mode, &right_uid,
|
|
|
+ &old_size, NULL, &right_mode, &right_uid,
|
|
|
&right_gid, NULL);
|
|
|
if (ret < 0)
|
|
|
goto out;
|
|
@@ -5837,6 +5845,10 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
|
|
|
need_chown = 1;
|
|
|
if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode)
|
|
|
need_chmod = 1;
|
|
|
+ if ((old_size == sctx->cur_inode_size) ||
|
|
|
+ (sctx->cur_inode_size > old_size &&
|
|
|
+ sctx->cur_inode_next_write_offset == sctx->cur_inode_size))
|
|
|
+ need_truncate = 0;
|
|
|
}
|
|
|
|
|
|
if (S_ISREG(sctx->cur_inode_mode)) {
|
|
@@ -5855,10 +5867,13 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
|
|
|
goto out;
|
|
|
}
|
|
|
}
|
|
|
- ret = send_truncate(sctx, sctx->cur_ino, sctx->cur_inode_gen,
|
|
|
- sctx->cur_inode_size);
|
|
|
- if (ret < 0)
|
|
|
- goto out;
|
|
|
+ if (need_truncate) {
|
|
|
+ ret = send_truncate(sctx, sctx->cur_ino,
|
|
|
+ sctx->cur_inode_gen,
|
|
|
+ sctx->cur_inode_size);
|
|
|
+ if (ret < 0)
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (need_chown) {
|
|
@@ -5912,6 +5927,7 @@ static int changed_inode(struct send_ctx *sctx,
|
|
|
sctx->cur_ino = key->objectid;
|
|
|
sctx->cur_inode_new_gen = 0;
|
|
|
sctx->cur_inode_last_extent = (u64)-1;
|
|
|
+ sctx->cur_inode_next_write_offset = 0;
|
|
|
|
|
|
/*
|
|
|
* Set send_progress to current inode. This will tell all get_cur_xxx
|