diff options
author | Qu Wenruo <wqu@suse.com> | 2022-07-26 13:22:10 +0800 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-08-05 13:25:48 -0400 |
commit | 33dcce3587dc791bb260d0750813a83530530107 (patch) | |
tree | 0d25e350864fe5222f8a15fb2b67940a4534348f | |
parent | c7f18bdd457769e7d8384d422705faeb8163ec4d (diff) | |
download | u-boot-33dcce3587dc791bb260d0750813a83530530107.zip u-boot-33dcce3587dc791bb260d0750813a83530530107.tar.gz u-boot-33dcce3587dc791bb260d0750813a83530530107.tar.bz2 |
fs: btrfs: fix a bug which no data get read if the length is not 0
[BUG]
When testing with unaligned read, if a specific length is passed in,
btrfs driver will read out nothing:
=> load host 0 $kernel_addr_r 5k_file 0x1000 0
0 bytes read in 0 ms
But if no length is passed in, it works fine, even if we pass a non-zero
length:
=> load host 0 $kernel_addr_r 5k_file 0 0x1000
1024 bytes read in 0 ms
[CAUSE]
In btrfs_read() if we have a larger size than our file, we will try to
truncate it using the file size.
However the real file size is not initialized if @len is not zero, thus
we always truncate our length to 0, and cause the problem.
[FIX]
Fix it by just always do the file size check.
In fact btrfs_size() always follow soft link, thus it will return the
real file size correctly.
Signed-off-by: Qu Wenruo <wqu@suse.com>
-rw-r--r-- | fs/btrfs/btrfs.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c index 4cdbbbe..309cd59 100644 --- a/fs/btrfs/btrfs.c +++ b/fs/btrfs/btrfs.c @@ -246,16 +246,17 @@ int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len, return -EINVAL; } - if (!len) { - ret = btrfs_size(file, &real_size); - if (ret < 0) { - error("Failed to get inode size: %s", file); - return ret; - } - len = real_size; + ret = btrfs_size(file, &real_size); + if (ret < 0) { + error("Failed to get inode size: %s", file); + return ret; } - if (len > real_size - offset) + /* + * If the length is 0 (meaning read the whole file) or the range is + * beyond file size, truncate it to the end of the file. + */ + if (!len || len > real_size - offset) len = real_size - offset; ret = btrfs_file_read(root, ino, offset, len, buf); |