Btrfs: improve the performance of the csums lookup
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / extent_io.c
index f173c5af64610de66597cce1e38ac493729d6125..617b5779b95b909a29ba88d4f29e6942c23ef62c 100644 (file)
@@ -1189,7 +1189,7 @@ int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
 int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end,
                        struct extent_state **cached_state, gfp_t mask)
 {
-       return set_extent_bit(tree, start, end, EXTENT_UPTODATE, 0,
+       return set_extent_bit(tree, start, end, EXTENT_UPTODATE, NULL,
                              cached_state, mask);
 }
 
@@ -1257,6 +1257,39 @@ int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end)
                                GFP_NOFS);
 }
 
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+       unsigned long index = start >> PAGE_CACHE_SHIFT;
+       unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+       struct page *page;
+
+       while (index <= end_index) {
+               page = find_get_page(inode->i_mapping, index);
+               BUG_ON(!page); /* Pages should be in the extent_io_tree */
+               clear_page_dirty_for_io(page);
+               page_cache_release(page);
+               index++;
+       }
+       return 0;
+}
+
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+       unsigned long index = start >> PAGE_CACHE_SHIFT;
+       unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+       struct page *page;
+
+       while (index <= end_index) {
+               page = find_get_page(inode->i_mapping, index);
+               BUG_ON(!page); /* Pages should be in the extent_io_tree */
+               account_page_redirty(page);
+               __set_page_dirty_nobuffers(page);
+               page_cache_release(page);
+               index++;
+       }
+       return 0;
+}
+
 /*
  * helper function to set both pages and extents in the tree writeback
  */
@@ -1744,6 +1777,64 @@ out:
        return ret;
 }
 
+void extent_cache_csums_dio(struct extent_io_tree *tree, u64 start, u32 csums[],
+                           int count)
+{
+       struct rb_node *node;
+       struct extent_state *state;
+
+       spin_lock(&tree->lock);
+       /*
+        * this search will find all the extents that end after
+        * our range starts.
+        */
+       node = tree_search(tree, start);
+       BUG_ON(!node);
+
+       state = rb_entry(node, struct extent_state, rb_node);
+       BUG_ON(state->start != start);
+
+       while (count) {
+               state->private = *csums++;
+               count--;
+               state = next_state(state);
+       }
+       spin_unlock(&tree->lock);
+}
+
+static inline u64 __btrfs_get_bio_offset(struct bio *bio, int bio_index)
+{
+       struct bio_vec *bvec = bio->bi_io_vec + bio_index;
+
+       return page_offset(bvec->bv_page) + bvec->bv_offset;
+}
+
+void extent_cache_csums(struct extent_io_tree *tree, struct bio *bio, int bio_index,
+                       u32 csums[], int count)
+{
+       struct rb_node *node;
+       struct extent_state *state = NULL;
+       u64 start;
+
+       spin_lock(&tree->lock);
+       do {
+               start = __btrfs_get_bio_offset(bio, bio_index);
+               if (state == NULL || state->start != start) {
+                       node = tree_search(tree, start);
+                       BUG_ON(!node);
+
+                       state = rb_entry(node, struct extent_state, rb_node);
+                       BUG_ON(state->start != start);
+               }
+               state->private = *csums++;
+               count--;
+               bio_index++;
+
+               state = next_state(state);
+       } while (count);
+       spin_unlock(&tree->lock);
+}
+
 int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private)
 {
        struct rb_node *node;