mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-29 00:42:45 +00:00
btrfs-progs: use read_data_from_disk() to replace read_extent_from_disk() and replace read_extent_data()
The function read_extent_from_disk() is only a wrapper to read tree block. And read_extent_data() is just a while loop to eliminate short read caused by stripe boundary. In fact, a lot of call sites of read_extent_data() are either reading metadata (thus no possible short read) or doing extra loop by themselves. This patch will replace those two functions with read_data_from_disk(), making it the only entrance for data/metadata read. And update read_data_from_disk() to return the read bytes, so caller can do a simple while loop. For the few callers of read_extent_data(), open-code a small while loop for them. This will allow later RAID56 read repair using P/Q much easier. Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
2a93728391
commit
3ff9d35257
@ -40,36 +40,18 @@ static int debug_corrupt_block(struct extent_buffer *eb,
|
||||
struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 copy)
|
||||
{
|
||||
int ret;
|
||||
u64 length;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
struct btrfs_device *device;
|
||||
int num_copies;
|
||||
int mirror_num = 1;
|
||||
|
||||
length = blocksize;
|
||||
while (1) {
|
||||
ret = btrfs_map_block(root->fs_info, READ, eb->start, &length,
|
||||
&multi, mirror_num, NULL);
|
||||
if (ret) {
|
||||
error("cannot map block %llu length %llu mirror %d: %d",
|
||||
(unsigned long long)eb->start,
|
||||
(unsigned long long)length,
|
||||
mirror_num, ret);
|
||||
return ret;
|
||||
}
|
||||
device = multi->stripes[0].dev;
|
||||
eb->fd = device->fd;
|
||||
device->total_ios++;
|
||||
eb->dev_bytenr = multi->stripes[0].physical;
|
||||
|
||||
fprintf(stdout,
|
||||
"mirror %d logical %llu physical %llu device %s\n",
|
||||
mirror_num, (unsigned long long)bytenr,
|
||||
(unsigned long long)eb->dev_bytenr, device->name);
|
||||
free(multi);
|
||||
|
||||
if (!copy || mirror_num == copy) {
|
||||
ret = read_extent_from_disk(eb, 0, eb->len);
|
||||
u64 read_len = eb->len;
|
||||
|
||||
ret = read_data_from_disk(eb->fs_info, eb->data,
|
||||
eb->start, &read_len,
|
||||
mirror_num);
|
||||
if (read_len < eb->len)
|
||||
ret = -EIO;
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
error("cannot read eb bytenr %llu: %m",
|
||||
|
@ -173,8 +173,9 @@ static int write_extent_content(struct btrfs_fs_info *fs_info, int out_fd,
|
||||
|
||||
while (cur_offset < length) {
|
||||
cur_len = min_t(u64, length - cur_offset, BUFFER_SIZE);
|
||||
ret = read_extent_data(fs_info, buffer,
|
||||
logical + cur_offset, &cur_len, mirror);
|
||||
ret = read_data_from_disk(fs_info, buffer,
|
||||
logical + cur_offset, &cur_len,
|
||||
mirror);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
fprintf(stderr,
|
||||
|
@ -337,7 +337,8 @@ static int populate_csum(struct btrfs_trans_handle *trans,
|
||||
|
||||
while (offset < len) {
|
||||
sectorsize = fs_info->sectorsize;
|
||||
ret = read_extent_data(fs_info, buf, start + offset, §orsize, 0);
|
||||
ret = read_data_from_disk(fs_info, buf, start + offset,
|
||||
§orsize, 0);
|
||||
if (ret)
|
||||
break;
|
||||
ret = btrfs_csum_file_block(trans, start + len, start + offset,
|
||||
|
@ -5840,7 +5840,7 @@ static int check_extent_csums(struct btrfs_root *root, u64 bytenr,
|
||||
for (mirror = 1; mirror <= num_copies; mirror++) {
|
||||
read_len = num_bytes - offset;
|
||||
/* read as much space once a time */
|
||||
ret = read_extent_data(gfs_info, (char *)data + offset,
|
||||
ret = read_data_from_disk(gfs_info, (char *)data + offset,
|
||||
bytenr + offset, &read_len, mirror);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -1203,8 +1203,8 @@ static int populate_csum(struct btrfs_trans_handle *trans,
|
||||
|
||||
while (offset < len) {
|
||||
sectorsize = gfs_info->sectorsize;
|
||||
ret = read_extent_data(gfs_info, buf, start + offset,
|
||||
§orsize, 0);
|
||||
ret = read_data_from_disk(gfs_info, buf, start + offset,
|
||||
§orsize, 0);
|
||||
if (ret)
|
||||
break;
|
||||
ret = btrfs_csum_file_block(trans, start + len, start + offset,
|
||||
|
@ -407,8 +407,8 @@ again:
|
||||
cur = bytenr;
|
||||
while (cur < bytenr + size_left) {
|
||||
length = bytenr + size_left - cur;
|
||||
ret = read_extent_data(root->fs_info, inbuf + cur - bytenr, cur,
|
||||
&length, mirror_num);
|
||||
ret = read_data_from_disk(root->fs_info, inbuf + cur - bytenr, cur,
|
||||
&length, mirror_num);
|
||||
if (ret < 0) {
|
||||
mirror_num++;
|
||||
if (mirror_num > num_copies) {
|
||||
|
@ -615,7 +615,7 @@ static int read_data_extent(struct metadump_struct *md,
|
||||
for (cur_mirror = 1; cur_mirror <= num_copies; cur_mirror++) {
|
||||
while (bytes_left) {
|
||||
read_len = bytes_left;
|
||||
ret = read_extent_data(fs_info,
|
||||
ret = read_data_from_disk(fs_info,
|
||||
(char *)(async->buffer + offset),
|
||||
logical, &read_len, cur_mirror);
|
||||
if (ret < 0)
|
||||
|
@ -319,45 +319,20 @@ static int read_on_restore(struct extent_buffer *eb)
|
||||
int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirror)
|
||||
{
|
||||
unsigned long offset = 0;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
struct btrfs_device *device;
|
||||
int ret = 0;
|
||||
u64 read_len;
|
||||
unsigned long bytes_left = eb->len;
|
||||
|
||||
while (bytes_left) {
|
||||
read_len = bytes_left;
|
||||
device = NULL;
|
||||
u64 read_len = bytes_left;
|
||||
|
||||
if (info->on_restoring)
|
||||
return read_on_restore(eb);
|
||||
|
||||
ret = btrfs_map_block(info, READ, eb->start + offset,
|
||||
&read_len, &multi, mirror, NULL);
|
||||
if (ret) {
|
||||
printk("Couldn't map the block %llu\n", eb->start + offset);
|
||||
kfree(multi);
|
||||
return -EIO;
|
||||
}
|
||||
device = multi->stripes[0].dev;
|
||||
|
||||
if (device->fd <= 0) {
|
||||
kfree(multi);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
eb->fd = device->fd;
|
||||
device->total_ios++;
|
||||
eb->dev_bytenr = multi->stripes[0].physical;
|
||||
kfree(multi);
|
||||
multi = NULL;
|
||||
|
||||
if (read_len > bytes_left)
|
||||
read_len = bytes_left;
|
||||
|
||||
ret = read_extent_from_disk(eb, offset, read_len);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
ret = read_data_from_disk(info, eb->data + offset,
|
||||
eb->start + offset, &read_len,
|
||||
mirror);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
offset += read_len;
|
||||
bytes_left -= read_len;
|
||||
}
|
||||
@ -474,42 +449,6 @@ struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int read_extent_data(struct btrfs_fs_info *fs_info, char *data, u64 logical,
|
||||
u64 *len, int mirror)
|
||||
{
|
||||
u64 offset = 0;
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
struct btrfs_device *device;
|
||||
int ret = 0;
|
||||
u64 max_len = *len;
|
||||
|
||||
ret = btrfs_map_block(fs_info, READ, logical, len, &multi, mirror,
|
||||
NULL);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Couldn't map the block %llu\n",
|
||||
logical + offset);
|
||||
goto err;
|
||||
}
|
||||
device = multi->stripes[0].dev;
|
||||
|
||||
if (*len > max_len)
|
||||
*len = max_len;
|
||||
if (device->fd < 0) {
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = btrfs_pread(device->fd, data, *len, multi->stripes[0].physical,
|
||||
fs_info->zoned);
|
||||
if (ret != *len)
|
||||
ret = -EIO;
|
||||
else
|
||||
ret = 0;
|
||||
err:
|
||||
kfree(multi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int write_and_map_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb)
|
||||
{
|
||||
int ret;
|
||||
|
@ -141,8 +141,6 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr
|
||||
struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
||||
u64 parent_transid);
|
||||
|
||||
int read_extent_data(struct btrfs_fs_info *fs_info, char *data, u64 logical,
|
||||
u64 *len, int mirror);
|
||||
void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
|
||||
u64 parent_transid);
|
||||
struct extent_buffer* btrfs_find_create_tree_block(
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "kernel-lib/list.h"
|
||||
#include "kernel-shared/ctree.h"
|
||||
#include "kernel-shared/volumes.h"
|
||||
#include "kernel-shared/disk-io.h"
|
||||
#include "common/utils.h"
|
||||
#include "common/device-utils.h"
|
||||
#include "common/internal.h"
|
||||
@ -789,69 +790,41 @@ struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_extent_from_disk(struct extent_buffer *eb,
|
||||
unsigned long offset, unsigned long len)
|
||||
{
|
||||
int ret;
|
||||
ret = btrfs_pread(eb->fd, eb->data + offset, len, eb->dev_bytenr,
|
||||
eb->fs_info->zoned);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
if (ret != len) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
ret = 0;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
|
||||
u64 bytes, int mirror)
|
||||
int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 logical,
|
||||
u64 *len, int mirror)
|
||||
{
|
||||
struct btrfs_multi_bio *multi = NULL;
|
||||
struct btrfs_device *device;
|
||||
u64 bytes_left = bytes;
|
||||
u64 read_len;
|
||||
u64 total_read = 0;
|
||||
u64 read_len = *len;
|
||||
int ret;
|
||||
|
||||
while (bytes_left) {
|
||||
read_len = bytes_left;
|
||||
ret = btrfs_map_block(info, READ, offset, &read_len, &multi,
|
||||
mirror, NULL);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Couldn't map the block %llu\n",
|
||||
offset);
|
||||
return -EIO;
|
||||
}
|
||||
device = multi->stripes[0].dev;
|
||||
ret = btrfs_map_block(info, READ, logical, &read_len, &multi, mirror,
|
||||
NULL);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Couldn't map the block %llu\n", logical);
|
||||
return -EIO;
|
||||
}
|
||||
device = multi->stripes[0].dev;
|
||||
|
||||
read_len = min(bytes_left, read_len);
|
||||
if (device->fd <= 0) {
|
||||
kfree(multi);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = btrfs_pread(device->fd, buf + total_read, read_len,
|
||||
multi->stripes[0].physical, info->zoned);
|
||||
read_len = min(*len, read_len);
|
||||
if (device->fd <= 0) {
|
||||
kfree(multi);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error reading %llu, %d\n", offset,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret != read_len) {
|
||||
fprintf(stderr, "Short read for %llu, read %d, "
|
||||
"read_len %llu\n", offset, ret, read_len);
|
||||
return -EIO;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
bytes_left -= read_len;
|
||||
offset += read_len;
|
||||
total_read += read_len;
|
||||
ret = btrfs_pread(device->fd, buf, read_len,
|
||||
multi->stripes[0].physical, info->zoned);
|
||||
kfree(multi);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error reading %llu, %d\n", logical,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret != read_len) {
|
||||
fprintf(stderr,
|
||||
"Short read for %llu, read %d, read_len %llu\n",
|
||||
logical, ret, read_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -150,8 +150,6 @@ struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
|
||||
u64 bytenr, u32 blocksize);
|
||||
void free_extent_buffer(struct extent_buffer *eb);
|
||||
void free_extent_buffer_nocache(struct extent_buffer *eb);
|
||||
int read_extent_from_disk(struct extent_buffer *eb,
|
||||
unsigned long offset, unsigned long len);
|
||||
int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv,
|
||||
unsigned long start, unsigned long len);
|
||||
void read_extent_buffer(const struct extent_buffer *eb, void *dst,
|
||||
@ -169,8 +167,8 @@ int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
|
||||
unsigned long nr);
|
||||
int set_extent_buffer_dirty(struct extent_buffer *eb);
|
||||
int clear_extent_buffer_dirty(struct extent_buffer *eb);
|
||||
int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
|
||||
u64 bytes, int mirror);
|
||||
int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 logical,
|
||||
u64 *len, int mirror);
|
||||
int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
|
||||
u64 bytes, int mirror);
|
||||
void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,
|
||||
|
@ -225,11 +225,11 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len,
|
||||
memset(dest, 0, len);
|
||||
while (1) {
|
||||
struct btrfs_file_extent_item *fi;
|
||||
u64 offset = 0;
|
||||
u64 extent_start;
|
||||
u64 extent_len;
|
||||
u64 read_start;
|
||||
u64 read_len;
|
||||
u64 read_len_ret;
|
||||
u64 disk_bytenr;
|
||||
|
||||
leaf = path.nodes[0];
|
||||
@ -282,14 +282,16 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len,
|
||||
|
||||
disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi) +
|
||||
btrfs_file_extent_offset(leaf, fi);
|
||||
read_len_ret = read_len;
|
||||
ret = read_extent_data(fs_info, dest + read_start - start, disk_bytenr,
|
||||
&read_len_ret, 0);
|
||||
if (ret < 0)
|
||||
break;
|
||||
/* Short read, something went wrong */
|
||||
if (read_len_ret != read_len)
|
||||
return -EIO;
|
||||
while (offset < read_len) {
|
||||
u64 read_len_ret = read_len - offset;
|
||||
|
||||
ret = read_data_from_disk(fs_info,
|
||||
dest + read_start - start + offset,
|
||||
disk_bytenr + offset, &read_len_ret, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
offset += read_len_ret;
|
||||
}
|
||||
read += read_len;
|
||||
next:
|
||||
ret = btrfs_next_item(root, &path);
|
||||
|
@ -118,6 +118,8 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct btrfs_root *root,
|
||||
}
|
||||
|
||||
while (total_read < io_ctl->total_size) {
|
||||
u64 offset = 0;
|
||||
|
||||
if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
|
||||
ret = btrfs_next_leaf(root, path);
|
||||
if (ret) {
|
||||
@ -150,11 +152,19 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct btrfs_root *root,
|
||||
bytenr = btrfs_file_extent_disk_bytenr(leaf, fi) +
|
||||
btrfs_file_extent_offset(leaf, fi);
|
||||
len = btrfs_file_extent_num_bytes(leaf, fi);
|
||||
ret = read_data_from_disk(root->fs_info,
|
||||
io_ctl->buffer + key.offset, bytenr,
|
||||
len, 0);
|
||||
if (ret)
|
||||
break;
|
||||
while (offset < len) {
|
||||
u64 read_len = len - offset;
|
||||
|
||||
ret = read_data_from_disk(root->fs_info,
|
||||
io_ctl->buffer + key.offset + offset,
|
||||
bytenr + offset,
|
||||
&read_len, 0);
|
||||
if (ret < 0) {
|
||||
btrfs_release_path(path);
|
||||
return ret;
|
||||
}
|
||||
offset += read_len;
|
||||
}
|
||||
total_read += len;
|
||||
path->slots[0]++;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user