* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
-#define _XOPEN_SOURCE 600
-#define __USE_XOPEN2K
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "list.h"
#include "ctree.h"
#include "volumes.h"
-
-u64 cache_soft_max = 1024 * 1024 * 256;
-u64 cache_hard_max = 1 * 1024 * 1024 * 1024;
+#include "internal.h"
void extent_io_tree_init(struct extent_io_tree *tree)
{
while(!list_empty(&tree->lru)) {
eb = list_entry(tree->lru.next, struct extent_buffer, lru);
- if (eb->refs != 1) {
- fprintf(stderr, "extent buffer leak: "
- "start %llu len %u\n",
- (unsigned long long)eb->start, eb->len);
- eb->refs = 1;
- }
+ fprintf(stderr, "extent buffer leak: "
+ "start %llu len %u\n",
+ (unsigned long long)eb->start, eb->len);
free_extent_buffer(eb);
}
int set = 0;
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
return ret;
}
-static int free_some_buffers(struct extent_io_tree *tree)
-{
- u32 nrscan = 0;
- struct extent_buffer *eb;
- struct list_head *node, *next;
-
- 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_hard_max)
- break;
- } else {
- list_move_tail(&eb->lru, &tree->lru);
- }
- if (nrscan++ > 64 && tree->cache_size < cache_hard_max)
- break;
- }
- return 0;
-}
-
static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
u64 bytenr, u32 blocksize)
{
struct extent_buffer *eb;
- int ret;
- eb = malloc(sizeof(struct extent_buffer) + blocksize);
- if (!eb) {
- BUG();
+ eb = calloc(1, sizeof(struct extent_buffer) + blocksize);
+ if (!eb)
return NULL;
- }
- memset(eb, 0, sizeof(struct extent_buffer) + blocksize);
eb->start = bytenr;
eb->len = blocksize;
- eb->refs = 2;
+ eb->refs = 1;
eb->flags = 0;
eb->tree = tree;
eb->fd = -1;
eb->dev_bytenr = (u64)-1;
eb->cache_node.start = bytenr;
eb->cache_node.size = blocksize;
+ INIT_LIST_HEAD(&eb->recow);
- free_some_buffers(tree);
- ret = insert_cache_extent(&tree->cache, &eb->cache_node);
- if (ret) {
- free(eb);
- return NULL;
- }
- list_add_tail(&eb->lru, &tree->lru);
- tree->cache_size += blocksize;
return eb;
}
+struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src)
+{
+ struct extent_buffer *new;
+
+ new = __alloc_extent_buffer(NULL, src->start, src->len);
+ if (!new)
+ return NULL;
+
+ copy_extent_buffer(new, src, 0, 0, src->len);
+ new->flags |= EXTENT_BUFFER_DUMMY;
+
+ return new;
+}
+
void free_extent_buffer(struct extent_buffer *eb)
{
- if (!eb)
+ if (!eb || IS_ERR(eb))
return;
eb->refs--;
struct extent_io_tree *tree = eb->tree;
BUG_ON(eb->flags & EXTENT_DIRTY);
list_del_init(&eb->lru);
- remove_cache_extent(&tree->cache, &eb->cache_node);
- BUG_ON(tree->cache_size < eb->len);
- tree->cache_size -= eb->len;
+ list_del_init(&eb->recow);
+ if (!(eb->flags & EXTENT_BUFFER_DUMMY)) {
+ BUG_ON(tree->cache_size < eb->len);
+ remove_cache_extent(&tree->cache, &eb->cache_node);
+ tree->cache_size -= eb->len;
+ }
free(eb);
}
}
list_move_tail(&eb->lru, &tree->lru);
eb->refs++;
} else {
+ int ret;
+
if (cache) {
eb = container_of(cache, struct extent_buffer,
cache_node);
free_extent_buffer(eb);
}
eb = __alloc_extent_buffer(tree, bytenr, blocksize);
+ if (!eb)
+ return NULL;
+ ret = insert_cache_extent(&tree->cache, &eb->cache_node);
+ if (ret) {
+ free(eb);
+ return NULL;
+ }
+ list_add_tail(&eb->lru, &tree->lru);
+ tree->cache_size += blocksize;
}
return eb;
}
{
int ret;
ret = pread(eb->fd, eb->data + offset, len, eb->dev_bytenr);
- if (ret < 0)
+ if (ret < 0) {
+ ret = -errno;
goto out;
+ }
if (ret != len) {
ret = -EIO;
goto out;
device = multi->stripes[0].dev;
read_len = min(bytes_left, read_len);
- if (device->fd == 0) {
+ if (device->fd <= 0) {
kfree(multi);
return -EIO;
}
u64 stripe_len = this_len;
this_len = min(this_len, bytes_left);
- this_len = min(this_len, (u64)info->tree_root->leafsize);
+ this_len = min(this_len, (u64)info->tree_root->nodesize);
eb = malloc(sizeof(struct extent_buffer) + this_len);
- BUG_ON(!eb);
+ if (!eb) {
+ fprintf(stderr, "cannot allocate memory for eb\n");
+ ret = -ENOMEM;
+ goto out;
+ }
memset(eb, 0, sizeof(struct extent_buffer) + this_len);
eb->start = offset;
raid_map = NULL;
} else while (dev_nr < multi->num_stripes) {
device = multi->stripes[dev_nr].dev;
- if (device->fd == 0) {
+ if (device->fd <= 0) {
kfree(multi);
return -EIO;
}
multi = NULL;
}
return 0;
-}
-
-
-int set_extent_buffer_uptodate(struct extent_buffer *eb)
-{
- eb->flags |= EXTENT_UPTODATE;
- return 0;
-}
-int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
- struct extent_buffer *eb)
-{
- eb->flags &= ~EXTENT_UPTODATE;
- return 0;
-}
-
-int extent_buffer_uptodate(struct extent_buffer *eb)
-{
- if (!eb)
- return 0;
-
- if (eb->flags & EXTENT_UPTODATE)
- return 1;
- return 0;
+out:
+ kfree(raid_map);
+ return ret;
}
int set_extent_buffer_dirty(struct extent_buffer *eb)
memcpy(dst->data + dst_offset, src->data + src_offset, len);
}
-void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
- unsigned long src_offset, unsigned long len)
-{
- memcpy(dst->data + dst_offset, dst->data + src_offset, len);
-}
-
void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
unsigned long src_offset, unsigned long len)
{
{
memset(eb->data + start, c, len);
}
+
+int extent_buffer_test_bit(struct extent_buffer *eb, unsigned long start,
+ unsigned long nr)
+{
+ return le_test_bit(nr, (u8 *)eb->data + start);
+}