aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-09-19 15:42:38 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-08 20:09:02 -0400
commit0aa4a17d8232e7d8a42763b53bb9943bc0484b18 (patch)
treefa3ca49da139088f2aad0877944f06e4bec1b6fb /fs/btrfs/tree-log.c
parent005d6427ac4f276d937a36ca6a1d62b181ed70bf (diff)
Btrfs: handle not finding the extent exactly when logging changed extents
I started hitting warnings when running xfstest 68 in a loop because there were EM's that were not lined up properly with the physical extents. This is ok, if we do something like punch a hole or write to a preallocated space or something like that we can have an EM that doesn't cover the entire physical extent. So fix the tree logging stuff to cope with this case so we don't just commit the transaction. With this patch I no longer see the warnings from the tree logging code. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index ed1f7ce7219a..e0ef92f91d66 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2833,6 +2833,7 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
2833 struct btrfs_file_extent_item *fi; 2833 struct btrfs_file_extent_item *fi;
2834 struct btrfs_key key; 2834 struct btrfs_key key;
2835 u64 start = em->mod_start; 2835 u64 start = em->mod_start;
2836 u64 search_start = start;
2836 u64 len = em->mod_len; 2837 u64 len = em->mod_len;
2837 u64 num_bytes; 2838 u64 num_bytes;
2838 int nritems; 2839 int nritems;
@@ -2848,23 +2849,55 @@ static int log_one_extent(struct btrfs_trans_handle *trans,
2848 while (len) { 2849 while (len) {
2849 if (args->nr) 2850 if (args->nr)
2850 goto next_slot; 2851 goto next_slot;
2852again:
2851 key.objectid = btrfs_ino(inode); 2853 key.objectid = btrfs_ino(inode);
2852 key.type = BTRFS_EXTENT_DATA_KEY; 2854 key.type = BTRFS_EXTENT_DATA_KEY;
2853 key.offset = start; 2855 key.offset = search_start;
2854 2856
2855 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); 2857 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
2856 if (ret < 0) 2858 if (ret < 0)
2857 return ret; 2859 return ret;
2860
2858 if (ret) { 2861 if (ret) {
2859 /* 2862 /*
2860 * This shouldn't happen, but it might so warn and 2863 * A rare case were we can have an em for a section of a
2861 * return an error. 2864 * larger extent so we need to make sure that this em
2865 * falls within the extent we've found. If not we just
2866 * bail and go back to ye-olde way of doing things but
2867 * it happens often enough in testing that we need to do
2868 * this dance to make sure.
2862 */ 2869 */
2863 WARN_ON(1); 2870 do {
2864 return -ENOENT; 2871 if (path->slots[0] == 0) {
2872 btrfs_release_path(path);
2873 if (search_start == 0)
2874 return -ENOENT;
2875 search_start--;
2876 goto again;
2877 }
2878
2879 path->slots[0]--;
2880 btrfs_item_key_to_cpu(path->nodes[0], &key,
2881 path->slots[0]);
2882 if (key.objectid != btrfs_ino(inode) ||
2883 key.type != BTRFS_EXTENT_DATA_KEY) {
2884 btrfs_release_path(path);
2885 return -ENOENT;
2886 }
2887 } while (key.offset > start);
2888
2889 fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
2890 struct btrfs_file_extent_item);
2891 num_bytes = btrfs_file_extent_num_bytes(path->nodes[0],
2892 fi);
2893 if (key.offset + num_bytes <= start) {
2894 btrfs_release_path(path);
2895 return -ENOENT;
2896 }
2865 } 2897 }
2866 args->src = path->nodes[0]; 2898 args->src = path->nodes[0];
2867next_slot: 2899next_slot:
2900 btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
2868 fi = btrfs_item_ptr(args->src, path->slots[0], 2901 fi = btrfs_item_ptr(args->src, path->slots[0],
2869 struct btrfs_file_extent_item); 2902 struct btrfs_file_extent_item);
2870 if (args->nr && 2903 if (args->nr &&
@@ -2898,8 +2931,9 @@ next_slot:
2898 } else { 2931 } else {
2899 len -= num_bytes; 2932 len -= num_bytes;
2900 } 2933 }
2901 start += btrfs_file_extent_num_bytes(args->src, fi); 2934 start = key.offset + num_bytes;
2902 args->next_offset = start; 2935 args->next_offset = start;
2936 search_start = start;
2903 2937
2904 if (path->slots[0] < nritems) { 2938 if (path->slots[0] < nritems) {
2905 if (len) 2939 if (len)