* [PATCH v3 00/10] undelete subvolume offline version
@ 2018-05-07 3:10 Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 01/10] btrfs-progs: copy btrfs_del_orphan_item from kernel Lu Fengqi
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
This patchset will add undelete-subvol subcommand for btrfs rescue.
Patchset can be fetched from github:
https://github.com/littleroad/btrfs-progs.git undelete
v2->v3: fixed some issues pointed out by Qu.
v1->v2: add -s option to allow user specify the subvolume which will be
recovered.
The first patch are not modified.
For the rest, please see the changelog in the patches.
Lu Fengqi (10):
btrfs-progs: copy btrfs_del_orphan_item from kernel
btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol
btrfs-progs: use btrfs_find_free_dir_index to find free inode index
btrfs-progs: undelete-subvol: introduce is_subvol_intact
btrfs-progs: undelete-subvol: introduce recover_dead_root
btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound
btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols
btrfs-progs: undelete-subvol: add undelete-subvol subcommand
btrfs-progs: tests: add testcase for undelete-subvol
btrfs-progs: undelete-subvol: update completion and documentation
Documentation/btrfs-rescue.asciidoc | 12 +
Makefile | 3 +-
btrfs-completion | 2 +-
cmds-rescue.c | 69 ++++++
convert/main.c | 59 ++++-
ctree.h | 8 +-
inode.c | 119 +++++----
.../031-undelete-subvol/intact_subvolume.img | Bin 0 -> 4096 bytes
.../subvolume_in_drop_progress.raw.xz | Bin 0 -> 23452 bytes
tests/misc-tests/031-undelete-subvol/test.sh | 38 +++
undelete-subvol.c | 227 ++++++++++++++++++
undelete-subvol.h | 11 +
12 files changed, 501 insertions(+), 47 deletions(-)
create mode 100644 tests/misc-tests/031-undelete-subvol/intact_subvolume.img
create mode 100644 tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
create mode 100755 tests/misc-tests/031-undelete-subvol/test.sh
create mode 100644 undelete-subvol.c
create mode 100644 undelete-subvol.h
--
2.17.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 01/10] btrfs-progs: copy btrfs_del_orphan_item from kernel
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 02/10] btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol Lu Fengqi
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
Add btrfs_del_orphan_item for the later subvolume undelete.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
ctree.h | 2 ++
inode.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/ctree.h b/ctree.h
index 1fef37c93485..46a1dbfd2f27 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2796,6 +2796,8 @@ int btrfs_unlink(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_path *path,
u64 ino);
+int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, u64 offset);
int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
char *name, int namelen, u64 parent_ino, u64 *ino, int mode);
struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, const char *base,
diff --git a/inode.c b/inode.c
index 2398bca4a109..8d0812c7cf50 100644
--- a/inode.c
+++ b/inode.c
@@ -262,6 +262,36 @@ int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,
return btrfs_insert_empty_item(trans, root, path, &key, 0);
}
+int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, u64 offset)
+{
+ struct btrfs_path *path;
+ struct btrfs_key key;
+ int ret = 0;
+
+ key.objectid = BTRFS_ORPHAN_OBJECTID;
+ key.type = BTRFS_ORPHAN_ITEM_KEY;
+ key.offset = offset;
+
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+
+ ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
+ if (ret < 0)
+ goto out;
+ if (ret) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ ret = btrfs_del_item(trans, root, path);
+
+out:
+ btrfs_free_path(path);
+ return ret;
+}
+
/*
* Unlink an inode, which will remove its backref and corresponding dir_index/
* dir_item if any of them exists.
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 02/10] btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 01/10] btrfs-progs: copy btrfs_del_orphan_item from kernel Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 03/10] btrfs-progs: use btrfs_find_free_dir_index to find free inode index Lu Fengqi
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The original btrfs_mksubvol is too specific to specify the directory that
the subvolume will link to. Furthermore, in this transaction, we don't only
need to create root_ref/dir-item, but also update the flags of root_item.
Extract a generic btrfs_link_subvol that allow the caller pass a trans
argument for later subvolume undelete. And rename the original
btrfs_mksubvol to link_subvol_for_convert since it is a less generic
btrfs_link_subvol.
No functional changes.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3:
rename the btrfs_mksubvol to link_subvol_for_convert;
remove the redundant parameter convert from link_subvol_for_convert;
rename convert to resolve_conflict in btrfs_link_subvol;
set root refs to 1 in btrfs_link_subvol.
convert/main.c | 59 ++++++++++++++++++++++++++++++++++++++++++--
ctree.h | 5 ++--
inode.c | 66 ++++++++++++++++++++++++++++++++------------------
3 files changed, 103 insertions(+), 27 deletions(-)
diff --git a/convert/main.c b/convert/main.c
index 80f3bed84c84..b092e25bccbb 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -1002,6 +1002,61 @@ err:
return ret;
}
+/*
+ * Link the subvolume specified by @root_objectid to the root_dir of @root.
+ *
+ * @root the root of the file tree which the subvolume will
+ * be linked to.
+ * @subvol_name the name of the subvolume which will be named.
+ * @root_objectid specify the subvolume which will be linked.
+ *
+ * Return the root of the subvolume if success, otherwise return NULL.
+ */
+static struct btrfs_root *link_subvol_for_convert(struct btrfs_root *root,
+ const char *subvol_name,
+ u64 root_objectid)
+{
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *subvol_root = NULL;
+ struct btrfs_key key;
+ u64 dirid = btrfs_root_dirid(&root->root_item);
+ int ret;
+
+ /*
+ * 2 for dir's dir_index and dir_item for the subvolume
+ * 2 for the subvolume's root_ref and root_backref
+ */
+ trans = btrfs_start_transaction(root, 4);
+ if (IS_ERR(trans)) {
+ error("unable to start transaction");
+ goto fail;
+ }
+
+ ret = btrfs_link_subvol(trans, root, subvol_name, root_objectid, dirid,
+ true);
+ if (ret) {
+ error("unable to link subvolume %s", subvol_name);
+ goto fail;
+ }
+
+ ret = btrfs_commit_transaction(trans, root);
+ if (ret) {
+ error("transaction commit failed: %d", ret);
+ goto fail;
+ }
+
+ key.objectid = root_objectid;
+ key.offset = (u64)-1;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+
+ subvol_root = btrfs_read_fs_root(root->fs_info, &key);
+ if (!subvol_root)
+ error("unable to link subvolume %s", subvol_name);
+
+fail:
+ return subvol_root;
+}
+
/*
* Migrate super block to its default position and zero 0 ~ 16k
*/
@@ -1194,8 +1249,8 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
task_deinit(ctx.info);
}
- image_root = btrfs_mksubvol(root, subvol_name,
- CONV_IMAGE_SUBVOL_OBJECTID, true);
+ image_root = link_subvol_for_convert(root, subvol_name,
+ CONV_IMAGE_SUBVOL_OBJECTID);
if (!image_root) {
error("unable to link subvolume %s", subvol_name);
goto fail;
diff --git a/ctree.h b/ctree.h
index 46a1dbfd2f27..2ac1eb532986 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2800,8 +2800,9 @@ int btrfs_del_orphan_item(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 offset);
int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
char *name, int namelen, u64 parent_ino, u64 *ino, int mode);
-struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, const char *base,
- u64 root_objectid, bool convert);
+int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+ const char *base, u64 root_objectid, u64 dirid,
+ bool resolve_conflict);
/* file.c */
int btrfs_get_extent(struct btrfs_trans_handle *trans,
diff --git a/inode.c b/inode.c
index 8d0812c7cf50..f9b72533f3a9 100644
--- a/inode.c
+++ b/inode.c
@@ -606,20 +606,31 @@ out:
return ret;
}
-struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
- const char *base, u64 root_objectid,
- bool convert)
+/*
+ * Link the subvolume specified by @root_objectid to the directory specified by
+ * @dirid on the file tree specified by @root.
+ *
+ * @root the root of the file tree where the directory on.
+ * @base the name of the subvolume which will be linked.
+ * @root_objectid specify the subvolume which will be linked.
+ * @dirid specify the directory which the subvolume will be
+ * linked to.
+ * @resolve_conflict the flag to determine whether to try to resolve
+ * the name conflict.
+ */
+int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+ const char *base, u64 root_objectid, u64 dirid,
+ bool resolve_conflict)
{
- struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_root *tree_root = fs_info->tree_root;
- struct btrfs_root *new_root = NULL;
struct btrfs_path path;
struct btrfs_inode_item *inode_item;
+ struct btrfs_root_item root_item;
struct extent_buffer *leaf;
struct btrfs_key key;
- u64 dirid = btrfs_root_dirid(&root->root_item);
u64 index = 2;
+ u64 offset;
char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
int len;
int i;
@@ -627,8 +638,9 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
len = strlen(base);
if (len == 0 || len > BTRFS_NAME_LEN)
- return NULL;
+ return -EINVAL;
+ /* find the free dir_index */
btrfs_init_path(&path);
key.objectid = dirid;
key.type = BTRFS_DIR_INDEX_KEY;
@@ -649,12 +661,7 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
}
btrfs_release_path(&path);
- trans = btrfs_start_transaction(root, 1);
- if (IS_ERR(trans)) {
- error("unable to start transaction");
- goto fail;
- }
-
+ /* add the dir_item/dir_index */
key.objectid = dirid;
key.offset = 0;
key.type = BTRFS_INODE_ITEM_KEY;
@@ -674,7 +681,8 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
key.type = BTRFS_ROOT_ITEM_KEY;
memcpy(buf, base, len);
- if (convert) {
+ if (resolve_conflict) {
+ /* try to resolve name conflict by adding the number suffix */
for (i = 0; i < 1024; i++) {
ret = btrfs_insert_dir_item(trans, root, buf, len,
dirid, &key, BTRFS_FT_DIR, index);
@@ -719,18 +727,30 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root,
goto fail;
}
- ret = btrfs_commit_transaction(trans, root);
+
+ /* set root refs of the subvolume to 1 */
+ key.objectid = root_objectid;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = 0;
+
+ ret = btrfs_search_slot(trans, tree_root, &key, &path, 0, 0);
if (ret) {
- error("transaction commit failed: %d", ret);
+ error("couldn't find ROOT_ITEM for %llu failed: %d",
+ root_objectid, ret);
goto fail;
}
- new_root = btrfs_read_fs_root(fs_info, &key);
- if (IS_ERR(new_root)) {
- error("unable to fs read root: %lu", PTR_ERR(new_root));
- new_root = NULL;
- }
+ leaf = path.nodes[0];
+
+ offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
+ read_extent_buffer(leaf, &root_item, offset, sizeof(root_item));
+
+ btrfs_set_root_refs(&root_item, 1);
+
+ write_extent_buffer(leaf, &root_item, offset, sizeof(root_item));
+ btrfs_mark_buffer_dirty(leaf);
+
fail:
- btrfs_init_path(&path);
- return new_root;
+ btrfs_release_path(&path);
+ return ret;
}
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 03/10] btrfs-progs: use btrfs_find_free_dir_index to find free inode index
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 01/10] btrfs-progs: copy btrfs_del_orphan_item from kernel Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 02/10] btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 04/10] btrfs-progs: undelete-subvol: introduce is_subvol_intact Lu Fengqi
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
Since we have an existing function to find free inode index, we can
reuse it here.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
---
V3: add Reviewed-by from Qu Wenruo.
inode.c | 27 +++++++--------------------
1 file changed, 7 insertions(+), 20 deletions(-)
diff --git a/inode.c b/inode.c
index f9b72533f3a9..03b8be63eb0a 100644
--- a/inode.c
+++ b/inode.c
@@ -629,7 +629,7 @@ int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_root_item root_item;
struct extent_buffer *leaf;
struct btrfs_key key;
- u64 index = 2;
+ u64 index;
u64 offset;
char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
int len;
@@ -640,28 +640,15 @@ int btrfs_link_subvol(struct btrfs_trans_handle *trans, struct btrfs_root *root,
if (len == 0 || len > BTRFS_NAME_LEN)
return -EINVAL;
- /* find the free dir_index */
- btrfs_init_path(&path);
- key.objectid = dirid;
- key.type = BTRFS_DIR_INDEX_KEY;
- key.offset = (u64)-1;
-
- ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
- if (ret <= 0) {
- error("search for DIR_INDEX dirid %llu failed: %d",
- (unsigned long long)dirid, ret);
+ /* add the dir_item/dir_index */
+ ret = btrfs_find_free_dir_index(root, dirid, &index);
+ if (ret < 0) {
+ error("unable to find free dir index dirid %llu failed: %d",
+ (unsigned long long)dirid, ret);
goto fail;
}
- if (path.slots[0] > 0) {
- path.slots[0]--;
- btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
- if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY)
- index = key.offset + 1;
- }
- btrfs_release_path(&path);
-
- /* add the dir_item/dir_index */
+ btrfs_init_path(&path);
key.objectid = dirid;
key.offset = 0;
key.type = BTRFS_INODE_ITEM_KEY;
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 04/10] btrfs-progs: undelete-subvol: introduce is_subvol_intact
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (2 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 03/10] btrfs-progs: use btrfs_find_free_dir_index to find free inode index Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 05/10] btrfs-progs: undelete-subvol: introduce recover_dead_root Lu Fengqi
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The function is used to determine whether the subvolume is intact.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3:
add SPDX-License-Identifier;
pass btrfs_fs_info instead of btrfs_root;
use btrfs_read_fs_root instead of manually search;
remove empty header file.
Makefile | 3 ++-
undelete-subvol.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 undelete-subvol.c
diff --git a/Makefile b/Makefile
index cbd855336b2f..6a425e3a65dd 100644
--- a/Makefile
+++ b/Makefile
@@ -116,7 +116,8 @@ objects = ctree.o disk-io.o kernel-lib/radix-tree.o extent-tree.o print-tree.o \
qgroup.o free-space-cache.o kernel-lib/list_sort.o props.o \
kernel-shared/ulist.o qgroup-verify.o backref.o string-table.o task-utils.o \
inode.o file.o find-root.o free-space-tree.o help.o send-dump.o \
- fsfeatures.o kernel-lib/tables.o kernel-lib/raid56.o transaction.o
+ fsfeatures.o kernel-lib/tables.o kernel-lib/raid56.o transaction.o \
+ undelete-subvol.o
cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
cmds-quota.o cmds-qgroup.o cmds-replace.o check/main.o \
diff --git a/undelete-subvol.c b/undelete-subvol.c
new file mode 100644
index 000000000000..26e156092011
--- /dev/null
+++ b/undelete-subvol.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Fujitsu. All rights reserved.
+ */
+
+#include "ctree.h"
+#include "disk-io.h"
+
+/*
+ * Determines whether the subvolume is intact, according to the drop_progress
+ * of the root item specified by @subvol_id.
+ *
+ * Return true if the subvolume is intact, otherwise return false.
+ */
+static bool is_subvol_intact(struct btrfs_fs_info *fs_info, u64 subvol_id)
+{
+ struct btrfs_key key;
+ struct btrfs_root *root;
+
+ key.objectid = subvol_id;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = -1;
+
+ root = btrfs_read_fs_root(fs_info, &key);
+ if (IS_ERR(root))
+ return false;
+
+ /* the subvolume is intact if the objectid of drop_progress == 0 */
+ return !btrfs_disk_key_objectid(&root->root_item.drop_progress);
+}
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 05/10] btrfs-progs: undelete-subvol: introduce recover_dead_root
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (3 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 04/10] btrfs-progs: undelete-subvol: introduce is_subvol_intact Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 06/10] btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound Lu Fengqi
` (5 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The function will find the root_item specified by the subvol_id
and clear the BTRFS_ROOT_SUBVOL_DEAD flag.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3:
remove btrfs_root argument;
don't modify root_refs.
ctree.h | 1 +
undelete-subvol.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/ctree.h b/ctree.h
index 2ac1eb532986..6e2046145f7c 100644
--- a/ctree.h
+++ b/ctree.h
@@ -186,6 +186,7 @@ static int btrfs_csum_sizes[] = { 4 };
#define BTRFS_FT_MAX 9
#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0)
+#define BTRFS_ROOT_SUBVOL_DEAD (1ULL << 48)
/*
* the key defines the order in the tree, and so it also defines (optimal)
diff --git a/undelete-subvol.c b/undelete-subvol.c
index 26e156092011..6d3ef19977d6 100644
--- a/undelete-subvol.c
+++ b/undelete-subvol.c
@@ -5,6 +5,8 @@
#include "ctree.h"
#include "disk-io.h"
+#include "transaction.h"
+#include "messages.h"
/*
* Determines whether the subvolume is intact, according to the drop_progress
@@ -28,3 +30,52 @@ static bool is_subvol_intact(struct btrfs_fs_info *fs_info, u64 subvol_id)
/* the subvolume is intact if the objectid of drop_progress == 0 */
return !btrfs_disk_key_objectid(&root->root_item.drop_progress);
}
+
+/*
+ * Clear BTRFS_ROOT_SUBVOL_DEAD flag.
+ *
+ * @subvol_id specify the root_item which will be modified.
+ *
+ * Return 0 if no error occurred.
+ */
+static int recover_dead_root(struct btrfs_trans_handle *trans, u64 subvol_id)
+{
+ struct btrfs_fs_info *fs_info = trans->fs_info;
+ struct btrfs_root *root = fs_info->tree_root;
+ struct btrfs_key key;
+ struct btrfs_path path;
+ struct extent_buffer *leaf;
+ struct btrfs_root_item root_item;
+ u64 root_flags;
+ u64 offset;
+ int ret;
+
+ key.objectid = subvol_id;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = 0;
+
+ btrfs_init_path(&path);
+ ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
+ if (ret) {
+ error("couldn't find ROOT_ITEM for %llu failed: %d",
+ subvol_id, ret);
+ goto out;
+ }
+
+ leaf = path.nodes[0];
+
+ offset = btrfs_item_ptr_offset(leaf, path.slots[0]);
+ read_extent_buffer(leaf, &root_item, offset, sizeof(root_item));
+
+ /* Clear BTRFS_ROOT_SUBVOL_DEAD */
+ root_flags = btrfs_root_flags(&root_item);
+ btrfs_set_root_flags(&root_item,
+ root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
+
+ write_extent_buffer(leaf, &root_item, offset, sizeof(root_item));
+ btrfs_mark_buffer_dirty(leaf);
+
+out:
+ btrfs_release_path(&path);
+ return ret;
+}
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 06/10] btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (4 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 05/10] btrfs-progs: undelete-subvol: introduce recover_dead_root Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 07/10] btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols Lu Fengqi
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The function will create lost+found directory, link the deleted
subvolume specified by the subvol_id to the directory, update the
information of root_item and cleanup the associated orphan item.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
---
V3:
pass btrfs_fs_info instead of btrfs_root;
add Reviewed-by from Qu Wenruo.
undelete-subvol.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/undelete-subvol.c b/undelete-subvol.c
index 6d3ef19977d6..9851998ec3df 100644
--- a/undelete-subvol.c
+++ b/undelete-subvol.c
@@ -79,3 +79,79 @@ out:
btrfs_release_path(&path);
return ret;
}
+
+/*
+ * Recover a subvolume specified by subvol_id, and link it to the lost+found
+ * directory.
+ *
+ * @subvol_id: specify the subvolume which will be linked, and also be the part
+ * of the subvolume name.
+ *
+ * Return 0 if no error occurred.
+ */
+static int link_subvol_to_lostfound(struct btrfs_fs_info *fs_info,
+ u64 subvol_id)
+{
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *root = fs_info->tree_root;
+ struct btrfs_root *fs_root = fs_info->fs_root;
+ char buf[BTRFS_NAME_LEN + 1] = {0}; /* 1 for snprintf null */
+ char *dir_name = "lost+found";
+ u64 lost_found_ino = 0;
+ u32 mode = 0700;
+ int ret;
+
+ /*
+ * For link subvolume to lost+found,
+ * 2 for parent(256)'s dir_index and dir_item
+ * 2 for lost+found dir's inode_item and inode_ref
+ * 2 for lost+found dir's dir_index and dir_item for the subvolume
+ * 2 for the subvolume's root_ref and root_backref
+ */
+ trans = btrfs_start_transaction(fs_root, 8);
+ if (IS_ERR(trans)) {
+ error("unable to start transaction");
+ ret = PTR_ERR(trans);
+ goto out;
+ }
+
+ /* Create lost+found directory */
+ ret = btrfs_mkdir(trans, fs_root, dir_name, strlen(dir_name),
+ BTRFS_FIRST_FREE_OBJECTID, &lost_found_ino,
+ mode);
+ if (ret < 0) {
+ error("failed to create '%s' dir: %d", dir_name, ret);
+ goto out;
+ }
+
+ /* Link the subvolume to lost+found directory */
+ snprintf(buf, BTRFS_NAME_LEN + 1, "sub%llu", subvol_id);
+ ret = btrfs_link_subvol(trans, fs_root, buf, subvol_id, lost_found_ino,
+ false);
+ if (ret) {
+ error("failed to link the subvol %llu: %d", subvol_id, ret);
+ goto out;
+ }
+
+ /* Clear root flags BTRFS_ROOT_SUBVOL_DEAD */
+ ret = recover_dead_root(trans, subvol_id);
+ if (ret)
+ goto out;
+
+ /* Delete the orphan item after undeletion is completed. */
+ ret = btrfs_del_orphan_item(trans, root, subvol_id);
+ if (ret) {
+ error("failed to delete the orphan_item for %llu: %d",
+ subvol_id, ret);
+ goto out;
+ }
+
+ ret = btrfs_commit_transaction(trans, fs_root);
+ if (ret) {
+ error("transaction commit failed: %d", ret);
+ goto out;
+ }
+
+out:
+ return ret;
+}
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 07/10] btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (5 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 06/10] btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 08/10] btrfs-progs: undelete-subvol: add undelete-subvol subcommand Lu Fengqi
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The function default will traverse the all orphan items on the tree root,
and recover the all intact subvolumes. If subvol_id is specified, then only
the corresponding subvolume will be recovered.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3:
pass btrfs_fs_info instead of btrfs_root;
rename btrfs_undelete_intact_subvols to btrfs_undelete_subvols;
use btrfs_previous_item to iterate.
V2: add subvol_id argument to specify subvol_id instead of recovering
all subvolumes.
undelete-subvol.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
undelete-subvol.h | 11 ++++++++
2 files changed, 81 insertions(+)
create mode 100644 undelete-subvol.h
diff --git a/undelete-subvol.c b/undelete-subvol.c
index 9851998ec3df..6b9803d4c590 100644
--- a/undelete-subvol.c
+++ b/undelete-subvol.c
@@ -7,6 +7,7 @@
#include "disk-io.h"
#include "transaction.h"
#include "messages.h"
+#include "undelete-subvol.h"
/*
* Determines whether the subvolume is intact, according to the drop_progress
@@ -155,3 +156,72 @@ static int link_subvol_to_lostfound(struct btrfs_fs_info *fs_info,
out:
return ret;
}
+
+/*
+ * Traverse all orphan items on the root tree, restore them to the lost+found
+ * directory if the corresponding subvolumes are still intact left on the disk.
+ *
+ * @subvol_id if not set to 0, skip other subvolumes and only recover the
+ * subvolume specified by @subvol_id.
+ *
+ * Return 0 if no error occurred even if no subvolume was recovered.
+ */
+int btrfs_undelete_subvols(struct btrfs_fs_info *fs_info, u64 subvol_id)
+{
+ struct btrfs_root *root = fs_info->tree_root;
+ struct btrfs_key key;
+ struct btrfs_path path;
+ u64 found_count = 0;
+ u64 recovered_count = 0;
+ int ret = 0;
+
+ key.objectid = BTRFS_ORPHAN_OBJECTID;
+ key.type = BTRFS_ORPHAN_ITEM_KEY;
+ key.offset = subvol_id ? subvol_id + 1 : (u64)-1;
+
+ btrfs_init_path(&path);
+ while (subvol_id != key.offset) {
+ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+ if (ret < 0) {
+ error("search ORPHAN_ITEM for %llu failed.\n",
+ key.offset);
+ btrfs_release_path(&path);
+ break;
+ }
+
+ ret = btrfs_previous_item(root, &path, BTRFS_ORPHAN_OBJECTID,
+ BTRFS_ORPHAN_ITEM_KEY);
+ if (ret) {
+ btrfs_release_path(&path);
+ break;
+ }
+
+ btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
+ btrfs_release_path(&path);
+
+ /* If subvol_id is non-zero, skip other deleted subvolume. */
+ if (subvol_id && subvol_id != key.offset) {
+ ret = -ENOENT;
+ break;
+ }
+
+ if (!is_subvol_intact(fs_info, key.offset))
+ continue;
+
+ /* Here we can confirm there is an intact subvolume. */
+ found_count++;
+ ret = link_subvol_to_lostfound(fs_info, key.offset);
+ if (ret == 0) {
+ recovered_count++;
+ printf(
+ "Recovered subvolume %llu to lost+found successfully.\n",
+ key.offset);
+ }
+
+ }
+
+ printf("Found %llu deleted subvols left intact\n", found_count);
+ printf("Recovered %llu deleted subvols\n", found_count);
+
+ return ret;
+}
diff --git a/undelete-subvol.h b/undelete-subvol.h
new file mode 100644
index 000000000000..a98d8ab90cea
--- /dev/null
+++ b/undelete-subvol.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Fujitsu. All rights reserved.
+ */
+
+#ifndef __BTRFS_UNDELETE_SUBVOLUME_H__
+#define __BTRFS_UNDELETE_SUBVOLUME_H__
+
+int btrfs_undelete_subvols(struct btrfs_fs_info *fs_info, u64 subvol_id);
+
+#endif
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 08/10] btrfs-progs: undelete-subvol: add undelete-subvol subcommand
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (6 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 07/10] btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 09/10] btrfs-progs: tests: add testcase for undelete-subvol Lu Fengqi
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
Add the undelete-subvol subcommand for btrfs rescue. This subcommand is
used to recover deleted subvolume left intact on the device.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3: remove OPEN_CTREE_PARTIAL flag.
V2: add -s option to specify subvol_id.
cmds-rescue.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
diff --git a/cmds-rescue.c b/cmds-rescue.c
index c40088ad374e..536d6b37ac50 100644
--- a/cmds-rescue.c
+++ b/cmds-rescue.c
@@ -25,6 +25,7 @@
#include "disk-io.h"
#include "commands.h"
#include "utils.h"
+#include "undelete-subvol.h"
#include "help.h"
static const char * const rescue_cmd_group_usage[] = {
@@ -248,6 +249,72 @@ out:
return !!ret;
}
+static const char * const cmd_rescue_undelete_subvol_usage[] = {
+ "btrfs rescue undelete-subvol [-s <subvolid>] <device>",
+ "Undelete deleted subvolume",
+ "All deleted subvolume that still left intact on the device will be",
+ "recovered. If -s <subvolid> option is given, then just recover the",
+ "subvolume which specified by <subvolid>.",
+ "",
+ "-s <subvolid> specify the subvolume which will be recovered.",
+ NULL
+};
+
+static int cmd_rescue_undelete_subvol(int argc, char **argv)
+{
+ struct btrfs_fs_info *fs_info;
+ char *devname;
+ u64 subvol_id = 0;
+ int ret;
+
+ while (1) {
+ int c = getopt(argc, argv, "s:");
+
+ if (c < 0)
+ break;
+ switch (c) {
+ case 's':
+ subvol_id = arg_strtou64(optarg);
+ if (!is_fstree(subvol_id)) {
+ error("%llu is not a valid subvolume id",
+ subvol_id);
+ ret = -EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ usage(cmd_rescue_undelete_subvol_usage);
+ }
+ }
+
+ if (check_argc_exact(argc - optind, 1))
+ usage(cmd_rescue_undelete_subvol_usage);
+
+ devname = argv[optind];
+ ret = check_mounted(devname);
+ if (ret < 0) {
+ error("could not check mount status: %s", strerror(-ret));
+ goto out;
+ } else if (ret) {
+ error("%s is currently mounted", devname);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ fs_info = open_ctree_fs_info(devname, 0, 0, 0, OPEN_CTREE_WRITES);
+ if (!fs_info) {
+ error("could not open btrfs");
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = btrfs_undelete_subvols(fs_info, subvol_id);
+
+ close_ctree(fs_info->tree_root);
+out:
+ return ret;
+}
+
static const char rescue_cmd_group_info[] =
"toolbox for specific rescue operations";
@@ -260,6 +327,8 @@ const struct cmd_group rescue_cmd_group = {
{ "zero-log", cmd_rescue_zero_log, cmd_rescue_zero_log_usage, NULL, 0},
{ "fix-device-size", cmd_rescue_fix_device_size,
cmd_rescue_fix_device_size_usage, NULL, 0},
+ { "undelete-subvol", cmd_rescue_undelete_subvol,
+ cmd_rescue_undelete_subvol_usage, NULL, 0},
NULL_CMD_STRUCT
}
};
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 09/10] btrfs-progs: tests: add testcase for undelete-subvol
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (7 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 08/10] btrfs-progs: undelete-subvol: add undelete-subvol subcommand Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-05-08 5:58 ` [PATCH v3.1 " Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 10/10] btrfs-progs: undelete-subvol: update completion and documentation Lu Fengqi
2018-09-11 11:44 ` [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
10 siblings, 1 reply; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
The testcase checks the functionality of "btrfs rescue undelete-subvol",
including recovering an intact subvolume, and handling correctly
incomplete subvolume.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3:
rename testcase to 031-undelete-subvol;
rename images and add image description to test.sh.
V2: add shell quoting to test script.
.../031-undelete-subvol/intact_subvolume.img | Bin 0 -> 4096 bytes
.../subvolume_in_drop_progress.raw.xz | Bin 0 -> 23452 bytes
tests/misc-tests/031-undelete-subvol/test.sh | 38 ++++++++++++++++++
3 files changed, 38 insertions(+)
create mode 100644 tests/misc-tests/031-undelete-subvol/intact_subvolume.img
create mode 100644 tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
create mode 100755 tests/misc-tests/031-undelete-subvol/test.sh
diff --git a/tests/misc-tests/031-undelete-subvol/intact_subvolume.img b/tests/misc-tests/031-undelete-subvol/intact_subvolume.img
new file mode 100644
index 0000000000000000000000000000000000000000..9168a8e33fbbb14f9ea78514721a52191b94d1a0
GIT binary patch
literal 4096
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
ZeM(;pZJdD++rKZroo*A@Ch+ek@Fx_v;e7xA
literal 0
HcmV?d00001
diff --git a/tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz b/tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
new file mode 100644
index 0000000000000000000000000000000000000000..3db2c80e61fa9bb99db374509dbb95910965d467
GIT binary patch
literal 23452
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
F{{akY3)=ty
literal 0
HcmV?d00001
diff --git a/tests/misc-tests/031-undelete-subvol/test.sh b/tests/misc-tests/031-undelete-subvol/test.sh
new file mode 100755
index 000000000000..c84eb310baef
--- /dev/null
+++ b/tests/misc-tests/031-undelete-subvol/test.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Test undelete-subvol can recover the intact subvolume, and can skip the
+# incomplete subvolume.
+#
+# For intact_subvolume.img it has 1 orphan root and it can be recovered.
+# For subvolume_in_drop_progress.raw.xz it has 2 orphan roots while only
+# one can be recovered.
+
+source "$TOP/tests/common"
+
+check_prereq btrfs
+check_prereq btrfs-image
+
+setup_root_helper
+
+check_image()
+{
+ TEST_DEV="$1"
+
+ run_check_stdout "$TOP/btrfs" rescue undelete-subvol "$TEST_DEV" \
+ | grep -q "Recovered 1 deleted subvols" \
+ || _fail "failed to undelete subvol $image" >&2
+
+ run_check "$TOP/btrfs" check "$TEST_DEV"
+
+ # check whether the recovered image can be mounted normally
+ run_check_mount_test_dev
+
+ run_check_stdout $SUDO_HELPER "$TOP/btrfs" subvolume list "$TEST_MNT" \
+ | grep -q "lost+found" \
+ || _fail "failed to find the recovered subvol $image" >&2
+
+ run_check_umount_test_dev "$TEST_MNT"
+
+ rm "$TEST_DEV"
+}
+
+check_all_images
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 10/10] btrfs-progs: undelete-subvol: update completion and documentation
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (8 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 09/10] btrfs-progs: tests: add testcase for undelete-subvol Lu Fengqi
@ 2018-05-07 3:10 ` Lu Fengqi
2018-09-11 11:44 ` [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-07 3:10 UTC (permalink / raw)
To: linux-btrfs
Add undelete-subvol to btrfs-completion, and update btrfs-rescue
documentation to introduce undelete-subvol.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V2: just add -s option documentation.
Documentation/btrfs-rescue.asciidoc | 12 ++++++++++++
btrfs-completion | 2 +-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/Documentation/btrfs-rescue.asciidoc b/Documentation/btrfs-rescue.asciidoc
index f94a0ff2b45e..573a865b1158 100644
--- a/Documentation/btrfs-rescue.asciidoc
+++ b/Documentation/btrfs-rescue.asciidoc
@@ -60,6 +60,18 @@ assume an answer of 'yes' to all questions.
-v::::
verbose mode.
+*undelete-subvol* <device>::
+Undelete deleted subvolumes that still left intact on the device.
++
+This command will create the lost+found directory, and recover all the
+subvolumes to this directory with the name "sub<id>". If -s <subvolid> option
+is given, then just recover the subvolume which specified by <subvolid>.
++
+`Options`
++
+-s::::
+specify the subvolume which will be recovered.
+
*zero-log* <device>::
clear the filesystem log tree
+
diff --git a/btrfs-completion b/btrfs-completion
index ae683f4ecf61..859595155a4b 100644
--- a/btrfs-completion
+++ b/btrfs-completion
@@ -35,7 +35,7 @@ _btrfs()
commands_balance='start pause cancel resume status'
commands_device='scan add delete remove ready stats usage'
commands_scrub='start cancel resume status'
- commands_rescue='chunk-recover super-recover zero-log'
+ commands_rescue='chunk-recover super-recover undelete-subvol zero-log'
commands_inspect_internal='inode-resolve logical-resolve subvolid-resolve rootid min-dev-size dump-tree dump-super tree-stats'
commands_property='get set list'
commands_quota='enable disable rescan'
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3.1 09/10] btrfs-progs: tests: add testcase for undelete-subvol
2018-05-07 3:10 ` [PATCH v3 09/10] btrfs-progs: tests: add testcase for undelete-subvol Lu Fengqi
@ 2018-05-08 5:58 ` Lu Fengqi
0 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-05-08 5:58 UTC (permalink / raw)
To: linux-btrfs
The testcase checks the functionality of "btrfs rescue undelete-subvol",
including recovering an intact subvolume, and handling correctly
incomplete subvolume.
Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
---
V3.1: remove unnecessary check_prereq btrfs-image
V3:
rename testcase to 031-undelete-subvol;
rename images and add image description to test.sh.
V2: add shell quoting to test script.
.../031-undelete-subvol/intact_subvolume.img | Bin 0 -> 4096 bytes
.../subvolume_in_drop_progress.raw.xz | Bin 0 -> 23452 bytes
tests/misc-tests/031-undelete-subvol/test.sh | 37 ++++++++++++++++++
3 files changed, 37 insertions(+)
create mode 100644 tests/misc-tests/031-undelete-subvol/intact_subvolume.img
create mode 100644 tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
create mode 100755 tests/misc-tests/031-undelete-subvol/test.sh
diff --git a/tests/misc-tests/031-undelete-subvol/intact_subvolume.img b/tests/misc-tests/031-undelete-subvol/intact_subvolume.img
new file mode 100644
index 0000000000000000000000000000000000000000..9168a8e33fbbb14f9ea78514721a52191b94d1a0
GIT binary patch
literal 4096
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
ZeM(;pZJdD++rKZroo*A@Ch+ek@Fx_v;e7xA
literal 0
HcmV?d00001
diff --git a/tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz b/tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
new file mode 100644
index 0000000000000000000000000000000000000000..3db2c80e61fa9bb99db374509dbb95910965d467
GIT binary patch
literal 23452
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
F{{akY3)=ty
literal 0
HcmV?d00001
diff --git a/tests/misc-tests/031-undelete-subvol/test.sh b/tests/misc-tests/031-undelete-subvol/test.sh
new file mode 100755
index 000000000000..f5eb0f46da7d
--- /dev/null
+++ b/tests/misc-tests/031-undelete-subvol/test.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+# Test undelete-subvol can recover the intact subvolume, and can skip the
+# incomplete subvolume.
+#
+# For intact_subvolume.img it has 1 orphan root and it can be recovered.
+# For subvolume_in_drop_progress.raw.xz it has 2 orphan roots while only
+# one can be recovered.
+
+source "$TOP/tests/common"
+
+check_prereq btrfs
+
+setup_root_helper
+
+check_image()
+{
+ TEST_DEV="$1"
+
+ run_check_stdout "$TOP/btrfs" rescue undelete-subvol "$TEST_DEV" \
+ | grep -q "Recovered 1 deleted subvols" \
+ || _fail "failed to undelete subvol $image" >&2
+
+ run_check "$TOP/btrfs" check "$TEST_DEV"
+
+ # check whether the recovered image can be mounted normally
+ run_check_mount_test_dev
+
+ run_check_stdout $SUDO_HELPER "$TOP/btrfs" subvolume list "$TEST_MNT" \
+ | grep -q "lost+found" \
+ || _fail "failed to find the recovered subvol $image" >&2
+
+ run_check_umount_test_dev "$TEST_MNT"
+
+ rm "$TEST_DEV"
+}
+
+check_all_images
--
2.17.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 00/10] undelete subvolume offline version
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
` (9 preceding siblings ...)
2018-05-07 3:10 ` [PATCH v3 10/10] btrfs-progs: undelete-subvol: update completion and documentation Lu Fengqi
@ 2018-09-11 11:44 ` Lu Fengqi
10 siblings, 0 replies; 13+ messages in thread
From: Lu Fengqi @ 2018-09-11 11:44 UTC (permalink / raw)
To: linux-btrfs, dsterba
On Mon, May 07, 2018 at 11:10:23AM +0800, Lu Fengqi wrote:
>This patchset will add undelete-subvol subcommand for btrfs rescue.
>
Hi David
Although there are some disagreements about undeleting subvolumes online
implementation, the offline version is considered more acceptable. Would
you like to spend some time talking about your opinions?
--
Thanks,
Lu
>Patchset can be fetched from github:
>https://github.com/littleroad/btrfs-progs.git undelete
>
>v2->v3: fixed some issues pointed out by Qu.
>v1->v2: add -s option to allow user specify the subvolume which will be
>recovered.
>
>The first patch are not modified.
>For the rest, please see the changelog in the patches.
>
>Lu Fengqi (10):
> btrfs-progs: copy btrfs_del_orphan_item from kernel
> btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol
> btrfs-progs: use btrfs_find_free_dir_index to find free inode index
> btrfs-progs: undelete-subvol: introduce is_subvol_intact
> btrfs-progs: undelete-subvol: introduce recover_dead_root
> btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound
> btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols
> btrfs-progs: undelete-subvol: add undelete-subvol subcommand
> btrfs-progs: tests: add testcase for undelete-subvol
> btrfs-progs: undelete-subvol: update completion and documentation
>
> Documentation/btrfs-rescue.asciidoc | 12 +
> Makefile | 3 +-
> btrfs-completion | 2 +-
> cmds-rescue.c | 69 ++++++
> convert/main.c | 59 ++++-
> ctree.h | 8 +-
> inode.c | 119 +++++----
> .../031-undelete-subvol/intact_subvolume.img | Bin 0 -> 4096 bytes
> .../subvolume_in_drop_progress.raw.xz | Bin 0 -> 23452 bytes
> tests/misc-tests/031-undelete-subvol/test.sh | 38 +++
> undelete-subvol.c | 227 ++++++++++++++++++
> undelete-subvol.h | 11 +
> 12 files changed, 501 insertions(+), 47 deletions(-)
> create mode 100644 tests/misc-tests/031-undelete-subvol/intact_subvolume.img
> create mode 100644 tests/misc-tests/031-undelete-subvol/subvolume_in_drop_progress.raw.xz
> create mode 100755 tests/misc-tests/031-undelete-subvol/test.sh
> create mode 100644 undelete-subvol.c
> create mode 100644 undelete-subvol.h
>
>--
>2.17.0
>
>
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2018-09-11 16:43 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-07 3:10 [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 01/10] btrfs-progs: copy btrfs_del_orphan_item from kernel Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 02/10] btrfs-progs: extract btrfs_link_subvol from btrfs_mksubvol Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 03/10] btrfs-progs: use btrfs_find_free_dir_index to find free inode index Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 04/10] btrfs-progs: undelete-subvol: introduce is_subvol_intact Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 05/10] btrfs-progs: undelete-subvol: introduce recover_dead_root Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 06/10] btrfs-progs: undelete-subvol: introduce link_subvol_to_lostfound Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 07/10] btrfs-progs: undelete-subvol: introduce btrfs_undelete_subvols Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 08/10] btrfs-progs: undelete-subvol: add undelete-subvol subcommand Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 09/10] btrfs-progs: tests: add testcase for undelete-subvol Lu Fengqi
2018-05-08 5:58 ` [PATCH v3.1 " Lu Fengqi
2018-05-07 3:10 ` [PATCH v3 10/10] btrfs-progs: undelete-subvol: update completion and documentation Lu Fengqi
2018-09-11 11:44 ` [PATCH v3 00/10] undelete subvolume offline version Lu Fengqi
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).