Skip to content

Commit 1881fba

Browse files
osandovkdave
authored andcommittedMar 14, 2022
btrfs: add BTRFS_IOC_ENCODED_READ ioctl
There are 4 main cases: 1. Inline extents: we copy the data straight out of the extent buffer. 2. Hole/preallocated extents: we fill in zeroes. 3. Regular, uncompressed extents: we read the sectors we need directly from disk. 4. Regular, compressed extents: we read the entire compressed extent from disk and indicate what subset of the decompressed extent is in the file. This initial implementation simplifies a few things that can be improved in the future: - Cases 1, 3, and 4 allocate temporary memory to read into before copying out to userspace. - We don't do read repair, because it turns out that read repair is currently broken for compressed data. - We hold the inode lock during the operation. Note that we don't need to hold the mmap lock. We may race with btrfs_page_mkwrite() and read the old data from before the page was dirtied: btrfs_page_mkwrite btrfs_encoded_read --------------------------------------------------- (enter) (enter) btrfs_wait_ordered_range lock_extent_bits btrfs_page_set_dirty unlock_extent_cached (exit) lock_extent_bits read extent (dirty page hasn't been flushed, so this is the old data) unlock_extent_cached (exit) we read the old data from before the page was dirtied. But, that's true even if we were to hold the mmap lock: btrfs_page_mkwrite btrfs_encoded_read ------------------------------------------------------------------- (enter) (enter) btrfs_inode_lock(BTRFS_ILOCK_MMAP) down_read(i_mmap_lock) (blocked) btrfs_wait_ordered_range lock_extent_bits read extent (page hasn't been dirtied, so this is the old data) unlock_extent_cached btrfs_inode_unlock(BTRFS_ILOCK_MMAP) down_read(i_mmap_lock) returns lock_extent_bits btrfs_page_set_dirty unlock_extent_cached In other words, this is inherently racy, so it's fine that we return the old data in this tiny window. Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent dcb77a9 commit 1881fba

File tree

3 files changed

+608
-0
lines changed

3 files changed

+608
-0
lines changed
 

‎fs/btrfs/ctree.h

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ extern struct kmem_cache *btrfs_free_space_bitmap_cachep;
4949
struct btrfs_ordered_sum;
5050
struct btrfs_ref;
5151
struct btrfs_bio;
52+
struct btrfs_ioctl_encoded_io_args;
5253

5354
#define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */
5455

@@ -3305,6 +3306,9 @@ int btrfs_writepage_cow_fixup(struct page *page);
33053306
void btrfs_writepage_endio_finish_ordered(struct btrfs_inode *inode,
33063307
struct page *page, u64 start,
33073308
u64 end, bool uptodate);
3309+
ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
3310+
struct btrfs_ioctl_encoded_io_args *encoded);
3311+
33083312
extern const struct dentry_operations btrfs_dentry_operations;
33093313
extern const struct iomap_ops btrfs_dio_iomap_ops;
33103314
extern const struct iomap_dio_ops btrfs_dio_ops;

0 commit comments

Comments
 (0)