diff options
author | Qu Wenruo <wqu@suse.com> | 2020-06-24 18:03:11 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-09-07 21:00:36 -0400 |
commit | e3427184f38a3a5d2ac9a3c200a5c3fc17592ec6 (patch) | |
tree | aa3021bacba25f9a905ad668ef8ad2136bdd7687 /fs/btrfs/btrfs.c | |
parent | 01347f64d5f86ae467141550f84ed0f97415a9ff (diff) |
fs: btrfs: Implement btrfs_file_read()
This version of btrfs_file_read() has the following new features:
- Tries all mirrors
- More handling on unaligned size
- Better compressed extent handling
The old implementation doesn't handle compressed extent with offset
properly: we need to read out the whole compressed extent, then
decompress the whole extent, and only then copy the requested part.
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Marek BehĂșn <marek.behun@nic.cz>
Diffstat (limited to 'fs/btrfs/btrfs.c')
-rw-r--r-- | fs/btrfs/btrfs.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c index 7eb01c4ff9b..f5d475205e0 100644 --- a/fs/btrfs/btrfs.c +++ b/fs/btrfs/btrfs.c @@ -253,37 +253,45 @@ out: int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, loff_t *actread) { - struct __btrfs_root root = btrfs_info.fs_root; - struct btrfs_inode_item inode; - u64 inr, rd; + struct btrfs_fs_info *fs_info = current_fs_info; + struct btrfs_root *root; + loff_t real_size = 0; + u64 ino; u8 type; + int ret; - inr = __btrfs_lookup_path(&root, root.root_dirid, file, &type, &inode, - 40); - - if (inr == -1ULL) { - printf("Cannot lookup file %s\n", file); - return -1; + ASSERT(fs_info); + ret = btrfs_lookup_path(fs_info->fs_root, BTRFS_FIRST_FREE_OBJECTID, + file, &root, &ino, &type, 40); + if (ret < 0) { + error("Cannot lookup file %s", file); + return ret; } if (type != BTRFS_FT_REG_FILE) { - printf("Not a regular file: %s\n", file); - return -1; + error("Not a regular file: %s", file); + return -EINVAL; } - if (!len) - len = inode.size; + if (!len) { + ret = btrfs_size(file, &real_size); + if (ret < 0) { + error("Failed to get inode size: %s", file); + return ret; + } + len = real_size; + } - if (len > inode.size - offset) - len = inode.size - offset; + if (len > real_size - offset) + len = real_size - offset; - rd = __btrfs_file_read(&root, inr, offset, len, buf); - if (rd == -1ULL) { - printf("An error occured while reading file %s\n", file); - return -1; + ret = btrfs_file_read(root, ino, offset, len, buf); + if (ret < 0) { + error("An error occured while reading file %s", file); + return ret; } - *actread = rd; + *actread = len; return 0; } |