Merge tag 'vfio-for-v3.8-v2' of git://github.com/awilliam/linux-vfio
[linux-2.6-block.git] / fs / btrfs / extent_map.c
index 85ae2b6fe03b73fe09258b4cf80e20695231a810..f169d6b11d7f6a093158428352a44f35d4bae952 100644 (file)
@@ -49,7 +49,7 @@ void extent_map_tree_init(struct extent_map_tree *tree)
 struct extent_map *alloc_extent_map(void)
 {
        struct extent_map *em;
-       em = kmem_cache_alloc(extent_map_cache, GFP_NOFS);
+       em = kmem_cache_zalloc(extent_map_cache, GFP_NOFS);
        if (!em)
                return NULL;
        em->in_tree = 0;
@@ -198,16 +198,15 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
                        merge = rb_entry(rb, struct extent_map, rb_node);
                if (rb && mergable_maps(merge, em)) {
                        em->start = merge->start;
+                       em->orig_start = merge->orig_start;
                        em->len += merge->len;
                        em->block_len += merge->block_len;
                        em->block_start = merge->block_start;
                        merge->in_tree = 0;
-                       if (merge->generation > em->generation) {
-                               em->mod_start = em->start;
-                               em->mod_len = em->len;
-                               em->generation = merge->generation;
-                               list_move(&em->list, &tree->modified_extents);
-                       }
+                       em->mod_len = (em->mod_len + em->mod_start) - merge->mod_start;
+                       em->mod_start = merge->mod_start;
+                       em->generation = max(em->generation, merge->generation);
+                       list_move(&em->list, &tree->modified_extents);
 
                        list_del_init(&merge->list);
                        rb_erase(&merge->rb_node, &tree->map);
@@ -223,23 +222,19 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
                em->block_len += merge->len;
                rb_erase(&merge->rb_node, &tree->map);
                merge->in_tree = 0;
-               if (merge->generation > em->generation) {
-                       em->mod_len = em->len;
-                       em->generation = merge->generation;
-                       list_move(&em->list, &tree->modified_extents);
-               }
+               em->mod_len = (merge->mod_start + merge->mod_len) - em->mod_start;
+               em->generation = max(em->generation, merge->generation);
                list_del_init(&merge->list);
                free_extent_map(merge);
        }
 }
 
 /**
- * unpint_extent_cache - unpin an extent from the cache
+ * unpin_extent_cache - unpin an extent from the cache
  * @tree:      tree to unpin the extent in
  * @start:     logical offset in the file
  * @len:       length of the extent
  * @gen:       generation that this extent has been modified in
- * @prealloc:  if this is set we need to clear the prealloc flag
  *
  * Called after an extent has been written to disk properly.  Set the generation
  * to the generation that actually added the file item to the inode so we know