Commit 29a5d29e authored by Goldwyn Rodrigues's avatar Goldwyn Rodrigues Committed by Jens Axboe

xfs: nowait aio support

If IOCB_NOWAIT is set, bail if the i_rwsem is not lockable
immediately.

IF IOMAP_NOWAIT is set, return EAGAIN in xfs_file_iomap_begin
if it needs allocation either due to file extension, writing to a hole,
or COW or waiting for other DIOs to finish.

Return -EAGAIN if we don't have extent list in memory.
Signed-off-by: default avatarGoldwyn Rodrigues <rgoldwyn@suse.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 728fbc0e
...@@ -237,7 +237,11 @@ xfs_file_dax_read( ...@@ -237,7 +237,11 @@ xfs_file_dax_read(
if (!count) if (!count)
return 0; /* skip atime */ return 0; /* skip atime */
xfs_ilock(ip, XFS_IOLOCK_SHARED); if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
}
ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops); ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
...@@ -541,7 +545,11 @@ xfs_file_dio_aio_write( ...@@ -541,7 +545,11 @@ xfs_file_dio_aio_write(
iolock = XFS_IOLOCK_SHARED; iolock = XFS_IOLOCK_SHARED;
} }
xfs_ilock(ip, iolock); if (!xfs_ilock_nowait(ip, iolock)) {
if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN;
xfs_ilock(ip, iolock);
}
ret = xfs_file_aio_write_checks(iocb, from, &iolock); ret = xfs_file_aio_write_checks(iocb, from, &iolock);
if (ret) if (ret)
...@@ -553,9 +561,15 @@ xfs_file_dio_aio_write( ...@@ -553,9 +561,15 @@ xfs_file_dio_aio_write(
* otherwise demote the lock if we had to take the exclusive lock * otherwise demote the lock if we had to take the exclusive lock
* for other reasons in xfs_file_aio_write_checks. * for other reasons in xfs_file_aio_write_checks.
*/ */
if (unaligned_io) if (unaligned_io) {
inode_dio_wait(inode); /* If we are going to wait for other DIO to finish, bail */
else if (iolock == XFS_IOLOCK_EXCL) { if (iocb->ki_flags & IOCB_NOWAIT) {
if (atomic_read(&inode->i_dio_count))
return -EAGAIN;
} else {
inode_dio_wait(inode);
}
} else if (iolock == XFS_IOLOCK_EXCL) {
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL); xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
iolock = XFS_IOLOCK_SHARED; iolock = XFS_IOLOCK_SHARED;
} }
...@@ -585,7 +599,12 @@ xfs_file_dax_write( ...@@ -585,7 +599,12 @@ xfs_file_dax_write(
size_t count; size_t count;
loff_t pos; loff_t pos;
xfs_ilock(ip, iolock); if (!xfs_ilock_nowait(ip, iolock)) {
if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN;
xfs_ilock(ip, iolock);
}
ret = xfs_file_aio_write_checks(iocb, from, &iolock); ret = xfs_file_aio_write_checks(iocb, from, &iolock);
if (ret) if (ret)
goto out; goto out;
...@@ -892,6 +911,7 @@ xfs_file_open( ...@@ -892,6 +911,7 @@ xfs_file_open(
return -EFBIG; return -EFBIG;
if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb))) if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
return -EIO; return -EIO;
file->f_mode |= FMODE_AIO_NOWAIT;
return 0; return 0;
} }
......
...@@ -995,6 +995,11 @@ xfs_file_iomap_begin( ...@@ -995,6 +995,11 @@ xfs_file_iomap_begin(
lockmode = xfs_ilock_data_map_shared(ip); lockmode = xfs_ilock_data_map_shared(ip);
} }
if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) {
error = -EAGAIN;
goto out_unlock;
}
ASSERT(offset <= mp->m_super->s_maxbytes); ASSERT(offset <= mp->m_super->s_maxbytes);
if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes) if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes)
length = mp->m_super->s_maxbytes - offset; length = mp->m_super->s_maxbytes - offset;
...@@ -1016,6 +1021,15 @@ xfs_file_iomap_begin( ...@@ -1016,6 +1021,15 @@ xfs_file_iomap_begin(
if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) { if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
if (flags & IOMAP_DIRECT) { if (flags & IOMAP_DIRECT) {
/*
* A reflinked inode will result in CoW alloc.
* FIXME: It could still overwrite on unshared extents
* and not need allocation.
*/
if (flags & IOMAP_NOWAIT) {
error = -EAGAIN;
goto out_unlock;
}
/* may drop and re-acquire the ilock */ /* may drop and re-acquire the ilock */
error = xfs_reflink_allocate_cow(ip, &imap, &shared, error = xfs_reflink_allocate_cow(ip, &imap, &shared,
&lockmode); &lockmode);
...@@ -1032,6 +1046,14 @@ xfs_file_iomap_begin( ...@@ -1032,6 +1046,14 @@ xfs_file_iomap_begin(
} }
if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) { if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
/*
* If nowait is set bail since we are going to make
* allocations.
*/
if (flags & IOMAP_NOWAIT) {
error = -EAGAIN;
goto out_unlock;
}
/* /*
* We cap the maximum length we map here to MAX_WRITEBACK_PAGES * We cap the maximum length we map here to MAX_WRITEBACK_PAGES
* pages to keep the chunks of work done where somewhat symmetric * pages to keep the chunks of work done where somewhat symmetric
......
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