|
@@ -4396,6 +4396,23 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
|
|
logged_end = end;
|
|
logged_end = end;
|
|
|
|
|
|
list_for_each_entry_safe(em, n, &tree->modified_extents, list) {
|
|
list_for_each_entry_safe(em, n, &tree->modified_extents, list) {
|
|
|
|
+ /*
|
|
|
|
+ * Skip extents outside our logging range. It's important to do
|
|
|
|
+ * it for correctness because if we don't ignore them, we may
|
|
|
|
+ * log them before their ordered extent completes, and therefore
|
|
|
|
+ * we could log them without logging their respective checksums
|
|
|
|
+ * (the checksum items are added to the csum tree at the very
|
|
|
|
+ * end of btrfs_finish_ordered_io()). Also leave such extents
|
|
|
|
+ * outside of our range in the list, since we may have another
|
|
|
|
+ * ranged fsync in the near future that needs them. If an extent
|
|
|
|
+ * outside our range corresponds to a hole, log it to avoid
|
|
|
|
+ * leaving gaps between extents (fsck will complain when we are
|
|
|
|
+ * not using the NO_HOLES feature).
|
|
|
|
+ */
|
|
|
|
+ if ((em->start > end || em->start + em->len <= start) &&
|
|
|
|
+ em->block_start != EXTENT_MAP_HOLE)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
list_del_init(&em->list);
|
|
list_del_init(&em->list);
|
|
/*
|
|
/*
|
|
* Just an arbitrary number, this can be really CPU intensive
|
|
* Just an arbitrary number, this can be really CPU intensive
|