]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
btrfs: check folio mapping after unlock in put_file_data()
authorBoris Burkov <boris@bur.io>
Fri, 13 Dec 2024 20:33:22 +0000 (12:33 -0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Dec 2024 21:00:07 +0000 (22:00 +0100)
When we call btrfs_read_folio() we get an unlocked folio, so it is possible
for a different thread to concurrently modify folio->mapping. We must
check that this hasn't happened once we do have the lock.

CC: stable@vger.kernel.org # 6.12+
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/send.c

index 7254279c3cc92c76cd3ebceabe9455ca38c67163..498c8432325369c5d188fef4aa69c3767e3edf01 100644 (file)
@@ -5280,6 +5280,7 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
                unsigned cur_len = min_t(unsigned, len,
                                         PAGE_SIZE - pg_offset);
 
+again:
                folio = filemap_lock_folio(mapping, index);
                if (IS_ERR(folio)) {
                        page_cache_sync_readahead(mapping,
@@ -5312,6 +5313,11 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
                                ret = -EIO;
                                break;
                        }
+                       if (folio->mapping != mapping) {
+                               folio_unlock(folio);
+                               folio_put(folio);
+                               goto again;
+                       }
                }
 
                memcpy_from_folio(sctx->send_buf + sctx->send_size, folio,