mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-19 11:43:40 +00:00
btrfs: don't sleep in btrfs_encoded_read() if IOCB_NOWAIT is set
Change btrfs_encoded_read() so that it returns -EAGAIN rather than sleeps if IOCB_NOWAIT is set in iocb->ki_flags. The conditions that require sleeping are: inode lock, writeback, extent lock, ordered range. Signed-off-by: Mark Harmstone <maharmstone@fb.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
26efd44796
commit
973a432637
@ -8983,12 +8983,16 @@ static ssize_t btrfs_encoded_read_inline(
|
||||
unsigned long ptr;
|
||||
void *tmp;
|
||||
ssize_t ret;
|
||||
const bool nowait = (iocb->ki_flags & IOCB_NOWAIT);
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
if (!path) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
path->nowait = nowait;
|
||||
|
||||
ret = btrfs_lookup_file_extent(NULL, root, path, btrfs_ino(inode),
|
||||
extent_start, 0);
|
||||
if (ret) {
|
||||
@ -9198,11 +9202,15 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
|
||||
size_t count = iov_iter_count(iter);
|
||||
u64 start, lockend;
|
||||
struct extent_map *em;
|
||||
const bool nowait = (iocb->ki_flags & IOCB_NOWAIT);
|
||||
bool unlocked = false;
|
||||
|
||||
file_accessed(iocb->ki_filp);
|
||||
|
||||
btrfs_inode_lock(inode, BTRFS_ILOCK_SHARED);
|
||||
ret = btrfs_inode_lock(inode,
|
||||
BTRFS_ILOCK_SHARED | (nowait ? BTRFS_ILOCK_TRY : 0));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (iocb->ki_pos >= inode->vfs_inode.i_size) {
|
||||
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
|
||||
@ -9215,21 +9223,46 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
|
||||
*/
|
||||
lockend = start + BTRFS_MAX_UNCOMPRESSED - 1;
|
||||
|
||||
for (;;) {
|
||||
if (nowait) {
|
||||
struct btrfs_ordered_extent *ordered;
|
||||
|
||||
ret = btrfs_wait_ordered_range(inode, start,
|
||||
lockend - start + 1);
|
||||
if (ret)
|
||||
if (filemap_range_needs_writeback(inode->vfs_inode.i_mapping,
|
||||
start, lockend)) {
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock_inode;
|
||||
lock_extent(io_tree, start, lockend, cached_state);
|
||||
}
|
||||
|
||||
if (!try_lock_extent(io_tree, start, lockend, cached_state)) {
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
|
||||
ordered = btrfs_lookup_ordered_range(inode, start,
|
||||
lockend - start + 1);
|
||||
if (!ordered)
|
||||
break;
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
unlock_extent(io_tree, start, lockend, cached_state);
|
||||
cond_resched();
|
||||
if (ordered) {
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
unlock_extent(io_tree, start, lockend, cached_state);
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock_inode;
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
struct btrfs_ordered_extent *ordered;
|
||||
|
||||
ret = btrfs_wait_ordered_range(inode, start,
|
||||
lockend - start + 1);
|
||||
if (ret)
|
||||
goto out_unlock_inode;
|
||||
|
||||
lock_extent(io_tree, start, lockend, cached_state);
|
||||
ordered = btrfs_lookup_ordered_range(inode, start,
|
||||
lockend - start + 1);
|
||||
if (!ordered)
|
||||
break;
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
unlock_extent(io_tree, start, lockend, cached_state);
|
||||
cond_resched();
|
||||
}
|
||||
}
|
||||
|
||||
em = btrfs_get_extent(inode, NULL, start, lockend - start + 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user