Introduce 'repair_ternary_lowmem' to repair error while checking
dir_item/index, inode_ref by the rule:
1. If two of three is missing or mismatched, delete the existed one.
2. If one of three is missing or mismatched, add the missing one.

Signed-off-by: Su Yue <suy.f...@cn.fujitsu.com>
---
 cmds-check.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/cmds-check.c b/cmds-check.c
index 85e87884..9a76107e 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -4388,6 +4388,63 @@ static void print_inode_ref_err(struct btrfs_root *root, 
struct btrfs_key *key,
                       namebuf, filetype);
 }
 
+static int repair_inode_item_missing(struct btrfs_root *root, u64 ino,
+                                    u8 filetype, int err);
+/*
+ * The ternary contains dir item, dir index and relative inode ref.
+ * the repair function will handle errs: INODE_MISSING, DIR_INDEX_MISSING
+ * DIR_INDEX_MISMATCH, DIR_ITEM_MISSING, DIR_ITEM_MISMATCH by the follow
+ * strategy:
+ * If two of three is missing or mismatched, delete the existed one.
+ * If one of three is missing or mismatched, add the missing one.
+ *
+ * returns 0 mens success.
+ */
+int repair_ternary_lowmem(struct btrfs_root *root, u64 dir_ino, u64 ino,
+                         u64 index, char *name, int name_len, u8 filetype,
+                         int err)
+{
+       struct btrfs_trans_handle *trans;
+       int stage = 0;
+       int ret;
+
+       if (!err)
+               return 0;
+       /*
+        * stage shall be one of follow valild values:
+        *      0: Fine, nothing to do.
+        *      1: One of three is wrong, so add missing one.
+        *      2: Two of three is wrong, so delete existed one.
+        */
+       if (err & (DIR_INDEX_MISMATCH | DIR_INDEX_MISSING))
+               ++stage;
+       if (err & (DIR_ITEM_MISMATCH | DIR_ITEM_MISSING))
+               ++stage;
+       if (err & (INODE_REF_MISSING))
+               ++stage;
+
+       /* stage must be smllarer than 3 */
+       ASSERT(stage < 3);
+
+       trans = btrfs_start_transaction(root, 2);
+       if (stage == 2) {
+               ret = btrfs_unlink(trans, root, ino, dir_ino, index, name,
+                                  name_len, 0);
+               if (ret)
+                       goto out;
+       }
+       if (stage == 1) {
+               ret = btrfs_add_link(trans, root, ino, dir_ino, name, name_len,
+                              filetype, &index, 1, 1);
+               if (ret)
+                       goto out;
+       }
+
+       btrfs_commit_transaction(trans, root);
+out:
+       return ret;
+}
+
 /*
  * Traverse the given INODE_REF and call find_dir_item() to find related
  * DIR_ITEM/DIR_INDEX.If repair is enable, research @ref_key and
-- 
2.11.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