diff mbox

[2/3] btrfs-progs: fsck: Fix a infinite loop on discount file extent repair

Message ID 1438761794-32738-3-git-send-email-quwenruo@cn.fujitsu.com (mailing list archive)
State Accepted
Headers show

Commit Message

Qu Wenruo Aug. 5, 2015, 8:03 a.m. UTC
For a special case, discount file extent repair function will cause
infinite loop.

The case is, if the file loses all its file extent, we won't have a hole
to fill, causing repair function doing nothing, and since the
I_ERR_DISCOUNT doesn't disappear, the fsck will do infinite loop.

For such case, just puch hole to fill all the range to fix it.

Reported-by: Robert Munteanu <robert.munteanu@gmail.com>
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
 cmds-check.c | 9 +++++++++
 1 file changed, 9 insertions(+)
diff mbox

Patch

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: