aboutsummaryrefslogtreecommitdiff
path: root/fs/btrfs/btrfs.c
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2020-06-24 18:03:11 +0200
committerTom Rini <trini@konsulko.com>2020-09-07 21:00:36 -0400
commite3427184f38a3a5d2ac9a3c200a5c3fc17592ec6 (patch)
treeaa3021bacba25f9a905ad668ef8ad2136bdd7687 /fs/btrfs/btrfs.c
parent01347f64d5f86ae467141550f84ed0f97415a9ff (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.c48
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;
}