diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-08-05 16:03:13 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2015-08-31 19:25:12 +0200 |
commit | 773ede50c002a28eabc16b5afa43951993170ab3 (patch) | |
tree | 2571d27c729a082bb96c1891bffc874a4bda4268 /cmds-check.c | |
parent | 1ffa833a910b5a7070d9ee4456fb833aab7cf91d (diff) | |
download | btrfs-progs-773ede50c002a28eabc16b5afa43951993170ab3.tar.gz |
btrfs-progs: fsck: fix a infinite loop on discount file extent repair
For a special case, discount file extent repair function will cause
infinite loop.
The case is, if the file loses all its extents, we won't have a hole
to fill, causing repair function doing nothing. Since the
I_ERR_DISCOUNT doesn't disappear, fsck will do an infinite loop.
For such case, just puch hole to fill the whole range to fix it.
Reported-by: Robert Munteanu <robert.munteanu@gmail.com>
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'cmds-check.c')
-rw-r--r-- | cmds-check.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/cmds-check.c b/cmds-check.c index 31ed589..4fa8709 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -2665,11 +2665,13 @@ static int repair_inode_discount_extent(struct btrfs_trans_handle *trans, { struct rb_node *node; struct file_extent_hole *hole; + int found = 0; int ret = 0; node = rb_first(&rec->holes); while (node) { + found = 1; hole = rb_entry(node, struct file_extent_hole, node); ret = btrfs_punch_hole(trans, root, rec->ino, hole->start, hole->len); @@ -2683,6 +2685,13 @@ static int repair_inode_discount_extent(struct btrfs_trans_handle *trans, rec->errors &= ~I_ERR_FILE_EXTENT_DISCOUNT; node = rb_first(&rec->holes); } + /* special case for a file losing all its file extent */ + if (!found) { + ret = btrfs_punch_hole(trans, root, rec->ino, 0, + round_up(rec->isize, root->sectorsize)); + if (ret < 0) + goto out; + } printf("Fixed discount file extents for inode: %llu in root: %llu\n", rec->ino, root->objectid); out: |