Skip to content

Commit 6c457c2

Browse files
maharmstonekdave
authored andcommitted
btrfs: change btrfs_encoded_read() so that reading of extent is done by caller
Change the behaviour of btrfs_encoded_read() so that if it needs to read an extent from disk, it leaves the extent and inode locked and returns -EIOCBQUEUED. The caller is then responsible for doing the I/O via btrfs_encoded_read_regular() and unlocking the extent and inode. Signed-off-by: Mark Harmstone <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 028b7bd commit 6c457c2

File tree

3 files changed

+66
-32
lines changed

3 files changed

+66
-32
lines changed

fs/btrfs/btrfs_inode.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,14 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
615615
u64 disk_bytenr, u64 disk_io_size,
616616
struct page **pages);
617617
ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
618-
struct btrfs_ioctl_encoded_io_args *encoded);
618+
struct btrfs_ioctl_encoded_io_args *encoded,
619+
struct extent_state **cached_state,
620+
u64 *disk_bytenr, u64 *disk_io_size);
621+
ssize_t btrfs_encoded_read_regular(struct kiocb *iocb, struct iov_iter *iter,
622+
u64 start, u64 lockend,
623+
struct extent_state **cached_state,
624+
u64 disk_bytenr, u64 disk_io_size,
625+
size_t count, bool compressed, bool *unlocked);
619626
ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
620627
const struct btrfs_ioctl_encoded_io_args *encoded);
621628

fs/btrfs/inode.c

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9122,13 +9122,11 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
91229122
return blk_status_to_errno(READ_ONCE(priv.status));
91239123
}
91249124

9125-
static ssize_t btrfs_encoded_read_regular(struct kiocb *iocb,
9126-
struct iov_iter *iter,
9127-
u64 start, u64 lockend,
9128-
struct extent_state **cached_state,
9129-
u64 disk_bytenr, u64 disk_io_size,
9130-
size_t count, bool compressed,
9131-
bool *unlocked)
9125+
ssize_t btrfs_encoded_read_regular(struct kiocb *iocb, struct iov_iter *iter,
9126+
u64 start, u64 lockend,
9127+
struct extent_state **cached_state,
9128+
u64 disk_bytenr, u64 disk_io_size,
9129+
size_t count, bool compressed, bool *unlocked)
91329130
{
91339131
struct btrfs_inode *inode = BTRFS_I(file_inode(iocb->ki_filp));
91349132
struct extent_io_tree *io_tree = &inode->io_tree;
@@ -9189,15 +9187,16 @@ static ssize_t btrfs_encoded_read_regular(struct kiocb *iocb,
91899187
}
91909188

91919189
ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
9192-
struct btrfs_ioctl_encoded_io_args *encoded)
9190+
struct btrfs_ioctl_encoded_io_args *encoded,
9191+
struct extent_state **cached_state,
9192+
u64 *disk_bytenr, u64 *disk_io_size)
91939193
{
91949194
struct btrfs_inode *inode = BTRFS_I(file_inode(iocb->ki_filp));
91959195
struct btrfs_fs_info *fs_info = inode->root->fs_info;
91969196
struct extent_io_tree *io_tree = &inode->io_tree;
91979197
ssize_t ret;
91989198
size_t count = iov_iter_count(iter);
9199-
u64 start, lockend, disk_bytenr, disk_io_size;
9200-
struct extent_state *cached_state = NULL;
9199+
u64 start, lockend;
92019200
struct extent_map *em;
92029201
bool unlocked = false;
92039202

@@ -9223,13 +9222,13 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
92239222
lockend - start + 1);
92249223
if (ret)
92259224
goto out_unlock_inode;
9226-
lock_extent(io_tree, start, lockend, &cached_state);
9225+
lock_extent(io_tree, start, lockend, cached_state);
92279226
ordered = btrfs_lookup_ordered_range(inode, start,
92289227
lockend - start + 1);
92299228
if (!ordered)
92309229
break;
92319230
btrfs_put_ordered_extent(ordered);
9232-
unlock_extent(io_tree, start, lockend, &cached_state);
9231+
unlock_extent(io_tree, start, lockend, cached_state);
92339232
cond_resched();
92349233
}
92359234

@@ -9249,7 +9248,7 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
92499248
free_extent_map(em);
92509249
em = NULL;
92519250
ret = btrfs_encoded_read_inline(iocb, iter, start, lockend,
9252-
&cached_state, extent_start,
9251+
cached_state, extent_start,
92539252
count, encoded, &unlocked);
92549253
goto out_em;
92559254
}
@@ -9262,12 +9261,12 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
92629261
inode->vfs_inode.i_size) - iocb->ki_pos;
92639262
if (em->disk_bytenr == EXTENT_MAP_HOLE ||
92649263
(em->flags & EXTENT_FLAG_PREALLOC)) {
9265-
disk_bytenr = EXTENT_MAP_HOLE;
9264+
*disk_bytenr = EXTENT_MAP_HOLE;
92669265
count = min_t(u64, count, encoded->len);
92679266
encoded->len = count;
92689267
encoded->unencoded_len = count;
92699268
} else if (extent_map_is_compressed(em)) {
9270-
disk_bytenr = em->disk_bytenr;
9269+
*disk_bytenr = em->disk_bytenr;
92719270
/*
92729271
* Bail if the buffer isn't large enough to return the whole
92739272
* compressed extent.
@@ -9276,7 +9275,7 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
92769275
ret = -ENOBUFS;
92779276
goto out_em;
92789277
}
9279-
disk_io_size = em->disk_num_bytes;
9278+
*disk_io_size = em->disk_num_bytes;
92809279
count = em->disk_num_bytes;
92819280
encoded->unencoded_len = em->ram_bytes;
92829281
encoded->unencoded_offset = iocb->ki_pos - (em->start - em->offset);
@@ -9286,44 +9285,42 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
92869285
goto out_em;
92879286
encoded->compression = ret;
92889287
} else {
9289-
disk_bytenr = extent_map_block_start(em) + (start - em->start);
9288+
*disk_bytenr = extent_map_block_start(em) + (start - em->start);
92909289
if (encoded->len > count)
92919290
encoded->len = count;
92929291
/*
92939292
* Don't read beyond what we locked. This also limits the page
92949293
* allocations that we'll do.
92959294
*/
9296-
disk_io_size = min(lockend + 1, iocb->ki_pos + encoded->len) - start;
9297-
count = start + disk_io_size - iocb->ki_pos;
9295+
*disk_io_size = min(lockend + 1, iocb->ki_pos + encoded->len) - start;
9296+
count = start + *disk_io_size - iocb->ki_pos;
92989297
encoded->len = count;
92999298
encoded->unencoded_len = count;
9300-
disk_io_size = ALIGN(disk_io_size, fs_info->sectorsize);
9299+
*disk_io_size = ALIGN(*disk_io_size, fs_info->sectorsize);
93019300
}
93029301
free_extent_map(em);
93039302
em = NULL;
93049303

9305-
if (disk_bytenr == EXTENT_MAP_HOLE) {
9306-
unlock_extent(io_tree, start, lockend, &cached_state);
9304+
if (*disk_bytenr == EXTENT_MAP_HOLE) {
9305+
unlock_extent(io_tree, start, lockend, cached_state);
93079306
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
93089307
unlocked = true;
93099308
ret = iov_iter_zero(count, iter);
93109309
if (ret != count)
93119310
ret = -EFAULT;
93129311
} else {
9313-
ret = btrfs_encoded_read_regular(iocb, iter, start, lockend,
9314-
&cached_state, disk_bytenr,
9315-
disk_io_size, count,
9316-
encoded->compression,
9317-
&unlocked);
9312+
ret = -EIOCBQUEUED;
9313+
goto out_em;
93189314
}
93199315

93209316
out_em:
93219317
free_extent_map(em);
93229318
out_unlock_extent:
9323-
if (!unlocked)
9324-
unlock_extent(io_tree, start, lockend, &cached_state);
9319+
/* Leave inode and extent locked if we need to do a read. */
9320+
if (!unlocked && ret != -EIOCBQUEUED)
9321+
unlock_extent(io_tree, start, lockend, cached_state);
93259322
out_unlock_inode:
9326-
if (!unlocked)
9323+
if (!unlocked && ret != -EIOCBQUEUED)
93279324
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
93289325
return ret;
93299326
}

fs/btrfs/ioctl.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4513,12 +4513,17 @@ static int btrfs_ioctl_encoded_read(struct file *file, void __user *argp,
45134513
size_t copy_end_kernel = offsetofend(struct btrfs_ioctl_encoded_io_args,
45144514
flags);
45154515
size_t copy_end;
4516+
struct btrfs_inode *inode = BTRFS_I(file_inode(file));
4517+
struct btrfs_fs_info *fs_info = inode->root->fs_info;
4518+
struct extent_io_tree *io_tree = &inode->io_tree;
45164519
struct iovec iovstack[UIO_FASTIOV];
45174520
struct iovec *iov = iovstack;
45184521
struct iov_iter iter;
45194522
loff_t pos;
45204523
struct kiocb kiocb;
45214524
ssize_t ret;
4525+
u64 disk_bytenr, disk_io_size;
4526+
struct extent_state *cached_state = NULL;
45224527

45234528
if (!capable(CAP_SYS_ADMIN)) {
45244529
ret = -EPERM;
@@ -4571,7 +4576,32 @@ static int btrfs_ioctl_encoded_read(struct file *file, void __user *argp,
45714576
init_sync_kiocb(&kiocb, file);
45724577
kiocb.ki_pos = pos;
45734578

4574-
ret = btrfs_encoded_read(&kiocb, &iter, &args);
4579+
ret = btrfs_encoded_read(&kiocb, &iter, &args, &cached_state,
4580+
&disk_bytenr, &disk_io_size);
4581+
4582+
if (ret == -EIOCBQUEUED) {
4583+
bool unlocked = false;
4584+
u64 start, lockend, count;
4585+
4586+
start = ALIGN_DOWN(kiocb.ki_pos, fs_info->sectorsize);
4587+
lockend = start + BTRFS_MAX_UNCOMPRESSED - 1;
4588+
4589+
if (args.compression)
4590+
count = disk_io_size;
4591+
else
4592+
count = args.len;
4593+
4594+
ret = btrfs_encoded_read_regular(&kiocb, &iter, start, lockend,
4595+
&cached_state, disk_bytenr,
4596+
disk_io_size, count,
4597+
args.compression, &unlocked);
4598+
4599+
if (!unlocked) {
4600+
unlock_extent(io_tree, start, lockend, &cached_state);
4601+
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
4602+
}
4603+
}
4604+
45754605
if (ret >= 0) {
45764606
fsnotify_access(file);
45774607
if (copy_to_user(argp + copy_end,

0 commit comments

Comments
 (0)