Skip to content

Commit 29a5d29

Browse files
goldwynraxboe
authored andcommitted
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>
1 parent 728fbc0 commit 29a5d29

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

fs/xfs/xfs_file.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,11 @@ xfs_file_dax_read(
237237
if (!count)
238238
return 0; /* skip atime */
239239

240-
xfs_ilock(ip, XFS_IOLOCK_SHARED);
240+
if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
241+
if (iocb->ki_flags & IOCB_NOWAIT)
242+
return -EAGAIN;
243+
xfs_ilock(ip, XFS_IOLOCK_SHARED);
244+
}
241245
ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);
242246
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
243247

@@ -541,7 +545,11 @@ xfs_file_dio_aio_write(
541545
iolock = XFS_IOLOCK_SHARED;
542546
}
543547

544-
xfs_ilock(ip, iolock);
548+
if (!xfs_ilock_nowait(ip, iolock)) {
549+
if (iocb->ki_flags & IOCB_NOWAIT)
550+
return -EAGAIN;
551+
xfs_ilock(ip, iolock);
552+
}
545553

546554
ret = xfs_file_aio_write_checks(iocb, from, &iolock);
547555
if (ret)
@@ -553,9 +561,15 @@ xfs_file_dio_aio_write(
553561
* otherwise demote the lock if we had to take the exclusive lock
554562
* for other reasons in xfs_file_aio_write_checks.
555563
*/
556-
if (unaligned_io)
557-
inode_dio_wait(inode);
558-
else if (iolock == XFS_IOLOCK_EXCL) {
564+
if (unaligned_io) {
565+
/* If we are going to wait for other DIO to finish, bail */
566+
if (iocb->ki_flags & IOCB_NOWAIT) {
567+
if (atomic_read(&inode->i_dio_count))
568+
return -EAGAIN;
569+
} else {
570+
inode_dio_wait(inode);
571+
}
572+
} else if (iolock == XFS_IOLOCK_EXCL) {
559573
xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
560574
iolock = XFS_IOLOCK_SHARED;
561575
}
@@ -585,7 +599,12 @@ xfs_file_dax_write(
585599
size_t count;
586600
loff_t pos;
587601

588-
xfs_ilock(ip, iolock);
602+
if (!xfs_ilock_nowait(ip, iolock)) {
603+
if (iocb->ki_flags & IOCB_NOWAIT)
604+
return -EAGAIN;
605+
xfs_ilock(ip, iolock);
606+
}
607+
589608
ret = xfs_file_aio_write_checks(iocb, from, &iolock);
590609
if (ret)
591610
goto out;
@@ -892,6 +911,7 @@ xfs_file_open(
892911
return -EFBIG;
893912
if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
894913
return -EIO;
914+
file->f_mode |= FMODE_AIO_NOWAIT;
895915
return 0;
896916
}
897917

fs/xfs/xfs_iomap.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,11 @@ xfs_file_iomap_begin(
995995
lockmode = xfs_ilock_data_map_shared(ip);
996996
}
997997

998+
if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) {
999+
error = -EAGAIN;
1000+
goto out_unlock;
1001+
}
1002+
9981003
ASSERT(offset <= mp->m_super->s_maxbytes);
9991004
if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes)
10001005
length = mp->m_super->s_maxbytes - offset;
@@ -1016,6 +1021,15 @@ xfs_file_iomap_begin(
10161021

10171022
if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
10181023
if (flags & IOMAP_DIRECT) {
1024+
/*
1025+
* A reflinked inode will result in CoW alloc.
1026+
* FIXME: It could still overwrite on unshared extents
1027+
* and not need allocation.
1028+
*/
1029+
if (flags & IOMAP_NOWAIT) {
1030+
error = -EAGAIN;
1031+
goto out_unlock;
1032+
}
10191033
/* may drop and re-acquire the ilock */
10201034
error = xfs_reflink_allocate_cow(ip, &imap, &shared,
10211035
&lockmode);
@@ -1032,6 +1046,14 @@ xfs_file_iomap_begin(
10321046
}
10331047

10341048
if ((flags & IOMAP_WRITE) && imap_needs_alloc(inode, &imap, nimaps)) {
1049+
/*
1050+
* If nowait is set bail since we are going to make
1051+
* allocations.
1052+
*/
1053+
if (flags & IOMAP_NOWAIT) {
1054+
error = -EAGAIN;
1055+
goto out_unlock;
1056+
}
10351057
/*
10361058
* We cap the maximum length we map here to MAX_WRITEBACK_PAGES
10371059
* pages to keep the chunks of work done where somewhat symmetric

0 commit comments

Comments
 (0)