]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/btrfs/extent-tree.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
[mv-sheeva.git] / fs / btrfs / extent-tree.c
index f07ba21cbf0628cf69c426e0f27afc8cc0d4fcc9..7b3089b5c2df816522e2356d3064f0b2bdb40c4f 100644 (file)
@@ -320,11 +320,6 @@ static int caching_kthread(void *data)
        if (!path)
                return -ENOMEM;
 
-       exclude_super_stripes(extent_root, block_group);
-       spin_lock(&block_group->space_info->lock);
-       block_group->space_info->bytes_readonly += block_group->bytes_super;
-       spin_unlock(&block_group->space_info->lock);
-
        last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET);
 
        /*
@@ -467,8 +462,10 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
                        cache->cached = BTRFS_CACHE_NO;
                }
                spin_unlock(&cache->lock);
-               if (ret == 1)
+               if (ret == 1) {
+                       free_excluded_extents(fs_info->extent_root, cache);
                        return 0;
+               }
        }
 
        if (load_cache_only)
@@ -1746,8 +1743,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,
@@ -3346,15 +3342,16 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
        u64 max_reclaim;
        u64 reclaimed = 0;
        long time_left;
-       int pause = 1;
        int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT;
        int loops = 0;
+       unsigned long progress;
 
        block_rsv = &root->fs_info->delalloc_block_rsv;
        space_info = block_rsv->space_info;
 
        smp_mb();
        reserved = space_info->bytes_reserved;
+       progress = space_info->reservation_progress;
 
        if (reserved == 0)
                return 0;
@@ -3369,31 +3366,36 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
                writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages);
 
                spin_lock(&space_info->lock);
-               if (reserved > space_info->bytes_reserved) {
-                       loops = 0;
+               if (reserved > space_info->bytes_reserved)
                        reclaimed += reserved - space_info->bytes_reserved;
-               } else {
-                       loops++;
-               }
                reserved = space_info->bytes_reserved;
                spin_unlock(&space_info->lock);
 
+               loops++;
+
                if (reserved == 0 || reclaimed >= max_reclaim)
                        break;
 
                if (trans && trans->transaction->blocked)
                        return -EAGAIN;
 
-               __set_current_state(TASK_INTERRUPTIBLE);
-               time_left = schedule_timeout(pause);
+               time_left = schedule_timeout_interruptible(1);
 
                /* We were interrupted, exit */
                if (time_left)
                        break;
 
-               pause <<= 1;
-               if (pause > HZ / 10)
-                       pause = HZ / 10;
+               /* we've kicked the IO a few times, if anything has been freed,
+                * exit.  There is no sense in looping here for a long time
+                * when we really need to commit the transaction, or there are
+                * just too many writers without enough free space
+                */
+
+               if (loops > 3) {
+                       smp_mb();
+                       if (progress != space_info->reservation_progress)
+                               break;
+               }
 
        }
        return reclaimed >= to_reclaim;
@@ -3616,6 +3618,7 @@ void block_rsv_release_bytes(struct btrfs_block_rsv *block_rsv,
                if (num_bytes) {
                        spin_lock(&space_info->lock);
                        space_info->bytes_reserved -= num_bytes;
+                       space_info->reservation_progress++;
                        spin_unlock(&space_info->lock);
                }
        }
@@ -3848,6 +3851,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
        if (block_rsv->reserved >= block_rsv->size) {
                num_bytes = block_rsv->reserved - block_rsv->size;
                sinfo->bytes_reserved -= num_bytes;
+               sinfo->reservation_progress++;
                block_rsv->reserved = block_rsv->size;
                block_rsv->full = 1;
        }
@@ -4009,7 +4013,6 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
                to_reserve = 0;
        }
        spin_unlock(&BTRFS_I(inode)->accounting_lock);
-
        to_reserve += calc_csum_metadata_size(inode, num_bytes);
        ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1);
        if (ret)
@@ -4036,6 +4039,7 @@ void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
 
        num_bytes = ALIGN(num_bytes, root->sectorsize);
        atomic_dec(&BTRFS_I(inode)->outstanding_extents);
+       WARN_ON(atomic_read(&BTRFS_I(inode)->outstanding_extents) < 0);
 
        spin_lock(&BTRFS_I(inode)->accounting_lock);
        nr_extents = atomic_read(&BTRFS_I(inode)->outstanding_extents);
@@ -4136,6 +4140,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                        btrfs_set_block_group_used(&cache->item, old_val);
                        cache->reserved -= num_bytes;
                        cache->space_info->bytes_reserved -= num_bytes;
+                       cache->space_info->reservation_progress++;
                        cache->space_info->bytes_used += num_bytes;
                        cache->space_info->disk_used += num_bytes * factor;
                        spin_unlock(&cache->lock);
@@ -4187,6 +4192,7 @@ static int pin_down_extent(struct btrfs_root *root,
        if (reserved) {
                cache->reserved -= num_bytes;
                cache->space_info->bytes_reserved -= num_bytes;
+               cache->space_info->reservation_progress++;
        }
        spin_unlock(&cache->lock);
        spin_unlock(&cache->space_info->lock);
@@ -4237,6 +4243,7 @@ static int update_reserved_bytes(struct btrfs_block_group_cache *cache,
                                space_info->bytes_readonly += num_bytes;
                        cache->reserved -= num_bytes;
                        space_info->bytes_reserved -= num_bytes;
+                       space_info->reservation_progress++;
                }
                spin_unlock(&cache->lock);
                spin_unlock(&space_info->lock);
@@ -4715,6 +4722,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
                if (ret) {
                        spin_lock(&cache->space_info->lock);
                        cache->space_info->bytes_reserved -= buf->len;
+                       cache->space_info->reservation_progress++;
                        spin_unlock(&cache->space_info->lock);
                }
                goto out;
@@ -5379,7 +5387,7 @@ again:
                               num_bytes, data, 1);
                goto again;
        }
-       if (ret == -ENOSPC) {
+       if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
                struct btrfs_space_info *sinfo;
 
                sinfo = __find_space_info(root->fs_info, data);
@@ -6586,7 +6594,7 @@ static noinline int relocate_data_extent(struct inode *reloc_inode,
        u64 end = start + extent_key->offset - 1;
 
        em = alloc_extent_map(GFP_NOFS);
-       BUG_ON(!em || IS_ERR(em));
+       BUG_ON(!em);
 
        em->start = start;
        em->len = extent_key->offset;
@@ -8068,6 +8076,13 @@ out:
        return ret;
 }
 
+int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
+                           struct btrfs_root *root, u64 type)
+{
+       u64 alloc_flags = get_alloc_profile(root, type);
+       return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
+}
+
 /*
  * helper to account the unused space of all the readonly block group in the
  * list. takes mirrors into account.
@@ -8325,6 +8340,13 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)
                if (block_group->cached == BTRFS_CACHE_STARTED)
                        wait_block_group_cache_done(block_group);
 
+               /*
+                * We haven't cached this block group, which means we could
+                * possibly have excluded extents on this block group.
+                */
+               if (block_group->cached == BTRFS_CACHE_NO)
+                       free_excluded_extents(info->extent_root, block_group);
+
                btrfs_remove_free_space_cache(block_group);
                btrfs_put_block_group(block_group);
 
@@ -8439,6 +8461,13 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                cache->flags = btrfs_block_group_flags(&cache->item);
                cache->sectorsize = root->sectorsize;
 
+               /*
+                * We need to exclude the super stripes now so that the space
+                * info has super bytes accounted for, otherwise we'll think
+                * we have more space than we actually do.
+                */
+               exclude_super_stripes(root, cache);
+
                /*
                 * check for two cases, either we are full, and therefore
                 * don't need to bother with the caching work since we won't
@@ -8447,12 +8476,10 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                 * time, particularly in the full case.
                 */
                if (found_key.offset == btrfs_block_group_used(&cache->item)) {
-                       exclude_super_stripes(root, cache);
                        cache->last_byte_to_unpin = (u64)-1;
                        cache->cached = BTRFS_CACHE_FINISHED;
                        free_excluded_extents(root, cache);
                } else if (btrfs_block_group_used(&cache->item) == 0) {
-                       exclude_super_stripes(root, cache);
                        cache->last_byte_to_unpin = (u64)-1;
                        cache->cached = BTRFS_CACHE_FINISHED;
                        add_new_free_space(cache, root->fs_info,