Btrfs: check return value of lookup_extent_mapping() correctly
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / volumes.c
index 7ffdb154daec5620745ca0ba4f961f243e5a5f57..cd040bf3fd87134bd36c76e40b29d7d0eab46b1d 100644 (file)
@@ -1954,7 +1954,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root,
        em = lookup_extent_mapping(em_tree, chunk_offset, 1);
        read_unlock(&em_tree->lock);
 
-       BUG_ON(em->start > chunk_offset ||
+       BUG_ON(!em || em->start > chunk_offset ||
               em->start + em->len < chunk_offset);
        map = (struct map_lookup *)em->bdev;
 
@@ -4357,6 +4357,20 @@ int btrfs_read_sys_array(struct btrfs_root *root)
                return -ENOMEM;
        btrfs_set_buffer_uptodate(sb);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
+       /*
+        * The sb extent buffer is artifical and just used to read the system array.
+        * btrfs_set_buffer_uptodate() call does not properly mark all it's
+        * pages up-to-date when the page is larger: extent does not cover the
+        * whole page and consequently check_page_uptodate does not find all
+        * the page's extents up-to-date (the hole beyond sb),
+        * write_extent_buffer then triggers a WARN_ON.
+        *
+        * Regular short extents go through mark_extent_buffer_dirty/writeback cycle,
+        * but sb spans only this function. Add an explicit SetPageUptodate call
+        * to silence the warning eg. on PowerPC 64.
+        */
+       if (PAGE_CACHE_SIZE > BTRFS_SUPER_INFO_SIZE)
+               SetPageUptodate(sb->first_page);
 
        write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
        array_size = btrfs_super_sys_array_size(super_copy);