btrfs-progs: check: Avoid reading beyond item boundary for dir_item and dir_index
[platform/upstream/btrfs-progs.git] / extent_io.c
index de9e0ec..915c6ed 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,6 +27,7 @@
 #include "list.h"
 #include "ctree.h"
 #include "volumes.h"
+#include "internal.h"
 
 void extent_io_tree_init(struct extent_io_tree *tree)
 {
@@ -193,8 +192,7 @@ static int clear_state_bit(struct extent_io_tree *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)
+int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits)
 {
        struct extent_state *state;
        struct extent_state *prealloc = NULL;
@@ -288,8 +286,7 @@ search_again:
 /*
  * set some bits on a range in the tree.
  */
-int set_extent_bits(struct extent_io_tree *tree, u64 start,
-                   u64 end, int bits, gfp_t mask)
+int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits)
 {
        struct extent_state *state;
        struct extent_state *prealloc = NULL;
@@ -412,16 +409,14 @@ search_again:
        goto again;
 }
 
-int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
-                    gfp_t mask)
+int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end)
 {
-       return set_extent_bits(tree, start, end, EXTENT_DIRTY, mask);
+       return set_extent_bits(tree, start, end, EXTENT_DIRTY);
 }
 
-int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
-                      gfp_t mask)
+int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end)
 {
-       return clear_extent_bits(tree, start, end, EXTENT_DIRTY, mask);
+       return clear_extent_bits(tree, start, end, EXTENT_DIRTY);
 }
 
 int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
@@ -540,12 +535,9 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
 {
        struct extent_buffer *eb;
 
-       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;
@@ -566,7 +558,7 @@ 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 == NULL)
+       if (!new)
                return NULL;
 
        copy_extent_buffer(new, src, 0, 0, src->len);
@@ -577,7 +569,7 @@ struct extent_buffer *btrfs_clone_extent_buffer(struct extent_buffer *src)
 
 void free_extent_buffer(struct extent_buffer *eb)
 {
-       if (!eb)
+       if (!eb || IS_ERR(eb))
                return;
 
        eb->refs--;
@@ -666,8 +658,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;
@@ -714,7 +708,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;
                }
@@ -771,10 +765,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;
@@ -790,7 +788,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;
                        }
@@ -825,30 +823,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)
@@ -856,7 +834,7 @@ int set_extent_buffer_dirty(struct extent_buffer *eb)
        struct extent_io_tree *tree = eb->tree;
        if (!(eb->flags & EXTENT_DIRTY)) {
                eb->flags |= EXTENT_DIRTY;
-               set_extent_dirty(tree, eb->start, eb->start + eb->len - 1, 0);
+               set_extent_dirty(tree, eb->start, eb->start + eb->len - 1);
                extent_buffer_get(eb);
        }
        return 0;
@@ -867,7 +845,7 @@ int clear_extent_buffer_dirty(struct extent_buffer *eb)
        struct extent_io_tree *tree = eb->tree;
        if (eb->flags & EXTENT_DIRTY) {
                eb->flags &= ~EXTENT_DIRTY;
-               clear_extent_dirty(tree, eb->start, eb->start + eb->len - 1, 0);
+               clear_extent_dirty(tree, eb->start, eb->start + eb->len - 1);
                free_extent_buffer(eb);
        }
        return 0;
@@ -909,3 +887,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);
+}