Commit db1327b1 authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: report shared extent mappings to userspace correctly

Report shared extents through the iomap interface so that FIEMAP flags
shared blocks accurately.  Have xfs_vm_bmap return zero for reflinked
files because the bmap-based swap code requires static block mappings,
which is incompatible with copy on write.

NOTE: Existing userspace bmap users such as lilo will have the same
problem with reflink files.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 43caeb18
...@@ -1508,6 +1508,17 @@ xfs_vm_bmap( ...@@ -1508,6 +1508,17 @@ xfs_vm_bmap(
trace_xfs_vm_bmap(XFS_I(inode)); trace_xfs_vm_bmap(XFS_I(inode));
xfs_ilock(ip, XFS_IOLOCK_SHARED); xfs_ilock(ip, XFS_IOLOCK_SHARED);
/*
* The swap code (ab-)uses ->bmap to get a block mapping and then
* bypasseѕ the file system for actual I/O. We really can't allow
* that on reflinks inodes, so we have to skip out here. And yes,
* 0 is the magic code for a bmap error..
*/
if (xfs_is_reflink_inode(ip)) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return 0;
}
filemap_write_and_wait(mapping); filemap_write_and_wait(mapping);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return generic_block_bmap(mapping, block, xfs_get_blocks); return generic_block_bmap(mapping, block, xfs_get_blocks);
......
...@@ -961,6 +961,7 @@ xfs_file_iomap_begin( ...@@ -961,6 +961,7 @@ xfs_file_iomap_begin(
struct xfs_mount *mp = ip->i_mount; struct xfs_mount *mp = ip->i_mount;
struct xfs_bmbt_irec imap; struct xfs_bmbt_irec imap;
xfs_fileoff_t offset_fsb, end_fsb; xfs_fileoff_t offset_fsb, end_fsb;
bool shared, trimmed;
int nimaps = 1, error = 0; int nimaps = 1, error = 0;
unsigned lockmode; unsigned lockmode;
...@@ -989,7 +990,14 @@ xfs_file_iomap_begin( ...@@ -989,7 +990,14 @@ xfs_file_iomap_begin(
end_fsb = XFS_B_TO_FSB(mp, offset + length); end_fsb = XFS_B_TO_FSB(mp, offset + length);
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
&nimaps, XFS_BMAPI_ENTIRE); &nimaps, 0);
if (error) {
xfs_iunlock(ip, lockmode);
return error;
}
/* Trim the mapping to the nearest shared extent boundary. */
error = xfs_reflink_trim_around_shared(ip, &imap, &shared, &trimmed);
if (error) { if (error) {
xfs_iunlock(ip, lockmode); xfs_iunlock(ip, lockmode);
return error; return error;
...@@ -1028,6 +1036,8 @@ xfs_file_iomap_begin( ...@@ -1028,6 +1036,8 @@ xfs_file_iomap_begin(
} }
xfs_bmbt_to_iomap(ip, iomap, &imap); xfs_bmbt_to_iomap(ip, iomap, &imap);
if (shared)
iomap->flags |= IOMAP_F_SHARED;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment