Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [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

* [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

* 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 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox