Btrfs: Fix extent_buffer usage when nodesize != leafsize
[linux-2.6-block.git] / fs / btrfs / extent_map.c
index 9d6aefa937c4b717b31b1e6e23bd64e1235772ea..f3a384ed700c5bb053918c5adc3233b5b4ae8326 100644 (file)
@@ -1663,6 +1663,13 @@ void set_page_extent_mapped(struct page *page)
        }
 }
 
+void set_page_extent_head(struct page *page, unsigned long len)
+{
+       WARN_ON(page->private && page->private == EXTENT_PAGE_PRIVATE &&
+               PageDirty(page));
+       set_page_private(page, EXTENT_PAGE_PRIVATE_FIRST_PAGE | len << 2);
+}
+
 /*
  * basic readpage implementation.  Locked extent state structs are inserted
  * into the tree that are removed when the IO is done (by the end_io
@@ -2490,8 +2497,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
                mark_page_accessed(page0);
                set_page_extent_mapped(page0);
                WARN_ON(!PageUptodate(page0));
-               set_page_private(page0, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
-                                len << 2);
+               set_page_extent_head(page0, len);
        } else {
                i = 0;
        }
@@ -2505,8 +2511,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
                mark_page_accessed(p);
                if (i == 0) {
                        eb->first_page = p;
-                       set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
-                                        len << 2);
+                       set_page_extent_head(p, len);
                } else {
                        set_page_private(p, EXTENT_PAGE_PRIVATE);
                }
@@ -2569,8 +2574,7 @@ struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
 
                if (i == 0) {
                        eb->first_page = p;
-                       set_page_private(p, EXTENT_PAGE_PRIVATE_FIRST_PAGE |
-                                        len << 2);
+                       set_page_extent_head(p, len);
                } else {
                        set_page_private(p, EXTENT_PAGE_PRIVATE);
                }
@@ -2643,6 +2647,11 @@ int clear_extent_buffer_dirty(struct extent_map_tree *tree,
        for (i = 0; i < num_pages; i++) {
                page = extent_buffer_page(eb, i);
                lock_page(page);
+               if (i == 0)
+                       set_page_extent_head(page, eb->len);
+               else
+                       set_page_private(page, EXTENT_PAGE_PRIVATE);
+
                /*
                 * if we're on the last page or the first page and the
                 * block isn't aligned on a page boundary, do extra checks
@@ -2697,9 +2706,12 @@ int set_extent_buffer_dirty(struct extent_map_tree *tree,
                 */
                if (i == 0) {
                        lock_page(page);
-                       set_page_private(page,
-                                        EXTENT_PAGE_PRIVATE_FIRST_PAGE |
-                                        eb->len << 2);
+                       set_page_extent_head(page, eb->len);
+               } else if (PagePrivate(page) &&
+                          page->private != EXTENT_PAGE_PRIVATE) {
+                       lock_page(page);
+                       set_page_extent_mapped(page);
+                       unlock_page(page);
                }
                __set_page_dirty_nobuffers(extent_buffer_page(eb, i));
                if (i == 0)