diff options
Diffstat (limited to 'extent_io.c')
-rw-r--r-- | extent_io.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/extent_io.c b/extent_io.c index 973e918..5093aeb 100644 --- a/extent_io.c +++ b/extent_io.c @@ -27,8 +27,11 @@ #include "kerncompat.h" #include "extent_io.h" #include "list.h" +#include "ctree.h" +#include "volumes.h" -u64 cache_max = 1024 * 1024 * 32; +u64 cache_soft_max = 1024 * 1024 * 256; +u64 cache_hard_max = 1 * 1024 * 1024 * 1024; void extent_io_tree_init(struct extent_io_tree *tree) { @@ -47,7 +50,7 @@ static struct extent_state *alloc_extent_state(void) return NULL; state->refs = 1; state->state = 0; - state->private = 0; + state->xprivate = 0; return state; } @@ -299,9 +302,11 @@ int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 last_start; u64 last_end; again: - prealloc = alloc_extent_state(); - if (!prealloc) - return -ENOMEM; + if (!prealloc) { + prealloc = alloc_extent_state(); + if (!prealloc) + return -ENOMEM; + } /* * this search will find the extents that end after @@ -508,7 +513,7 @@ int set_state_private(struct extent_io_tree *tree, u64 start, u64 private) ret = -ENOENT; goto out; } - state->private = private; + state->xprivate = private; out: return ret; } @@ -529,7 +534,7 @@ int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private) ret = -ENOENT; goto out; } - *private = state->private; + *private = state->xprivate; out: return ret; } @@ -540,18 +545,19 @@ static int free_some_buffers(struct extent_io_tree *tree) struct extent_buffer *eb; struct list_head *node, *next; - if (tree->cache_size < cache_max) + if (tree->cache_size < cache_soft_max) return 0; + list_for_each_safe(node, next, &tree->lru) { eb = list_entry(node, struct extent_buffer, lru); if (eb->refs == 1) { free_extent_buffer(eb); - if (tree->cache_size < cache_max) + if (tree->cache_size < cache_hard_max) break; } else { list_move_tail(&eb->lru, &tree->lru); } - if (nrscan++ > 64) + if (nrscan++ > 64 && tree->cache_size < cache_hard_max) break; } return 0; @@ -661,13 +667,14 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, return eb; } -int read_extent_from_disk(struct extent_buffer *eb) +int read_extent_from_disk(struct extent_buffer *eb, + unsigned long offset, unsigned long len) { int ret; - ret = pread(eb->fd, eb->data, eb->len, eb->dev_bytenr); + ret = pread(eb->fd, eb->data + offset, len, eb->dev_bytenr); if (ret < 0) goto out; - if (ret != eb->len) { + if (ret != len) { ret = -EIO; goto out; } @@ -691,6 +698,55 @@ out: return ret; } +int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset, + u64 bytes, int mirror) +{ + struct btrfs_multi_bio *multi = NULL; + struct btrfs_device *device; + u64 bytes_left = bytes; + u64 read_len; + u64 total_read = 0; + int ret; + + while (bytes_left) { + read_len = bytes_left; + ret = btrfs_map_block(&info->mapping_tree, READ, offset, + &read_len, &multi, mirror, NULL); + if (ret) { + fprintf(stderr, "Couldn't map the block %Lu\n", + offset); + return -EIO; + } + device = multi->stripes[0].dev; + + read_len = min(bytes_left, read_len); + if (device->fd == 0) { + kfree(multi); + return -EIO; + } + + ret = pread(device->fd, buf + total_read, read_len, + multi->stripes[0].physical); + kfree(multi); + if (ret < 0) { + fprintf(stderr, "Error reading %Lu, %d\n", offset, + ret); + return ret; + } + if (ret != read_len) { + fprintf(stderr, "Short read for %Lu, read %d, " + "read_len %Lu\n", offset, ret, read_len); + return -EIO; + } + + bytes_left -= read_len; + offset += read_len; + total_read += read_len; + } + + return 0; +} + int set_extent_buffer_uptodate(struct extent_buffer *eb) { eb->flags |= EXTENT_UPTODATE; @@ -706,6 +762,9 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree, int extent_buffer_uptodate(struct extent_buffer *eb) { + if (!eb) + return 0; + if (eb->flags & EXTENT_UPTODATE) return 1; return 0; |