btrfs: fix stale data exposure after cloning a hole with NO_HOLES enabled
[linux-2.6-microblaze.git] / fs / btrfs / reflink.c
index b24396c..5413578 100644 (file)
@@ -553,6 +553,24 @@ process_slot:
                 */
                btrfs_release_path(path);
 
+               /*
+                * When using NO_HOLES and we are cloning a range that covers
+                * only a hole (no extents) into a range beyond the current
+                * i_size, punching a hole in the target range will not create
+                * an extent map defining a hole, because the range starts at or
+                * beyond current i_size. If the file previously had an i_size
+                * greater than the new i_size set by this clone operation, we
+                * need to make sure the next fsync is a full fsync, so that it
+                * detects and logs a hole covering a range from the current
+                * i_size to the new i_size. If the clone range covers extents,
+                * besides a hole, then we know the full sync flag was already
+                * set by previous calls to btrfs_replace_file_extents() that
+                * replaced file extent items.
+                */
+               if (last_dest_end >= i_size_read(inode))
+                       set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
+                               &BTRFS_I(inode)->runtime_flags);
+
                ret = btrfs_replace_file_extents(inode, path, last_dest_end,
                                destoff + len - 1, NULL, &trans);
                if (ret)