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.f...@cn.fujitsu.com>
---
 undelete-subvol.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/undelete-subvol.c b/undelete-subvol.c
index 781057df2b84..9243e35545c5 100644
--- a/undelete-subvol.c
+++ b/undelete-subvol.c
@@ -106,3 +106,79 @@ out:
        btrfs_release_path(&path);
        return ret;
 }
+
+/*
+ * Recover a subvolume specified by subvol_id, and link it to the lost+found
+ * directory.
+ *
+ * @root: the root of the root tree.
+ * @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_root *root, u64 subvol_id)
+{
+       struct btrfs_trans_handle *trans;
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       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 and increase root refs */
+       ret = recover_dead_root(trans, root, 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.16.1



--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to