From: BingJing Chang <[email protected]>
There is a bug sending link commands for existing file paths. When we're
processing an inode, we go over all references. All the new file paths are
added to the "new_refs" list. And all the deleted file paths are added to
the "deleted_refs" list. In the end, when we finish processing the inode,
we iterate over all the items in the "new_refs" list and send link commands
for those file paths. After that, we go over all the items in the
"deleted_refs" list and send unlink commands for them. If there are
duplicated file paths in both lists, we will try to create them before we
remove them. Then the receiver gets an -EEXIST error when trying the link
operations.
BingJing Chang (2):
btrfs: send: introduce recorded_ref_alloc and recorded_ref_free
btrfs: send: fix sending link commands for existing file paths
fs/btrfs/send.c | 195 ++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 181 insertions(+), 14 deletions(-)
--
2.37.0
From: BingJing Chang <[email protected]>
Introduce wrappers to allocate and free struct recorded_ref*.
Reviewed-by: Robbie Ko <[email protected]>
Signed-off-by: BingJing Chang <[email protected]>
---
fs/btrfs/send.c | 34 ++++++++++++++++++++++++----------
1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index fa56890ff81f..420a86720aa2 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -2749,6 +2749,26 @@ struct recorded_ref {
int name_len;
};
+static struct recorded_ref *recorded_ref_alloc(void)
+{
+ struct recorded_ref *ref;
+
+ ref = kzalloc(sizeof(*ref), GFP_KERNEL);
+ if (!ref)
+ return NULL;
+ INIT_LIST_HEAD(&ref->list);
+ return ref;
+}
+
+static void recorded_ref_free(struct recorded_ref *ref)
+{
+ if (!ref)
+ return;
+ list_del(&ref->list);
+ fs_path_free(ref->full_path);
+ kfree(ref);
+}
+
static void set_ref_path(struct recorded_ref *ref, struct fs_path *path)
{
ref->full_path = path;
@@ -2766,7 +2786,7 @@ static int __record_ref(struct list_head *head, u64 dir,
{
struct recorded_ref *ref;
- ref = kmalloc(sizeof(*ref), GFP_KERNEL);
+ ref = recorded_ref_alloc();
if (!ref)
return -ENOMEM;
@@ -2781,14 +2801,12 @@ static int dup_ref(struct recorded_ref *ref, struct list_head *list)
{
struct recorded_ref *new;
- new = kmalloc(sizeof(*ref), GFP_KERNEL);
+ new = recorded_ref_alloc();
if (!new)
return -ENOMEM;
new->dir = ref->dir;
new->dir_gen = ref->dir_gen;
- new->full_path = NULL;
- INIT_LIST_HEAD(&new->list);
list_add_tail(&new->list, list);
return 0;
}
@@ -2799,9 +2817,7 @@ static void __free_recorded_refs(struct list_head *head)
while (!list_empty(head)) {
cur = list_entry(head->next, struct recorded_ref, list);
- fs_path_free(cur->full_path);
- list_del(&cur->list);
- kfree(cur);
+ recorded_ref_free(cur);
}
}
@@ -6216,9 +6232,7 @@ static int btrfs_unlink_all_paths(struct send_ctx *sctx)
ret = send_unlink(sctx, ref->full_path);
if (ret < 0)
goto out;
- fs_path_free(ref->full_path);
- list_del(&ref->list);
- kfree(ref);
+ recorded_ref_free(ref);
}
ret = 0;
out:
--
2.37.0
On Tue, Jul 12, 2022 at 09:36:30AM +0800, bingjingc wrote:
> From: BingJing Chang <[email protected]>
>
> There is a bug sending link commands for existing file paths. When we're
> processing an inode, we go over all references. All the new file paths are
> added to the "new_refs" list. And all the deleted file paths are added to
> the "deleted_refs" list. In the end, when we finish processing the inode,
> we iterate over all the items in the "new_refs" list and send link commands
> for those file paths. After that, we go over all the items in the
> "deleted_refs" list and send unlink commands for them. If there are
> duplicated file paths in both lists, we will try to create them before we
> remove them. Then the receiver gets an -EEXIST error when trying the link
> operations.
>
> BingJing Chang (2):
> btrfs: send: introduce recorded_ref_alloc and recorded_ref_free
> btrfs: send: fix sending link commands for existing file paths
>
> fs/btrfs/send.c | 195 ++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 181 insertions(+), 14 deletions(-)
Looks good now, thanks.
Reviewed-by: Filipe Manana <[email protected]>
Also, are you planning on submitting a test case for fstests too?
>
> --
> 2.37.0
>
Filipe Manana <[email protected]>於 2022年7月12日 週二,下午10:52寫道:
>
> On Tue, Jul 12, 2022 at 09:36:30AM +0800, bingjingc wrote:
> > From: BingJing Chang <[email protected]>
> >
> > There is a bug sending link commands for existing file paths. When we're
> > processing an inode, we go over all references. All the new file paths are
> > added to the "new_refs" list. And all the deleted file paths are added to
> > the "deleted_refs" list. In the end, when we finish processing the inode,
> > we iterate over all the items in the "new_refs" list and send link commands
> > for those file paths. After that, we go over all the items in the
> > "deleted_refs" list and send unlink commands for them. If there are
> > duplicated file paths in both lists, we will try to create them before we
> > remove them. Then the receiver gets an -EEXIST error when trying the link
> > operations.
> >
> > BingJing Chang (2):
> > btrfs: send: introduce recorded_ref_alloc and recorded_ref_free
> > btrfs: send: fix sending link commands for existing file paths
> >
> > fs/btrfs/send.c | 195 ++++++++++++++++++++++++++++++++++++++++++++----
> > 1 file changed, 181 insertions(+), 14 deletions(-)
>
> Looks good now, thanks.
>
> Reviewed-by: Filipe Manana <[email protected]>
>
> Also, are you planning on submitting a test case for fstests too?
Sorry for my late reply. I will try to add a test case to fstests,
thanks for reminding me.
>
> >
> > --
> > 2.37.0
> >