diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r-- | fs/btrfs/tree-log.c | 21 |
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 | ||