mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
nfs: add nowait version of nfs_start_io_direct
nfs_start_io_direct might block on existing operations to the same inode. In order to support NOWAIT O_DIRECT reads, add a non-blocking version of this nfs_start_io_direct that just returns -EAGAIN if locks could not be taken. Signed-off-by: Dylan Yudaken <dyudaken@gmail.com> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
This commit is contained in:
parent
1d62e659c0
commit
e3a7802944
|
|
@ -532,6 +532,7 @@ extern void nfs_end_io_read(struct inode *inode);
|
|||
extern __must_check int nfs_start_io_write(struct inode *inode);
|
||||
extern void nfs_end_io_write(struct inode *inode);
|
||||
extern __must_check int nfs_start_io_direct(struct inode *inode);
|
||||
extern __must_check int nfs_start_io_direct_nowait(struct inode *inode);
|
||||
extern void nfs_end_io_direct(struct inode *inode);
|
||||
|
||||
static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
|
||||
|
|
|
|||
41
fs/nfs/io.c
41
fs/nfs/io.c
|
|
@ -109,6 +109,16 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode)
|
|||
}
|
||||
}
|
||||
|
||||
static int nfs_block_buffered_nowait(struct nfs_inode *nfsi, struct inode *inode)
|
||||
{
|
||||
if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
|
||||
if (inode->i_mapping->nrpages != 0)
|
||||
return 1;
|
||||
set_bit(NFS_INO_ODIRECT, &nfsi->flags);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_start_io_direct - declare the file is being used for direct i/o
|
||||
* @inode: file inode
|
||||
|
|
@ -149,6 +159,37 @@ nfs_start_io_direct(struct inode *inode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_start_io_direct_nowait - non-blocking variant of nfs_start_io_direct()
|
||||
* @inode: file inode
|
||||
*
|
||||
* Try to declare that a direct I/O operation is about to start without
|
||||
* blocking.
|
||||
* Ensure all buffered I/O is blocked.
|
||||
* If this could not be done without blocking then returns -EAGAIN.
|
||||
*/
|
||||
int
|
||||
nfs_start_io_direct_nowait(struct inode *inode)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
|
||||
if (!down_read_trylock(&inode->i_rwsem))
|
||||
return -EAGAIN;
|
||||
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags))
|
||||
return 0;
|
||||
up_read(&inode->i_rwsem);
|
||||
|
||||
/* Slow path: try to flip NFS_INO_ODIRECT without blocking. */
|
||||
if (!down_write_trylock(&inode->i_rwsem))
|
||||
return -EAGAIN;
|
||||
if (nfs_block_buffered_nowait(nfsi, inode)) {
|
||||
up_write(&inode->i_rwsem);
|
||||
return -EAGAIN;
|
||||
}
|
||||
downgrade_write(&inode->i_rwsem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_end_io_direct - declare that the direct i/o operation is done
|
||||
* @inode: file inode
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user