btrfs-progs: add OPEN_CTREE_INVALIDATE_FST flag
[platform/upstream/btrfs-progs.git] / extent_io.c
index 464bd07..7b9eb8e 100644 (file)
@@ -16,8 +16,6 @@
  * 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>
@@ -29,9 +27,7 @@
 #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)
 {
@@ -77,12 +73,9 @@ void extent_io_tree_cleanup(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);
        }
 
@@ -197,7 +190,7 @@ static int clear_state_bit(struct extent_io_tree *tree,
 }
 
 /*
- * set some bits on a range in the tree.
+ * clear some bits on a range in the tree.
  */
 int clear_extent_bits(struct extent_io_tree *tree, u64 start,
                      u64 end, int bits, gfp_t mask)
@@ -210,9 +203,11 @@ int clear_extent_bits(struct extent_io_tree *tree, u64 start,
        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
@@ -539,67 +534,46 @@ out:
        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--;
@@ -608,9 +582,12 @@ void free_extent_buffer(struct extent_buffer *eb)
                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);
        }
 }
@@ -659,12 +636,23 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree,
                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;
 }
@@ -674,8 +662,10 @@ int read_extent_from_disk(struct extent_buffer *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;
@@ -722,7 +712,7 @@ int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
                device = multi->stripes[0].dev;
 
                read_len = min(bytes_left, read_len);
-               if (device->fd == 0) {
+               if (device->fd <= 0) {
                        kfree(multi);
                        return -EIO;
                }
@@ -779,10 +769,14 @@ int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
                        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;
@@ -798,7 +792,7 @@ int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 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;
                        }
@@ -833,30 +827,10 @@ int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
                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)
@@ -906,12 +880,6 @@ void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
        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)
 {
@@ -923,3 +891,9 @@ void memset_extent_buffer(struct extent_buffer *eb, char c,
 {
        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);
+}