hugetlb: ensure hugepage access is denied if hugepages are not supported
[pandora-kernel.git] / fs / btrfs / extent-tree.c
index 4eb4d27..da528f8 100644 (file)
@@ -2822,7 +2822,7 @@ out_free:
        btrfs_release_path(path);
 out:
        spin_lock(&block_group->lock);
-       if (!ret)
+       if (!ret && dcs == BTRFS_DC_SETUP)
                block_group->cache_generation = trans->transid;
        block_group->disk_cache_state = dcs;
        spin_unlock(&block_group->lock);
@@ -3416,7 +3416,8 @@ static int shrink_delalloc(struct btrfs_root *root, u64 to_reclaim,
                smp_mb();
                nr_pages = min_t(unsigned long, nr_pages,
                       root->fs_info->delalloc_bytes >> PAGE_CACHE_SHIFT);
-               writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages);
+               writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages,
+                                               WB_REASON_FS_FREE_SPACE);
 
                spin_lock(&space_info->lock);
                if (reserved > space_info->bytes_may_use)
@@ -3995,7 +3996,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
        spin_lock(&block_rsv->lock);
        spin_lock(&sinfo->lock);
 
-       block_rsv->size = num_bytes;
+       block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
 
        num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
                    sinfo->bytes_reserved + sinfo->bytes_readonly +
@@ -4610,7 +4611,8 @@ int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
+static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end,
+                             const bool return_free_space)
 {
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_block_group_cache *cache = NULL;
@@ -4630,7 +4632,8 @@ static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
 
                if (start < cache->last_byte_to_unpin) {
                        len = min(len, cache->last_byte_to_unpin - start);
-                       btrfs_add_free_space(cache, start, len);
+                       if (return_free_space)
+                               btrfs_add_free_space(cache, start, len);
                }
 
                start += len;
@@ -4675,7 +4678,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
                                                   end + 1 - start, NULL);
 
                clear_extent_dirty(unpin, start, end, GFP_NOFS);
-               unpin_extent_range(root, start, end);
+               unpin_extent_range(root, start, end, true);
                cond_resched();
        }
 
@@ -5675,12 +5678,11 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,
                return -ENOSPC;
        }
 
-       if (btrfs_test_opt(root, DISCARD))
-               ret = btrfs_discard_extent(root, start, len, NULL);
-
        if (pin)
                pin_down_extent(root, cache, start, len, 1);
        else {
+               if (btrfs_test_opt(root, DISCARD))
+                       ret = btrfs_discard_extent(root, start, len, NULL);
                btrfs_add_free_space(cache, start, len);
                btrfs_update_reserved_bytes(cache, len, RESERVE_FREE);
        }
@@ -6559,6 +6561,7 @@ void btrfs_drop_snapshot(struct btrfs_root *root,
        int err = 0;
        int ret;
        int level;
+       bool root_dropped = false;
 
        path = btrfs_alloc_path();
        if (!path) {
@@ -6613,6 +6616,7 @@ void btrfs_drop_snapshot(struct btrfs_root *root,
                while (1) {
                        btrfs_tree_lock(path->nodes[level]);
                        btrfs_set_lock_blocking(path->nodes[level]);
+                       path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
 
                        ret = btrfs_lookup_extent_info(trans, root,
                                                path->nodes[level]->start,
@@ -6626,6 +6630,7 @@ void btrfs_drop_snapshot(struct btrfs_root *root,
                                break;
 
                        btrfs_tree_unlock(path->nodes[level]);
+                       path->locks[level] = 0;
                        WARN_ON(wc->refs[level] != 1);
                        level--;
                }
@@ -6706,12 +6711,22 @@ void btrfs_drop_snapshot(struct btrfs_root *root,
                free_extent_buffer(root->commit_root);
                kfree(root);
        }
+       root_dropped = true;
 out_free:
        btrfs_end_transaction_throttle(trans, tree_root);
        kfree(wc);
        btrfs_free_path(path);
 out:
-       if (err)
+       /*
+        * So if we need to stop dropping the snapshot for whatever reason we
+        * need to make sure to add it back to the dead root list so that we
+        * keep trying to do the work later.  This also cleans up roots if we
+        * don't have it in the radix (like when we recover after a power fail
+        * or unmount) so we don't leak memory.
+        */
+       if (root_dropped == false)
+               btrfs_add_dead_root(root);
+       if (err && err != -EAGAIN)
                btrfs_std_error(root->fs_info, err);
        return;
 }
@@ -7636,7 +7651,7 @@ out:
 
 int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
 {
-       return unpin_extent_range(root, start, end);
+       return unpin_extent_range(root, start, end, false);
 }
 
 int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,