* [PATCH 0/2] send: Avoid sending disknr==0 and PREALLOC extents when possible V2
@ 2013-01-21 10:22 Alex Lyakas
2013-01-21 10:27 ` [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible Alex Lyakas
2013-01-21 10:30 ` [PATCH 2/2] V2 On a diff-send, avoid sending PREALLOC extents Alex Lyakas
0 siblings, 2 replies; 5+ messages in thread
From: Alex Lyakas @ 2013-01-21 10:22 UTC (permalink / raw)
To: linux-btrfs, Josef Bacik, Alexander Block, Jan Schmidt, Chen Yang
Cc: Arne Jansen
These two patches address the issue of sending unneeded zero data for
disknr==0 and PREALLOC extents.
There is room for additional improvement for PREALLOC extents, but it
requires adding a new send command, so for now this is not addressed.
Changes in V2: no functional change; previous patchset was malformed,
so cleanup done with checkpatch.pl.
Please review and comment.
Alex Lyakas (2):
Avoid sending disknr==0 extents when possible.
On a diff-send, avoid sending PREALLOC extents, if the parent
root has only PREALLOC extents on an appropriate file range.
fs/btrfs/send.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 178 insertions(+), 6 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible.
2013-01-21 10:22 [PATCH 0/2] send: Avoid sending disknr==0 and PREALLOC extents when possible V2 Alex Lyakas
@ 2013-01-21 10:27 ` Alex Lyakas
2013-01-24 15:48 ` Josef Bacik
2013-01-21 10:30 ` [PATCH 2/2] V2 On a diff-send, avoid sending PREALLOC extents Alex Lyakas
1 sibling, 1 reply; 5+ messages in thread
From: Alex Lyakas @ 2013-01-21 10:27 UTC (permalink / raw)
To: linux-btrfs, Josef Bacik, Alexander Block, Jan Schmidt, Chen Yang
Cc: Arne Jansen
In the following cases we do not send disknr==0 extents:
1) full send 2) new inode in a diff-send 3) when disknr==0 extents are
added to the end of an inode
Original-version-by: Chen Yang <chenyang.fnst@cn.fujitsu.com>
Signed-off-by: Alex Lyakas <alex@zadarastorage.com>
---
fs/btrfs/send.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 5445454..bdef966 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3844,7 +3844,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
btrfs_item_key_to_cpu(eb, &found_key, slot);
if (found_key.objectid != key.objectid ||
found_key.type != key.type) {
- ret = 0;
+ /* No need to send a no-data extent it in this case */
+ ret = (left_disknr == 0) ? 1 : 0;
goto out;
}
@@ -3870,7 +3871,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
* This may only happen on the first iteration.
*/
if (found_key.offset + right_len <= ekey->offset) {
- ret = 0;
+ /* No need to send a no-data extent it in this case */
+ ret = (left_disknr == 0) ? 1 : 0;
goto out;
}
@@ -3951,6 +3953,30 @@ static int process_extent(struct send_ctx *sctx,
ret = 0;
goto out;
}
+ } else {
+ struct extent_buffer *eb;
+ struct btrfs_file_extent_item *ei;
+ u8 extent_type;
+ u64 extent_disknr;
+
+ eb = path->nodes[0];
+ ei = btrfs_item_ptr(eb, path->slots[0],
+ struct btrfs_file_extent_item);
+
+ extent_type = btrfs_file_extent_type(eb, ei);
+ extent_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
+ if (extent_type == BTRFS_FILE_EXTENT_REG &&
+ extent_disknr == 0) {
+ /*
+ * This is disknr=0 extent in a full-send or a
+ * new inode in a diff-send. Since we will
+ * send truncate command in finish_inode_if_needed
+ * anyways, the inode size will be correct,
+ * and we don't have to send all-zero data.
+ */
+ ret = 0;
+ goto out;
+ }
}
ret = find_extent_clone(sctx, path, key->objectid, key->offset,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible.
2013-01-21 10:27 ` [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible Alex Lyakas
@ 2013-01-24 15:48 ` Josef Bacik
0 siblings, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2013-01-24 15:48 UTC (permalink / raw)
To: Alex Lyakas
Cc: linux-btrfs, Josef Bacik, Alexander Block, Jan Schmidt, Chen Yang,
Arne Jansen
On Mon, Jan 21, 2013 at 03:27:22AM -0700, Alex Lyakas wrote:
> In the following cases we do not send disknr==0 extents:
> 1) full send 2) new inode in a diff-send 3) when disknr==0 extents are
> added to the end of an inode
>
> Original-version-by: Chen Yang <chenyang.fnst@cn.fujitsu.com>
> Signed-off-by: Alex Lyakas <alex@zadarastorage.com>
Neither of these would apply to btrfs-next, please rebase against btrfs-next and
resend. Thanks,
Josef
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] V2 On a diff-send, avoid sending PREALLOC extents
2013-01-21 10:22 [PATCH 0/2] send: Avoid sending disknr==0 and PREALLOC extents when possible V2 Alex Lyakas
2013-01-21 10:27 ` [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible Alex Lyakas
@ 2013-01-21 10:30 ` Alex Lyakas
1 sibling, 0 replies; 5+ messages in thread
From: Alex Lyakas @ 2013-01-21 10:30 UTC (permalink / raw)
To: linux-btrfs, Josef Bacik, Alexander Block, Jan Schmidt, Chen Yang
Cc: Arne Jansen
On a diff-send, avoid sending PREALLOC extents, if the parent root has
only PREALLOC extents on an appropriate file range.
This does not fully avoid sending PREALLOC extents, because on full-send or
on new inode we need a new send command to do that. But this patch improves
the situation by handling diff-sends.
Signed-off-by: Alex Lyakas <alex@zadarastorage.com>
---
fs/btrfs/send.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 150 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index bdef966..a162fa6 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3763,6 +3763,148 @@ out:
return ret;
}
+static int is_prealloc_extent_unchanged(struct send_ctx *sctx,
+ struct btrfs_path *left_path,
+ struct btrfs_key *ekey)
+{
+ int ret = 0;
+ struct btrfs_key key;
+ struct btrfs_path *path = NULL;
+ struct extent_buffer *eb;
+ int slot;
+ struct btrfs_key found_key;
+ struct btrfs_file_extent_item *ei;
+ u64 left_len;
+ u64 right_len;
+ u8 right_type;
+
+ eb = left_path->nodes[0];
+ slot = left_path->slots[0];
+ ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
+ left_len = btrfs_file_extent_num_bytes(eb, ei);
+
+ /*
+ * The logic is similar, but much simpler than in is_extent_unchanged().
+ * We need to check extents on the parent root, and make sure that only
+ * PREALLOC extents are on the same file range as our current extent.
+ *
+ * Following comments will refer to these graphics. L is the left
+ * extents which we are checking at the moment. 1-8 are the right
+ * extents that we iterate.
+ *
+ * |-----L-----|
+ * |-1-|-2a-|-3-|-4-|-5-|-6-|
+ *
+ * |-----L-----|
+ * |--1--|-2b-|...(same as above)
+ *
+ * Alternative situation. Happens on files where extents got split.
+ * |-----L-----|
+ * |-----------7-----------|-6-|
+ *
+ * Alternative situation. Happens on files which got larger.
+ * |-----L-----|
+ * |-8-|
+ * Nothing follows after 8.
+ */
+
+ path = alloc_path_for_send();
+ if (!path)
+ return -ENOMEM;
+
+ key.objectid = ekey->objectid;
+ key.type = BTRFS_EXTENT_DATA_KEY;
+ key.offset = ekey->offset;
+ ret = btrfs_search_slot_for_read(sctx->parent_root, &key, path, 0, 0);
+ if (ret < 0)
+ goto out;
+ if (ret) {
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * Handle special case where the right side has no extents at all.
+ */
+ eb = path->nodes[0];
+ slot = path->slots[0];
+ btrfs_item_key_to_cpu(eb, &found_key, slot);
+ if (found_key.objectid != key.objectid ||
+ found_key.type != key.type) {
+ /*
+ * We need to send a "prealloc" command,
+ * which we don't have yet, just send
+ * this extent fully.
+ */
+ ret = 0;
+ goto out;
+ }
+
+ key = found_key;
+ while (key.offset < ekey->offset + left_len) {
+ ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
+ right_type = btrfs_file_extent_type(eb, ei);
+ right_len = btrfs_file_extent_num_bytes(eb, ei);
+
+ if (right_type != BTRFS_FILE_EXTENT_PREALLOC) {
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * Are we at extent 8? If yes, we know the extent is changed.
+ * This may only happen on the first iteration.
+ */
+ if (found_key.offset + right_len <= ekey->offset) {
+ /*
+ * We need to send a "prealloc" command,
+ * which we don't have yet,
+ * just send this extent fully.
+ */
+ ret = 0;
+ goto out;
+ }
+
+ /*
+ * The right extent is also PREALLOC, so up to
+ * here we are ok, continue checking
+ */
+ ret = btrfs_next_item(sctx->parent_root, path);
+ if (ret < 0)
+ goto out;
+ if (!ret) {
+ eb = path->nodes[0];
+ slot = path->slots[0];
+ btrfs_item_key_to_cpu(eb, &found_key, slot);
+ }
+ if (ret || found_key.objectid != key.objectid ||
+ found_key.type != key.type) {
+ key.offset += right_len;
+ break;
+ } else {
+ if (found_key.offset != key.offset + right_len) {
+ /* Should really not happen */
+ ret = -EIO;
+ goto out;
+ }
+ }
+ key = found_key;
+ }
+
+ /*
+ * We're now behind the left extent (treat as unchanged) or at the end
+ * of the right side (treat as changed).
+ */
+ if (key.offset >= ekey->offset + left_len)
+ ret = 1;
+ else
+ ret = 0;
+
+out:
+ btrfs_free_path(path);
+ return ret;
+}
+
static int is_extent_unchanged(struct send_ctx *sctx,
struct btrfs_path *left_path,
struct btrfs_key *ekey)
@@ -3786,15 +3928,15 @@ static int is_extent_unchanged(struct send_ctx *sctx,
u8 left_type;
u8 right_type;
- path = alloc_path_for_send();
- if (!path)
- return -ENOMEM;
-
eb = left_path->nodes[0];
slot = left_path->slots[0];
ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
left_type = btrfs_file_extent_type(eb, ei);
+ if (left_type == BTRFS_FILE_EXTENT_PREALLOC) {
+ ret = is_prealloc_extent_unchanged(sctx, left_path, ekey);
+ goto out;
+ }
if (left_type != BTRFS_FILE_EXTENT_REG) {
ret = 0;
goto out;
@@ -3825,6 +3967,10 @@ static int is_extent_unchanged(struct send_ctx *sctx,
* Nothing follows after 8.
*/
+ path = alloc_path_for_send();
+ if (!path)
+ return -ENOMEM;
+
key.objectid = ekey->objectid;
key.type = BTRFS_EXTENT_DATA_KEY;
key.offset = ekey->offset;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible
@ 2013-01-28 17:03 Alex Lyakas
0 siblings, 0 replies; 5+ messages in thread
From: Alex Lyakas @ 2013-01-28 17:03 UTC (permalink / raw)
To: linux-btrfs, Josef Bacik
Cc: Jan Schmidt, Alexander Block, Arne Jansen, Chen Yang
In the following cases we do not send disknr==0 extents:
1) full send 2) new inode in a diff-send 3) when disknr==0 extents are
added to the end of an inode
Original-version-by: Chen Yang <chenyang.fnst@cn.fujitsu.com>
Signed-off-by: Alex Lyakas <alex.btrfs@zadarastorage.com>
---
fs/btrfs/send.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 321b7fb..e23f5cf 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3846,7 +3846,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
btrfs_item_key_to_cpu(eb, &found_key, slot);
if (found_key.objectid != key.objectid ||
found_key.type != key.type) {
- ret = 0;
+ /* No need to send a no-data extent it in this case */
+ ret = (left_disknr == 0) ? 1 : 0;
goto out;
}
@@ -3872,7 +3873,8 @@ static int is_extent_unchanged(struct send_ctx *sctx,
* This may only happen on the first iteration.
*/
if (found_key.offset + right_len <= ekey->offset) {
- ret = 0;
+ /* No need to send a no-data extent it in this case */
+ ret = (left_disknr == 0) ? 1 : 0;
goto out;
}
@@ -3953,6 +3955,30 @@ static int process_extent(struct send_ctx *sctx,
ret = 0;
goto out;
}
+ } else {
+ struct extent_buffer *eb;
+ struct btrfs_file_extent_item *ei;
+ u8 extent_type;
+ u64 extent_disknr;
+
+ eb = path->nodes[0];
+ ei = btrfs_item_ptr(eb, path->slots[0],
+ struct btrfs_file_extent_item);
+
+ extent_type = btrfs_file_extent_type(eb, ei);
+ extent_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
+ if (extent_type == BTRFS_FILE_EXTENT_REG &&
+ extent_disknr == 0) {
+ /*
+ * This is disknr=0 extent in a full-send or a
+ * new inode in a diff-send. Since we will
+ * send truncate command in finish_inode_if_needed
+ * anyways, the inode size will be correct,
+ * and we don't have to send all-zero data.
+ */
+ ret = 0;
+ goto out;
+ }
}
ret = find_extent_clone(sctx, path, key->objectid, key->offset,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-01-28 17:03 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-01-21 10:22 [PATCH 0/2] send: Avoid sending disknr==0 and PREALLOC extents when possible V2 Alex Lyakas
2013-01-21 10:27 ` [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible Alex Lyakas
2013-01-24 15:48 ` Josef Bacik
2013-01-21 10:30 ` [PATCH 2/2] V2 On a diff-send, avoid sending PREALLOC extents Alex Lyakas
-- strict thread matches above, loose matches on Subject: below --
2013-01-28 17:03 [PATCH 1/2] V2 Avoid sending disknr==0 extents when possible Alex Lyakas
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.