WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
rb_erase(&em->rb_node, &tree->map);
- list_del_init(&em->list);
+ if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
+ list_del_init(&em->list);
em->in_tree = 0;
return ret;
}
list_del_init(&em->list);
if (em->generation <= test_gen)
continue;
+ /* Need a ref to keep it from getting evicted from cache */
+ atomic_inc(&em->refs);
+ set_bit(EXTENT_FLAG_LOGGING, &em->flags);
list_add_tail(&em->list, &extents);
}
em = list_entry(extents.next, struct extent_map, list);
list_del_init(&em->list);
+ clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
/*
* If we had an error we just need to delete everybody from our
* private list.
*/
- if (ret)
+ if (ret) {
+ free_extent_map(em);
continue;
+ }
+
+ write_unlock(&tree->lock);
/*
* If the previous EM and the last extent we left off on aren't
ret = copy_items(trans, inode, dst_path, args.src,
args.start_slot, args.nr,
LOG_INODE_ALL);
- if (ret)
+ if (ret) {
+ free_extent_map(em);
+ write_lock(&tree->lock);
continue;
+ }
btrfs_release_path(path);
args.nr = 0;
}
ret = log_one_extent(trans, inode, root, em, path, dst_path, &args);
+ free_extent_map(em);
+ write_lock(&tree->lock);
}
+ WARN_ON(!list_empty(&extents));
+ write_unlock(&tree->lock);
if (!ret && args.nr)
ret = copy_items(trans, inode, dst_path, args.src,
args.start_slot, args.nr, LOG_INODE_ALL);
btrfs_release_path(path);
- WARN_ON(!list_empty(&extents));
- write_unlock(&tree->lock);
return ret;
}