aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-12 06:44:04 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:39:02 -0400
commitf612496bca664bff6a09a99a9a7506410b6e876e (patch)
treed74da9c3d7c60a4ceb29c70be9a5d114eb7c8cc2
parent8b110e393c5a6e72d50fcdf9fa7ed8b647cfdfc9 (diff)
Btrfs: cleanup the read failure record after write or when the inode is freeing
After the data is written successfully, we should cleanup the read failure record in that range because - If we set data COW for the file, the range that the failure record pointed to is mapped to a new place, so it is invalid. - If we set no data COW for the file, and if there is no error during writting, the corrupted data is corrected, so the failure record can be removed. And if some errors happen on the mirrors, we also needn't worry about it because the failure record will be recreated if we read the same place again. Sometimes, we may fail to correct the data, so the failure records will be left in the tree, we need free them when we free the inode or the memory leak happens. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/extent_io.c34
-rw-r--r--fs/btrfs/extent_io.h1
-rw-r--r--fs/btrfs/inode.c6
3 files changed, 41 insertions, 0 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 9e2ef27672e5..78229007f99e 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2138,6 +2138,40 @@ out:
2138 return 0; 2138 return 0;
2139} 2139}
2140 2140
2141/*
2142 * Can be called when
2143 * - hold extent lock
2144 * - under ordered extent
2145 * - the inode is freeing
2146 */
2147void btrfs_free_io_failure_record(struct inode *inode, u64 start, u64 end)
2148{
2149 struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
2150 struct io_failure_record *failrec;
2151 struct extent_state *state, *next;
2152
2153 if (RB_EMPTY_ROOT(&failure_tree->state))
2154 return;
2155
2156 spin_lock(&failure_tree->lock);
2157 state = find_first_extent_bit_state(failure_tree, start, EXTENT_DIRTY);
2158 while (state) {
2159 if (state->start > end)
2160 break;
2161
2162 ASSERT(state->end <= end);
2163
2164 next = next_state(state);
2165
2166 failrec = (struct io_failure_record *)state->private;
2167 free_extent_state(state);
2168 kfree(failrec);
2169
2170 state = next;
2171 }
2172 spin_unlock(&failure_tree->lock);
2173}
2174
2141int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end, 2175int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
2142 struct io_failure_record **failrec_ret) 2176 struct io_failure_record **failrec_ret)
2143{ 2177{
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 176a4b1ed520..5e91fb9d1764 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -366,6 +366,7 @@ struct io_failure_record {
366 int in_validation; 366 int in_validation;
367}; 367};
368 368
369void btrfs_free_io_failure_record(struct inode *inode, u64 start, u64 end);
369int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end, 370int btrfs_get_io_failure_record(struct inode *inode, u64 start, u64 end,
370 struct io_failure_record **failrec_ret); 371 struct io_failure_record **failrec_ret);
371int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio, 372int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c3c3269a9e08..3c16a1493e22 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2703,6 +2703,10 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
2703 goto out; 2703 goto out;
2704 } 2704 }
2705 2705
2706 btrfs_free_io_failure_record(inode, ordered_extent->file_offset,
2707 ordered_extent->file_offset +
2708 ordered_extent->len - 1);
2709
2706 if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) { 2710 if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) {
2707 truncated = true; 2711 truncated = true;
2708 logical_len = ordered_extent->truncated_len; 2712 logical_len = ordered_extent->truncated_len;
@@ -4799,6 +4803,8 @@ void btrfs_evict_inode(struct inode *inode)
4799 /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */ 4803 /* do we really want it for ->i_nlink > 0 and zero btrfs_root_refs? */
4800 btrfs_wait_ordered_range(inode, 0, (u64)-1); 4804 btrfs_wait_ordered_range(inode, 0, (u64)-1);
4801 4805
4806 btrfs_free_io_failure_record(inode, 0, (u64)-1);
4807
4802 if (root->fs_info->log_root_recovering) { 4808 if (root->fs_info->log_root_recovering) {
4803 BUG_ON(test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM, 4809 BUG_ON(test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
4804 &BTRFS_I(inode)->runtime_flags)); 4810 &BTRFS_I(inode)->runtime_flags));