linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Btrfs: incremental send, clear name from cache after orphanization
@ 2015-03-08 17:48 Filipe Manana
  2015-04-02 16:21 ` David Sterba
  0 siblings, 1 reply; 3+ messages in thread
From: Filipe Manana @ 2015-03-08 17:48 UTC (permalink / raw)
  To: linux-btrfs; +Cc: robbieko, Filipe Manana

If a directory's reference ends up being orphanized, because the inode
currently being processed has a new path that matches that directory's
path, make sure we evict the name of the directory from the name cache.
This is because there might be descendent inodes (either directories or
regular files) that will be orphanized later too, and therefore the
orphan name of the ancestor must be used, otherwise we send issue rename
operations with a wrong path in the send stream.

Reproducer:

  $ mkfs.btrfs -f /dev/sdb
  $ mount /dev/sdb /mnt

  $ mkdir -p /mnt/data/n1/n2/p1/p2
  $ mkdir /mnt/data/n4
  $ mkdir -p /mnt/data/p1/p2

  $ btrfs subvolume snapshot -r /mnt /mnt/snap1

  $ mv /mnt/data/p1/p2 /mnt/data
  $ mv /mnt/data/n1/n2/p1/p2 /mnt/data/p1
  $ mv /mnt/data/p2 /mnt/data/n1/n2/p1
  $ mv /mnt/data/n1/n2 /mnt/data/p1
  $ mv /mnt/data/p1 /mnt/data/n4
  $ mv /mnt/data/n4/p1/n2/p1 /mnt/data

  $ btrfs subvolume snapshot -r /mnt /mnt/snap2

  $ btrfs send /mnt/snap1 -f /tmp/1.send
  $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/2.send

  $ mkfs.btrfs -f /dev/sdc
  $ mount /dev/sdc /mnt2
  $ btrfs receive /mnt2 -f /tmp/1.send
  $ btrfs receive /mnt2 -f /tmp/2.send
  ERROR: rename data/p1/p2 -> data/n4/p1/p2 failed. no such file or directory

Directories data/p1 (inode 263) and data/p1/p2 (inode 264) in the parent
snapshot are both orphanized during the incremental send, and as soon as
data/p1 is orphanized, we must make sure that when orphanizing data/p1/p2
we use a source path of o263-6-o/p2 for the rename operation instead of
the old path data/p1/p2 (the one before the orphanization of inode 263).

A test case for xfstests follows soon.

Reported-by: Robbie Ko <robbieko@synology.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/send.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 571de5a..00cb924 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3610,10 +3610,27 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
 			if (ret < 0)
 				goto out;
 			if (ret) {
+				struct name_cache_entry *nce;
+
 				ret = orphanize_inode(sctx, ow_inode, ow_gen,
 						cur->full_path);
 				if (ret < 0)
 					goto out;
+				/*
+				 * Make sure we clear our orphanized inode's
+				 * name from the name cache. This is because the
+				 * inode ow_inode might be an ancestor of some
+				 * other inode that will be orphanized as well
+				 * later and has an inode number greater than
+				 * sctx->send_progress. We need to prevent
+				 * future name lookups from using the old name
+				 * and get instead the orphan name.
+				 */
+				nce = name_cache_search(sctx, ow_inode, ow_gen);
+				if (nce) {
+					name_cache_delete(sctx, nce);
+					kfree(nce);
+				}
 			} else {
 				ret = send_unlink(sctx, cur->full_path);
 				if (ret < 0)
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] Btrfs: incremental send, clear name from cache after orphanization
@ 2015-03-12 15:16 Filipe Manana
  0 siblings, 0 replies; 3+ messages in thread
From: Filipe Manana @ 2015-03-12 15:16 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Filipe Manana

If a directory's reference ends up being orphanized, because the inode
currently being processed has a new path that matches that directory's
path, make sure we evict the name of the directory from the name cache.
This is because there might be descendent inodes (either directories or
regular files) that will be orphanized later too, and therefore the
orphan name of the ancestor must be used, otherwise we send issue rename
operations with a wrong path in the send stream.

Reproducer:

  $ mkfs.btrfs -f /dev/sdb
  $ mount /dev/sdb /mnt

  $ mkdir -p /mnt/data/n1/n2/p1/p2
  $ mkdir /mnt/data/n4
  $ mkdir -p /mnt/data/p1/p2

  $ btrfs subvolume snapshot -r /mnt /mnt/snap1

  $ mv /mnt/data/p1/p2 /mnt/data
  $ mv /mnt/data/n1/n2/p1/p2 /mnt/data/p1
  $ mv /mnt/data/p2 /mnt/data/n1/n2/p1
  $ mv /mnt/data/n1/n2 /mnt/data/p1
  $ mv /mnt/data/p1 /mnt/data/n4
  $ mv /mnt/data/n4/p1/n2/p1 /mnt/data

  $ btrfs subvolume snapshot -r /mnt /mnt/snap2

  $ btrfs send /mnt/snap1 -f /tmp/1.send
  $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/2.send

  $ mkfs.btrfs -f /dev/sdc
  $ mount /dev/sdc /mnt2
  $ btrfs receive /mnt2 -f /tmp/1.send
  $ btrfs receive /mnt2 -f /tmp/2.send
  ERROR: rename data/p1/p2 -> data/n4/p1/p2 failed. no such file or directory

Directories data/p1 (inode 263) and data/p1/p2 (inode 264) in the parent
snapshot are both orphanized during the incremental send, and as soon as
data/p1 is orphanized, we must make sure that when orphanizing data/p1/p2
we use a source path of o263-6-o/p2 for the rename operation instead of
the old path data/p1/p2 (the one before the orphanization of inode 263).

A test case for xfstests follows soon.

Reported-by: Robbie Ko <robbieko@synology.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---

This is a re-send, since my git send-email seems to have failed earlier
today.

 fs/btrfs/send.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 571de5a..00cb924 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -3610,10 +3610,27 @@ verbose_printk("btrfs: process_recorded_refs %llu\n", sctx->cur_ino);
 			if (ret < 0)
 				goto out;
 			if (ret) {
+				struct name_cache_entry *nce;
+
 				ret = orphanize_inode(sctx, ow_inode, ow_gen,
 						cur->full_path);
 				if (ret < 0)
 					goto out;
+				/*
+				 * Make sure we clear our orphanized inode's
+				 * name from the name cache. This is because the
+				 * inode ow_inode might be an ancestor of some
+				 * other inode that will be orphanized as well
+				 * later and has an inode number greater than
+				 * sctx->send_progress. We need to prevent
+				 * future name lookups from using the old name
+				 * and get instead the orphan name.
+				 */
+				nce = name_cache_search(sctx, ow_inode, ow_gen);
+				if (nce) {
+					name_cache_delete(sctx, nce);
+					kfree(nce);
+				}
 			} else {
 				ret = send_unlink(sctx, cur->full_path);
 				if (ret < 0)
-- 
2.1.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] Btrfs: incremental send, clear name from cache after orphanization
  2015-03-08 17:48 Filipe Manana
@ 2015-04-02 16:21 ` David Sterba
  0 siblings, 0 replies; 3+ messages in thread
From: David Sterba @ 2015-04-02 16:21 UTC (permalink / raw)
  To: Filipe Manana; +Cc: linux-btrfs, robbieko

On Sun, Mar 08, 2015 at 05:48:25PM +0000, Filipe Manana wrote:
> If a directory's reference ends up being orphanized, because the inode
> currently being processed has a new path that matches that directory's
> path, make sure we evict the name of the directory from the name cache.
> This is because there might be descendent inodes (either directories or
> regular files) that will be orphanized later too, and therefore the
> orphan name of the ancestor must be used, otherwise we send issue rename
> operations with a wrong path in the send stream.
> 
> Reproducer:
> 
>   $ mkfs.btrfs -f /dev/sdb
>   $ mount /dev/sdb /mnt
> 
>   $ mkdir -p /mnt/data/n1/n2/p1/p2
>   $ mkdir /mnt/data/n4
>   $ mkdir -p /mnt/data/p1/p2
> 
>   $ btrfs subvolume snapshot -r /mnt /mnt/snap1
> 
>   $ mv /mnt/data/p1/p2 /mnt/data
>   $ mv /mnt/data/n1/n2/p1/p2 /mnt/data/p1
>   $ mv /mnt/data/p2 /mnt/data/n1/n2/p1
>   $ mv /mnt/data/n1/n2 /mnt/data/p1
>   $ mv /mnt/data/p1 /mnt/data/n4
>   $ mv /mnt/data/n4/p1/n2/p1 /mnt/data
> 
>   $ btrfs subvolume snapshot -r /mnt /mnt/snap2
> 
>   $ btrfs send /mnt/snap1 -f /tmp/1.send
>   $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/2.send
> 
>   $ mkfs.btrfs -f /dev/sdc
>   $ mount /dev/sdc /mnt2
>   $ btrfs receive /mnt2 -f /tmp/1.send
>   $ btrfs receive /mnt2 -f /tmp/2.send
>   ERROR: rename data/p1/p2 -> data/n4/p1/p2 failed. no such file or directory
> 
> Directories data/p1 (inode 263) and data/p1/p2 (inode 264) in the parent
> snapshot are both orphanized during the incremental send, and as soon as
> data/p1 is orphanized, we must make sure that when orphanizing data/p1/p2
> we use a source path of o263-6-o/p2 for the rename operation instead of
> the old path data/p1/p2 (the one before the orphanization of inode 263).
> 
> A test case for xfstests follows soon.
> 
> Reported-by: Robbie Ko <robbieko@synology.com>
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

Tested-by: David Sterba <dsterba@suse.cz>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-04-02 16:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-12 15:16 [PATCH] Btrfs: incremental send, clear name from cache after orphanization Filipe Manana
  -- strict thread matches above, loose matches on Subject: below --
2015-03-08 17:48 Filipe Manana
2015-04-02 16:21 ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).