]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/extent-tree.c
Merge branch 'for-linus' of git://git.infradead.org/users/eparis/notify
[karo-tx-linux.git] / fs / btrfs / extent-tree.c
index 372fd224a11d018ddf896693df564bf261224d4f..0c097f3aec418564e25df5b7e0af8d9a81a79d1d 100644 (file)
@@ -580,6 +580,15 @@ static u64 div_factor(u64 num, int factor)
        return num;
 }
 
+static u64 div_factor_fine(u64 num, int factor)
+{
+       if (factor == 100)
+               return num;
+       num *= factor;
+       do_div(num, 100);
+       return num;
+}
+
 u64 btrfs_find_block_group(struct btrfs_root *root,
                           u64 search_start, u64 search_hint, int owner)
 {
@@ -1733,8 +1742,7 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 static void btrfs_issue_discard(struct block_device *bdev,
                                u64 start, u64 len)
 {
-       blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
-                       BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
+       blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0);
 }
 
 static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
@@ -3218,9 +3226,11 @@ static void force_metadata_allocation(struct btrfs_fs_info *info)
        rcu_read_unlock();
 }
 
-static int should_alloc_chunk(struct btrfs_space_info *sinfo, u64 alloc_bytes)
+static int should_alloc_chunk(struct btrfs_root *root,
+                             struct btrfs_space_info *sinfo, u64 alloc_bytes)
 {
        u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly;
+       u64 thresh;
 
        if (sinfo->bytes_used + sinfo->bytes_reserved +
            alloc_bytes + 256 * 1024 * 1024 < num_bytes)
@@ -3230,8 +3240,10 @@ static int should_alloc_chunk(struct btrfs_space_info *sinfo, u64 alloc_bytes)
            alloc_bytes < div_factor(num_bytes, 8))
                return 0;
 
-       if (num_bytes > 256 * 1024 * 1024 &&
-           sinfo->bytes_used < div_factor(num_bytes, 3))
+       thresh = btrfs_super_total_bytes(&root->fs_info->super_copy);
+       thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5));
+
+       if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3))
                return 0;
 
        return 1;
@@ -3265,7 +3277,8 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                goto out;
        }
 
-       if (!force && !should_alloc_chunk(space_info, alloc_bytes)) {
+       if (!force && !should_alloc_chunk(extent_root, space_info,
+                                         alloc_bytes)) {
                spin_unlock(&space_info->lock);
                goto out;
        }
@@ -3314,15 +3327,14 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
        u64 reserved;
        u64 max_reclaim;
        u64 reclaimed = 0;
-       int no_reclaim = 0;
        int pause = 1;
-       int ret;
+       int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT;
 
        block_rsv = &root->fs_info->delalloc_block_rsv;
        space_info = block_rsv->space_info;
-       spin_lock(&space_info->lock);
+
+       smp_mb();
        reserved = space_info->bytes_reserved;
-       spin_unlock(&space_info->lock);
 
        if (reserved == 0)
                return 0;
@@ -3330,20 +3342,11 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
        max_reclaim = min(reserved, to_reclaim);
 
        while (1) {
-               ret = btrfs_start_one_delalloc_inode(root, trans ? 1 : 0, sync);
-               if (!ret) {
-                       if (no_reclaim > 2)
-                               break;
-                       no_reclaim++;
-                       __set_current_state(TASK_INTERRUPTIBLE);
-                       schedule_timeout(pause);
-                       pause <<= 1;
-                       if (pause > HZ / 10)
-                               pause = HZ / 10;
-               } else {
-                       no_reclaim = 0;
-                       pause = 1;
-               }
+               /* have the flusher threads jump in and do some IO */
+               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);
 
                spin_lock(&space_info->lock);
                if (reserved > space_info->bytes_reserved)
@@ -3356,6 +3359,13 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
 
                if (trans && trans->transaction->blocked)
                        return -EAGAIN;
+
+               __set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(pause);
+               pause <<= 1;
+               if (pause > HZ / 10)
+                       pause = HZ / 10;
+
        }
        return reclaimed >= to_reclaim;
 }
@@ -3596,18 +3606,14 @@ struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root)
 {
        struct btrfs_block_rsv *block_rsv;
        struct btrfs_fs_info *fs_info = root->fs_info;
-       u64 alloc_target;
 
        block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS);
        if (!block_rsv)
                return NULL;
 
        btrfs_init_block_rsv(block_rsv);
-
-       alloc_target = btrfs_get_alloc_profile(root, 0);
        block_rsv->space_info = __find_space_info(fs_info,
                                                  BTRFS_BLOCK_GROUP_METADATA);
-
        return block_rsv;
 }
 
@@ -5708,7 +5714,6 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
        u64 generation;
        u64 refs;
        u64 flags;
-       u64 last = 0;
        u32 nritems;
        u32 blocksize;
        struct btrfs_key key;
@@ -5776,7 +5781,6 @@ reada:
                                           generation);
                if (ret)
                        break;
-               last = bytenr + blocksize;
                nread++;
        }
        wc->reada_slot = slot;