aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 038a5229404a..ed1f7ce7219a 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2945,6 +2945,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
2945 list_del_init(&em->list); 2945 list_del_init(&em->list);
2946 if (em->generation <= test_gen) 2946 if (em->generation <= test_gen)
2947 continue; 2947 continue;
2948 /* Need a ref to keep it from getting evicted from cache */
2949 atomic_inc(&em->refs);
2950 set_bit(EXTENT_FLAG_LOGGING, &em->flags);
2948 list_add_tail(&em->list, &extents); 2951 list_add_tail(&em->list, &extents);
2949 } 2952 }
2950 2953
@@ -2954,13 +2957,18 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
2954 em = list_entry(extents.next, struct extent_map, list); 2957 em = list_entry(extents.next, struct extent_map, list);
2955 2958
2956 list_del_init(&em->list); 2959 list_del_init(&em->list);
2960 clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
2957 2961
2958 /* 2962 /*
2959 * If we had an error we just need to delete everybody from our 2963 * If we had an error we just need to delete everybody from our
2960 * private list. 2964 * private list.
2961 */ 2965 */
2962 if (ret) 2966 if (ret) {
2967 free_extent_map(em);
2963 continue; 2968 continue;
2969 }
2970
2971 write_unlock(&tree->lock);
2964 2972
2965 /* 2973 /*
2966 * If the previous EM and the last extent we left off on aren't 2974 * If the previous EM and the last extent we left off on aren't
@@ -2971,21 +2979,26 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
2971 ret = copy_items(trans, inode, dst_path, args.src, 2979 ret = copy_items(trans, inode, dst_path, args.src,
2972 args.start_slot, args.nr, 2980 args.start_slot, args.nr,
2973 LOG_INODE_ALL); 2981 LOG_INODE_ALL);
2974 if (ret) 2982 if (ret) {
2983 free_extent_map(em);
2984 write_lock(&tree->lock);
2975 continue; 2985 continue;
2986 }
2976 btrfs_release_path(path); 2987 btrfs_release_path(path);
2977 args.nr = 0; 2988 args.nr = 0;
2978 } 2989 }
2979 2990
2980 ret = log_one_extent(trans, inode, root, em, path, dst_path, &args); 2991 ret = log_one_extent(trans, inode, root, em, path, dst_path, &args);
2992 free_extent_map(em);
2993 write_lock(&tree->lock);
2981 } 2994 }
2995 WARN_ON(!list_empty(&extents));
2996 write_unlock(&tree->lock);
2982 2997
2983 if (!ret && args.nr) 2998 if (!ret && args.nr)
2984 ret = copy_items(trans, inode, dst_path, args.src, 2999 ret = copy_items(trans, inode, dst_path, args.src,
2985 args.start_slot, args.nr, LOG_INODE_ALL); 3000 args.start_slot, args.nr, LOG_INODE_ALL);
2986 btrfs_release_path(path); 3001 btrfs_release_path(path);
2987 WARN_ON(!list_empty(&extents));
2988 write_unlock(&tree->lock);
2989 return ret; 3002 return ret;
2990} 3003}
2991 3004