summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2015-01-02 15:12:33 +0800
committerDavid Sterba <dsterba@suse.cz>2015-02-02 14:16:38 +0100
commit16584ea51eeb836f6a82b44d15cbc40de1e4da5f (patch)
tree2ebc7ea46cd48895c5493f89848723a07b501b0c
parentad03f840f0d2fabba682941db685b2c767a0c536 (diff)
btrfs-progs: Add repair function for discount file extent hole.
Since orphan extents are handled in previous patches, now just punch holes to fill the file extents hole. Also since now btrfsck is aware of whether the inode has orphan file extent, allow repair_inode_no_item() to determine filetype according to orphan file extent. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.cz>
-rw-r--r--cmds-check.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/cmds-check.c b/cmds-check.c
index 7d5625da..15e44956 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -2473,12 +2473,6 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
int type_recovered = 0;
int ret = 0;
- /*
- * TODO:
- * 1. salvage data from existing file extent and
- * punch hole to keep fi ext consistent.
- * 2. salvage data from extent tree
- */
printf("Trying to rebuild inode:%llu\n", rec->ino);
type_recovered = !find_file_type(rec, &filetype);
@@ -2492,9 +2486,7 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
* For undetermined one, use FILE as fallback.
*
* TODO:
- * 1. If found extent belong to it in extent tree, it must be FILE
- * Need extra hook in extent tree scan.
- * 2. If found backref(inode_index/item is already handled) to it,
+ * 1. If found backref(inode_index/item is already handled) to it,
* it must be DIR.
* Need new inode-inode ref structure to allow search for that.
*/
@@ -2506,7 +2498,10 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
} else if (rec->found_dir_item) {
type_recovered = 1;
filetype = BTRFS_FT_DIR;
- } else {
+ } else if (!list_empty(&rec->orphan_extents)) {
+ type_recovered = 1;
+ filetype = BTRFS_FT_REG_FILE;
+ } else{
printf("Can't determint the filetype for inode %llu, assume it is a normal file\n",
rec->ino);
type_recovered = 1;
@@ -2597,6 +2592,37 @@ out:
return ret;
}
+static int repair_inode_discount_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_path *path,
+ struct inode_record *rec)
+{
+ struct rb_node *node;
+ struct file_extent_hole *hole;
+ int ret = 0;
+
+ node = rb_first(&rec->holes);
+
+ while (node) {
+ hole = rb_entry(node, struct file_extent_hole, node);
+ ret = btrfs_punch_hole(trans, root, rec->ino,
+ hole->start, hole->len);
+ if (ret < 0)
+ goto out;
+ ret = del_file_extent_hole(&rec->holes, hole->start,
+ hole->len);
+ if (ret < 0)
+ goto out;
+ if (RB_EMPTY_ROOT(&rec->holes))
+ rec->errors &= ~I_ERR_FILE_EXTENT_DISCOUNT;
+ node = rb_first(&rec->holes);
+ }
+ printf("Fixed discount file extents for inode: %llu in root: %llu\n",
+ rec->ino, root->objectid);
+out:
+ return ret;
+}
+
static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
{
struct btrfs_trans_handle *trans;
@@ -2607,7 +2633,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
I_ERR_NO_ORPHAN_ITEM |
I_ERR_LINK_COUNT_WRONG |
I_ERR_NO_INODE_ITEM |
- I_ERR_FILE_EXTENT_ORPHAN)))
+ I_ERR_FILE_EXTENT_ORPHAN |
+ I_ERR_FILE_EXTENT_DISCOUNT)))
return rec->errors;
path = btrfs_alloc_path();
@@ -2631,6 +2658,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
ret = repair_inode_no_item(trans, root, path, rec);
if (!ret && rec->errors & I_ERR_FILE_EXTENT_ORPHAN)
ret = repair_inode_orphan_extent(trans, root, path, rec);
+ if (!ret && rec->errors & I_ERR_FILE_EXTENT_DISCOUNT)
+ ret = repair_inode_discount_extent(trans, root, path, rec);
if (!ret && rec->errors & I_ERR_DIR_ISIZE_WRONG)
ret = repair_inode_isize(trans, root, path, rec);
if (!ret && rec->errors & I_ERR_NO_ORPHAN_ITEM)