In preparation for using FL_LAYOUT leases to allow coordination between the kernel and processes doing userspace flushes / RDMA with DAX mappings, add this helper that can be used to start the lease break process in contexts where we can not sleep waiting for the lease break timeout. This is targeted to be used in an ->iomap_begin() implementation where we may have various filesystem locks held and can not synchronously wait for any FL_LAYOUT leases to be released. In particular an iomap mmap fault handler running under mmap_sem can not unlock that semaphore and wait for these leases to be unlocked. Instead, this signals the lease holder(s) that a break is requested and immediately returns with an error. Cc: Jan Kara <jack@xxxxxxx> Cc: Jeff Moyer <jmoyer@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: "Darrick J. Wong" <darrick.wong@xxxxxxxxxx> Cc: Ross Zwisler <ross.zwisler@xxxxxxxxxxxxxxx> Suggested-by: Dave Chinner <david@xxxxxxxxxxxxx> Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> --- fs/xfs/xfs_iomap.c | 3 +++ fs/xfs/xfs_layout.c | 5 ++++- include/linux/fs.h | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index f179bdf1644d..840e4080afb5 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -1055,6 +1055,9 @@ xfs_file_iomap_begin( error = -EAGAIN; goto out_unlock; } + error = break_layout_nowait(inode); + if (error) + goto out_unlock; /* * We cap the maximum length we map here to MAX_WRITEBACK_PAGES * pages to keep the chunks of work done where somewhat symmetric diff --git a/fs/xfs/xfs_layout.c b/fs/xfs/xfs_layout.c index 71d95e1a910a..7a633b6e9397 100644 --- a/fs/xfs/xfs_layout.c +++ b/fs/xfs/xfs_layout.c @@ -19,7 +19,10 @@ * about exposing unallocated blocks but just want to provide basic * synchronization between a local writer and pNFS clients. mmap writes would * also benefit from this sort of synchronization, but due to the tricky locking - * rules in the page fault path we don't bother. + * rules in the page fault path all we can do is start the lease break + * timeout. See usage of break_layout_nowait in xfs_file_iomap_begin to + * prevent write-faults from allocating blocks or performing extent + * conversion. */ int xfs_break_layouts( diff --git a/include/linux/fs.h b/include/linux/fs.h index 17e0e899e184..2b030a2fccc7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2364,6 +2364,15 @@ static inline int break_layout(struct inode *inode, bool wait) #endif /* CONFIG_FILE_LOCKING */ +/* + * For use in paths where we can not wait for the layout to be recalled, + * for example when we are holding mmap_sem. + */ +static inline int break_layout_nowait(struct inode *inode) +{ + return break_layout(inode, false); +} + /* fs/open.c */ struct audit_names; struct filename { -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html