| From 13dd4e04625f600e5affb1b3f0b6c35268ab839b Mon Sep 17 00:00:00 2001 |
| From: Shiyang Ruan <ruansy.fnst@fujitsu.com> |
| Date: Wed, 22 Mar 2023 11:11:09 +0000 |
| Subject: fsdax: unshare: zero destination if srcmap is HOLE or UNWRITTEN |
| |
| From: Shiyang Ruan <ruansy.fnst@fujitsu.com> |
| |
| commit 13dd4e04625f600e5affb1b3f0b6c35268ab839b upstream. |
| |
| unshare copies data from source to destination. But if the source is |
| HOLE or UNWRITTEN extents, we should zero the destination, otherwise |
| the HOLE or UNWRITTEN part will be user-visible old data of the new |
| allocated extent. |
| |
| Found by running generic/649 while mounting with -o dax=always on pmem. |
| |
| Link: https://lkml.kernel.org/r/1679483469-2-1-git-send-email-ruansy.fnst@fujitsu.com |
| Fixes: d984648e428b ("fsdax,xfs: port unshare to fsdax") |
| Signed-off-by: Shiyang Ruan <ruansy.fnst@fujitsu.com> |
| Cc: Dan Williams <dan.j.williams@intel.com> |
| Cc: Darrick J. Wong <djwong@kernel.org> |
| Cc: Jan Kara <jack@suse.cz> |
| Cc: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Cc: Alistair Popple <apopple@nvidia.com> |
| Cc: Jason Gunthorpe <jgg@nvidia.com> |
| Cc: John Hubbard <jhubbard@nvidia.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/dax.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| --- a/fs/dax.c |
| +++ b/fs/dax.c |
| @@ -1234,15 +1234,20 @@ static s64 dax_unshare_iter(struct iomap |
| /* don't bother with blocks that are not shared to start with */ |
| if (!(iomap->flags & IOMAP_F_SHARED)) |
| return length; |
| - /* don't bother with holes or unwritten extents */ |
| - if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN) |
| - return length; |
| |
| id = dax_read_lock(); |
| ret = dax_iomap_direct_access(iomap, pos, length, &daddr, NULL); |
| if (ret < 0) |
| goto out_unlock; |
| |
| + /* zero the distance if srcmap is HOLE or UNWRITTEN */ |
| + if (srcmap->flags & IOMAP_F_SHARED || srcmap->type == IOMAP_UNWRITTEN) { |
| + memset(daddr, 0, length); |
| + dax_flush(iomap->dax_dev, daddr, length); |
| + ret = length; |
| + goto out_unlock; |
| + } |
| + |
| ret = dax_iomap_direct_access(srcmap, pos, length, &saddr, NULL); |
| if (ret < 0) |
| goto out_unlock; |