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: Goldwyn Rodrigues <rgoldwyn@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
728fbc0e10
commit
29a5d29ec1
|
@ -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(
|
||||||
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(
|
||||||
* 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(
|
||||||
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(
|
||||||
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(
|
||||||
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(
|
||||||
|
|
||||||
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(
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue