btrfs: use BUG() instead of BUG_ON(1)
[sfrench/cifs-2.6.git] / fs / btrfs / extent_io.c
index ca8b8e785cf3a17f963449058210d1f0ff4cfd0d..66b4637b29b3f7420e525359dc2ca94d110dd9e6 100644 (file)
@@ -109,8 +109,6 @@ static inline void __btrfs_debug_check_extent_io_range(const char *caller,
 #define btrfs_debug_check_extent_io_range(c, s, e)     do {} while (0)
 #endif
 
-#define BUFFER_LRU_MAX 64
-
 struct tree_entry {
        u64 start;
        u64 end;
@@ -170,15 +168,38 @@ static int __must_check submit_one_bio(struct bio *bio, int mirror_num,
        return blk_status_to_errno(ret);
 }
 
-static void flush_write_bio(struct extent_page_data *epd)
+/* Cleanup unsubmitted bios */
+static void end_write_bio(struct extent_page_data *epd, int ret)
 {
        if (epd->bio) {
-               int ret;
+               epd->bio->bi_status = errno_to_blk_status(ret);
+               bio_endio(epd->bio);
+               epd->bio = NULL;
+       }
+}
+
+/*
+ * Submit bio from extent page data via submit_one_bio
+ *
+ * Return 0 if everything is OK.
+ * Return <0 for error.
+ */
+static int __must_check flush_write_bio(struct extent_page_data *epd)
+{
+       int ret = 0;
 
+       if (epd->bio) {
                ret = submit_one_bio(epd->bio, 0, 0);
-               BUG_ON(ret < 0); /* -ENOMEM */
+               /*
+                * Clean up of epd->bio is handled by its endio function.
+                * And endio is either triggered by successful bio execution
+                * or the error handler of submit bio hook.
+                * So at this point, no matter what happened, we don't need
+                * to clean up epd->bio.
+                */
                epd->bio = NULL;
        }
+       return ret;
 }
 
 int __init extent_io_init(void)
@@ -232,14 +253,17 @@ void __cold extent_io_exit(void)
        bioset_exit(&btrfs_bioset);
 }
 
-void extent_io_tree_init(struct extent_io_tree *tree,
+void extent_io_tree_init(struct btrfs_fs_info *fs_info,
+                        struct extent_io_tree *tree, unsigned int owner,
                         void *private_data)
 {
+       tree->fs_info = fs_info;
        tree->state = RB_ROOT;
        tree->ops = NULL;
        tree->dirty_bytes = 0;
        spin_lock_init(&tree->lock);
        tree->private_data = private_data;
+       tree->owner = owner;
 }
 
 static struct extent_state *alloc_extent_state(gfp_t mask)
@@ -400,7 +424,7 @@ static void merge_state(struct extent_io_tree *tree,
        struct extent_state *other;
        struct rb_node *other_node;
 
-       if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY))
+       if (state->state & (EXTENT_LOCKED | EXTENT_BOUNDARY))
                return;
 
        other_node = rb_prev(&state->rb_node);
@@ -611,6 +635,7 @@ int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        int clear = 0;
 
        btrfs_debug_check_extent_io_range(tree, start, end);
+       trace_btrfs_clear_extent_bit(tree, start, end - start + 1, bits);
 
        if (bits & EXTENT_DELALLOC)
                bits |= EXTENT_NORESERVE;
@@ -618,7 +643,7 @@ int __clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        if (delete)
                bits |= ~EXTENT_CTLBITS;
 
-       if (bits & (EXTENT_IOBITS | EXTENT_BOUNDARY))
+       if (bits & (EXTENT_LOCKED | EXTENT_BOUNDARY))
                clear = 1;
 again:
        if (!prealloc && gfpflags_allow_blocking(mask)) {
@@ -850,7 +875,7 @@ static void cache_state(struct extent_state *state,
                        struct extent_state **cached_ptr)
 {
        return cache_state_if_flags(state, cached_ptr,
-                                   EXTENT_IOBITS | EXTENT_BOUNDARY);
+                                   EXTENT_LOCKED | EXTENT_BOUNDARY);
 }
 
 /*
@@ -880,6 +905,7 @@ __set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        u64 last_end;
 
        btrfs_debug_check_extent_io_range(tree, start, end);
+       trace_btrfs_set_extent_bit(tree, start, end - start + 1, bits);
 
 again:
        if (!prealloc && gfpflags_allow_blocking(mask)) {
@@ -1112,6 +1138,8 @@ int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
        bool first_iteration = true;
 
        btrfs_debug_check_extent_io_range(tree, start, end);
+       trace_btrfs_convert_extent_bit(tree, start, end - start + 1, bits,
+                                      clear_bits);
 
 again:
        if (!prealloc) {
@@ -2607,8 +2635,6 @@ static void end_bio_extent_readpage(struct bio *bio)
                        if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD,
                                               &eb->bflags))
                                btree_readahead_hook(eb, -EIO);
-
-                       ret = -EIO;
                }
 readpage_ok:
                if (likely(uptodate)) {
@@ -3069,7 +3095,7 @@ out:
        return ret;
 }
 
-static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
+static inline void contiguous_readpages(struct extent_io_tree *tree,
                                             struct page *pages[], int nr_pages,
                                             u64 start, u64 end,
                                             struct extent_map **em_cached,
@@ -3100,46 +3126,6 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree,
        }
 }
 
-static void __extent_readpages(struct extent_io_tree *tree,
-                              struct page *pages[],
-                              int nr_pages,
-                              struct extent_map **em_cached,
-                              struct bio **bio, unsigned long *bio_flags,
-                              u64 *prev_em_start)
-{
-       u64 start = 0;
-       u64 end = 0;
-       u64 page_start;
-       int index;
-       int first_index = 0;
-
-       for (index = 0; index < nr_pages; index++) {
-               page_start = page_offset(pages[index]);
-               if (!end) {
-                       start = page_start;
-                       end = start + PAGE_SIZE - 1;
-                       first_index = index;
-               } else if (end + 1 == page_start) {
-                       end += PAGE_SIZE;
-               } else {
-                       __do_contiguous_readpages(tree, &pages[first_index],
-                                                 index - first_index, start,
-                                                 end, em_cached,
-                                                 bio, bio_flags,
-                                                 prev_em_start);
-                       start = page_start;
-                       end = start + PAGE_SIZE - 1;
-                       first_index = index;
-               }
-       }
-
-       if (end)
-               __do_contiguous_readpages(tree, &pages[first_index],
-                                         index - first_index, start,
-                                         end, em_cached, bio,
-                                         bio_flags, prev_em_start);
-}
-
 static int __extent_read_full_page(struct extent_io_tree *tree,
                                   struct page *page,
                                   get_extent_t *get_extent,
@@ -3419,6 +3405,9 @@ done:
  * records are inserted to lock ranges in the tree, and as dirty areas
  * are found, they are marked writeback.  Then the lock bits are removed
  * and the end_io handler clears the writeback ranges
+ *
+ * Return 0 if everything goes well.
+ * Return <0 for error.
  */
 static int __extent_writepage(struct page *page, struct writeback_control *wbc,
                              struct extent_page_data *epd)
@@ -3488,6 +3477,7 @@ done:
                end_extent_writepage(page, ret, start, page_end);
        }
        unlock_page(page);
+       ASSERT(ret <= 0);
        return ret;
 
 done_unlocked:
@@ -3500,18 +3490,27 @@ void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
                       TASK_UNINTERRUPTIBLE);
 }
 
+/*
+ * Lock eb pages and flush the bio if we can't the locks
+ *
+ * Return  0 if nothing went wrong
+ * Return >0 is same as 0, except bio is not submitted
+ * Return <0 if something went wrong, no page is locked
+ */
 static noinline_for_stack int
 lock_extent_buffer_for_io(struct extent_buffer *eb,
                          struct btrfs_fs_info *fs_info,
                          struct extent_page_data *epd)
 {
-       int i, num_pages;
+       int i, num_pages, failed_page_nr;
        int flush = 0;
        int ret = 0;
 
        if (!btrfs_try_tree_write_lock(eb)) {
+               ret = flush_write_bio(epd);
+               if (ret < 0)
+                       return ret;
                flush = 1;
-               flush_write_bio(epd);
                btrfs_tree_lock(eb);
        }
 
@@ -3520,7 +3519,9 @@ lock_extent_buffer_for_io(struct extent_buffer *eb,
                if (!epd->sync_io)
                        return 0;
                if (!flush) {
-                       flush_write_bio(epd);
+                       ret = flush_write_bio(epd);
+                       if (ret < 0)
+                               return ret;
                        flush = 1;
                }
                while (1) {
@@ -3561,7 +3562,11 @@ lock_extent_buffer_for_io(struct extent_buffer *eb,
 
                if (!trylock_page(p)) {
                        if (!flush) {
-                               flush_write_bio(epd);
+                               ret = flush_write_bio(epd);
+                               if (ret < 0) {
+                                       failed_page_nr = i;
+                                       goto err_unlock;
+                               }
                                flush = 1;
                        }
                        lock_page(p);
@@ -3569,6 +3574,11 @@ lock_extent_buffer_for_io(struct extent_buffer *eb,
        }
 
        return ret;
+err_unlock:
+       /* Unlock already locked pages */
+       for (i = 0; i < failed_page_nr; i++)
+               unlock_page(eb->pages[i]);
+       return ret;
 }
 
 static void end_extent_buffer_writeback(struct extent_buffer *eb)
@@ -3852,7 +3862,12 @@ retry:
                index = 0;
                goto retry;
        }
-       flush_write_bio(&epd);
+       ASSERT(ret <= 0);
+       if (ret < 0) {
+               end_write_bio(&epd, ret);
+               return ret;
+       }
+       ret = flush_write_bio(&epd);
        return ret;
 }
 
@@ -3949,7 +3964,8 @@ retry:
                         * tmpfs file mapping
                         */
                        if (!trylock_page(page)) {
-                               flush_write_bio(epd);
+                               ret = flush_write_bio(epd);
+                               BUG_ON(ret < 0);
                                lock_page(page);
                        }
 
@@ -3959,8 +3975,10 @@ retry:
                        }
 
                        if (wbc->sync_mode != WB_SYNC_NONE) {
-                               if (PageWriteback(page))
-                                       flush_write_bio(epd);
+                               if (PageWriteback(page)) {
+                                       ret = flush_write_bio(epd);
+                                       BUG_ON(ret < 0);
+                               }
                                wait_on_page_writeback(page);
                        }
 
@@ -3971,11 +3989,6 @@ retry:
                        }
 
                        ret = __extent_writepage(page, wbc, epd);
-
-                       if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE)) {
-                               unlock_page(page);
-                               ret = 0;
-                       }
                        if (ret < 0) {
                                /*
                                 * done_index is set past this page,
@@ -4029,8 +4042,14 @@ int extent_write_full_page(struct page *page, struct writeback_control *wbc)
        };
 
        ret = __extent_writepage(page, wbc, &epd);
+       ASSERT(ret <= 0);
+       if (ret < 0) {
+               end_write_bio(&epd, ret);
+               return ret;
+       }
 
-       flush_write_bio(&epd);
+       ret = flush_write_bio(&epd);
+       ASSERT(ret <= 0);
        return ret;
 }
 
@@ -4070,7 +4089,12 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
                start += PAGE_SIZE;
        }
 
-       flush_write_bio(&epd);
+       ASSERT(ret <= 0);
+       if (ret < 0) {
+               end_write_bio(&epd, ret);
+               return ret;
+       }
+       ret = flush_write_bio(&epd);
        return ret;
 }
 
@@ -4086,7 +4110,12 @@ int extent_writepages(struct address_space *mapping,
        };
 
        ret = extent_write_cache_pages(mapping, wbc, &epd);
-       flush_write_bio(&epd);
+       ASSERT(ret <= 0);
+       if (ret < 0) {
+               end_write_bio(&epd, ret);
+               return ret;
+       }
+       ret = flush_write_bio(&epd);
        return ret;
 }
 
@@ -4102,6 +4131,8 @@ int extent_readpages(struct address_space *mapping, struct list_head *pages,
        u64 prev_em_start = (u64)-1;
 
        while (!list_empty(pages)) {
+               u64 contig_end = 0;
+
                for (nr = 0; nr < ARRAY_SIZE(pagepool) && !list_empty(pages);) {
                        struct page *page = lru_to_page(pages);
 
@@ -4110,14 +4141,22 @@ int extent_readpages(struct address_space *mapping, struct list_head *pages,
                        if (add_to_page_cache_lru(page, mapping, page->index,
                                                readahead_gfp_mask(mapping))) {
                                put_page(page);
-                               continue;
+                               break;
                        }
 
                        pagepool[nr++] = page;
+                       contig_end = page_offset(page) + PAGE_SIZE - 1;
                }
 
-               __extent_readpages(tree, pagepool, nr, &em_cached, &bio,
-                                  &bio_flags, &prev_em_start);
+               if (nr) {
+                       u64 contig_start = page_offset(pagepool[0]);
+
+                       ASSERT(contig_start + nr * PAGE_SIZE - 1 == contig_end);
+
+                       contiguous_readpages(tree, pagepool, nr, contig_start,
+                                    contig_end, &em_cached, &bio, &bio_flags,
+                                    &prev_em_start);
+               }
        }
 
        if (em_cached)
@@ -4166,10 +4205,9 @@ static int try_release_extent_state(struct extent_io_tree *tree,
        u64 end = start + PAGE_SIZE - 1;
        int ret = 1;
 
-       if (test_range_bit(tree, start, end,
-                          EXTENT_IOBITS, 0, NULL))
+       if (test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL)) {
                ret = 0;
-       else {
+       else {
                /*
                 * at this point we can safely clear everything except the
                 * locked bit and the nodatasum bit
@@ -4222,8 +4260,7 @@ int try_release_extent_mapping(struct page *page, gfp_t mask)
                        }
                        if (!test_range_bit(tree, em->start,
                                            extent_map_end(em) - 1,
-                                           EXTENT_LOCKED | EXTENT_WRITEBACK,
-                                           0, NULL)) {
+                                           EXTENT_LOCKED, 0, NULL)) {
                                set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                                        &btrfs_inode->runtime_flags);
                                remove_extent_mapping(map, em);
@@ -4672,13 +4709,9 @@ __alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start,
        eb->fs_info = fs_info;
        eb->bflags = 0;
        rwlock_init(&eb->lock);
-       atomic_set(&eb->write_locks, 0);
-       atomic_set(&eb->read_locks, 0);
        atomic_set(&eb->blocking_readers, 0);
        atomic_set(&eb->blocking_writers, 0);
-       atomic_set(&eb->spinning_readers, 0);
-       atomic_set(&eb->spinning_writers, 0);
-       eb->lock_nested = 0;
+       eb->lock_nested = false;
        init_waitqueue_head(&eb->write_lock_wq);
        init_waitqueue_head(&eb->read_lock_wq);
 
@@ -4695,6 +4728,13 @@ __alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start,
                > MAX_INLINE_EXTENT_BUFFER_SIZE);
        BUG_ON(len > MAX_INLINE_EXTENT_BUFFER_SIZE);
 
+#ifdef CONFIG_BTRFS_DEBUG
+       atomic_set(&eb->spinning_writers, 0);
+       atomic_set(&eb->spinning_readers, 0);
+       atomic_set(&eb->read_locks, 0);
+       atomic_set(&eb->write_locks, 0);
+#endif
+
        return eb;
 }
 
@@ -5746,13 +5786,13 @@ void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
                btrfs_err(fs_info,
                        "memmove bogus src_offset %lu move len %lu dst len %lu",
                         src_offset, len, dst->len);
-               BUG_ON(1);
+               BUG();
        }
        if (dst_offset + len > dst->len) {
                btrfs_err(fs_info,
                        "memmove bogus dst_offset %lu move len %lu dst len %lu",
                         dst_offset, len, dst->len);
-               BUG_ON(1);
+               BUG();
        }
 
        while (len > 0) {
@@ -5793,13 +5833,13 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
                btrfs_err(fs_info,
                          "memmove bogus src_offset %lu move len %lu len %lu",
                          src_offset, len, dst->len);
-               BUG_ON(1);
+               BUG();
        }
        if (dst_offset + len > dst->len) {
                btrfs_err(fs_info,
                          "memmove bogus dst_offset %lu move len %lu len %lu",
                          dst_offset, len, dst->len);
-               BUG_ON(1);
+               BUG();
        }
        if (dst_offset < src_offset) {
                memcpy_extent_buffer(dst, dst_offset, src_offset, len);