summaryrefslogtreecommitdiff
path: root/extent_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'extent_io.c')
-rw-r--r--extent_io.c85
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;