summaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_reflink.h
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2016-10-03 09:11:37 -0700
committerDarrick J. Wong <darrick.wong@oracle.com>2016-10-05 16:26:04 -0700
commit0613f16cd20174d701853f1580ad44a9a6791ff2 (patch)
treea638ec8569cb6151628075d75c8dd6bb1fafd9cc /fs/xfs/xfs_reflink.h
parentdb1327b16c2b24e28d1e5899bced89db9ae6538e (diff)
downloadlinux-stable-0613f16cd20174d701853f1580ad44a9a6791ff2.tar.gz
linux-stable-0613f16cd20174d701853f1580ad44a9a6791ff2.tar.bz2
linux-stable-0613f16cd20174d701853f1580ad44a9a6791ff2.zip
xfs: implement CoW for directio writes
For O_DIRECT writes to shared blocks, we have to CoW them just like we would with buffered writes. For writes that are not block-aligned, just bounce them to the page cache. For block-aligned writes, however, we can do better than that. Use the same mechanisms that we employ for buffered CoW to set up a delalloc reservation, allocate all the blocks at once, issue the writes against the new blocks and use the same ioend functions to remap the blocks after the write. This should be fairly performant. Christoph discovered that xfs_reflink_allocate_cow_range may stumble over invalid entries in the extent array given that it drops the ilock but still expects the index to be stable. Simple fixing it to a new lookup for every iteration still isn't correct given that xfs_bmapi_allocate will trigger a BUG_ON() if hitting a hole, and there is nothing preventing a xfs_bunmapi_cow call removing extents once we dropped the ilock either. This patch duplicates the inner loop of xfs_bmapi_allocate into a helper for xfs_reflink_allocate_cow_range so that it can be done under the same ilock critical section as our CoW fork delayed allocation. The directio CoW warts will be revisited in a later patch. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_reflink.h')
-rw-r--r--fs/xfs/xfs_reflink.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index bffa4befa534..c0c989ae84bc 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -28,6 +28,8 @@ extern int xfs_reflink_trim_around_shared(struct xfs_inode *ip,
extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip,
xfs_off_t offset, xfs_off_t count);
+extern int xfs_reflink_allocate_cow_range(struct xfs_inode *ip,
+ xfs_off_t offset, xfs_off_t count);
extern bool xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset,
struct xfs_bmbt_irec *imap, bool *need_alloc);
extern int xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip,