btrfs: get fs_info from block group in next_block_group
[sfrench/cifs-2.6.git] / fs / btrfs / extent-tree.c
index c5880329ae37c661b4e87b3cafc0599e776f242d..7a0f3e1519996b86e099125de0785e22023fa706 100644 (file)
@@ -1905,7 +1905,6 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
        return ret;
 }
 
-#define in_range(b, first, len)        ((b) >= (first) && (b) < (first) + (len))
 static int btrfs_issue_discard(struct block_device *bdev, u64 start, u64 len,
                               u64 *discarded_bytes)
 {
@@ -2877,97 +2876,6 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans)
        return btrfs_check_space_for_delayed_refs(trans->fs_info);
 }
 
-struct async_delayed_refs {
-       struct btrfs_root *root;
-       u64 transid;
-       int count;
-       int error;
-       int sync;
-       struct completion wait;
-       struct btrfs_work work;
-};
-
-static inline struct async_delayed_refs *
-to_async_delayed_refs(struct btrfs_work *work)
-{
-       return container_of(work, struct async_delayed_refs, work);
-}
-
-static void delayed_ref_async_start(struct btrfs_work *work)
-{
-       struct async_delayed_refs *async = to_async_delayed_refs(work);
-       struct btrfs_trans_handle *trans;
-       struct btrfs_fs_info *fs_info = async->root->fs_info;
-       int ret;
-
-       /* if the commit is already started, we don't need to wait here */
-       if (btrfs_transaction_blocked(fs_info))
-               goto done;
-
-       trans = btrfs_join_transaction(async->root);
-       if (IS_ERR(trans)) {
-               async->error = PTR_ERR(trans);
-               goto done;
-       }
-
-       /*
-        * trans->sync means that when we call end_transaction, we won't
-        * wait on delayed refs
-        */
-       trans->sync = true;
-
-       /* Don't bother flushing if we got into a different transaction */
-       if (trans->transid > async->transid)
-               goto end;
-
-       ret = btrfs_run_delayed_refs(trans, async->count);
-       if (ret)
-               async->error = ret;
-end:
-       ret = btrfs_end_transaction(trans);
-       if (ret && !async->error)
-               async->error = ret;
-done:
-       if (async->sync)
-               complete(&async->wait);
-       else
-               kfree(async);
-}
-
-int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info,
-                                unsigned long count, u64 transid, int wait)
-{
-       struct async_delayed_refs *async;
-       int ret;
-
-       async = kmalloc(sizeof(*async), GFP_NOFS);
-       if (!async)
-               return -ENOMEM;
-
-       async->root = fs_info->tree_root;
-       async->count = count;
-       async->error = 0;
-       async->transid = transid;
-       if (wait)
-               async->sync = 1;
-       else
-               async->sync = 0;
-       init_completion(&async->wait);
-
-       btrfs_init_work(&async->work, btrfs_extent_refs_helper,
-                       delayed_ref_async_start, NULL, NULL);
-
-       btrfs_queue_work(fs_info->extent_workers, &async->work);
-
-       if (wait) {
-               wait_for_completion(&async->wait);
-               ret = async->error;
-               kfree(async);
-               return ret;
-       }
-       return 0;
-}
-
 /*
  * this starts processing the delayed reference count updates and
  * extent insertions we have queued up so far.  count can be
@@ -3322,10 +3230,10 @@ int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 }
 
 static int write_one_cache_group(struct btrfs_trans_handle *trans,
-                                struct btrfs_fs_info *fs_info,
                                 struct btrfs_path *path,
                                 struct btrfs_block_group_cache *cache)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        int ret;
        struct btrfs_root *extent_root = fs_info->extent_root;
        unsigned long bi;
@@ -3348,10 +3256,10 @@ fail:
 
 }
 
-static struct btrfs_block_group_cache *
-next_block_group(struct btrfs_fs_info *fs_info,
-                struct btrfs_block_group_cache *cache)
+static struct btrfs_block_group_cache *next_block_group(
+               struct btrfs_block_group_cache *cache)
 {
+       struct btrfs_fs_info *fs_info = cache->fs_info;
        struct rb_node *node;
 
        spin_lock(&fs_info->block_group_cache_lock);
@@ -3418,8 +3326,7 @@ again:
                if (block_group->ro)
                        goto out_free;
 
-               ret = create_free_space_inode(fs_info, trans, block_group,
-                                             path);
+               ret = create_free_space_inode(trans, block_group, path);
                if (ret)
                        goto out_free;
                goto again;
@@ -3538,9 +3445,9 @@ out:
        return ret;
 }
 
-int btrfs_setup_space_cache(struct btrfs_trans_handle *trans,
-                           struct btrfs_fs_info *fs_info)
+int btrfs_setup_space_cache(struct btrfs_trans_handle *trans)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_block_group_cache *cache, *tmp;
        struct btrfs_transaction *cur_trans = trans->transaction;
        struct btrfs_path *path;
@@ -3652,8 +3559,7 @@ again:
 
                if (cache->disk_cache_state == BTRFS_DC_SETUP) {
                        cache->io_ctl.inode = NULL;
-                       ret = btrfs_write_out_cache(fs_info, trans,
-                                                   cache, path);
+                       ret = btrfs_write_out_cache(trans, cache, path);
                        if (ret == 0 && cache->io_ctl.inode) {
                                num_started++;
                                should_put = 0;
@@ -3673,8 +3579,7 @@ again:
                        }
                }
                if (!ret) {
-                       ret = write_one_cache_group(trans, fs_info,
-                                                   path, cache);
+                       ret = write_one_cache_group(trans, path, cache);
                        /*
                         * Our block group might still be attached to the list
                         * of new block groups in the transaction handle of some
@@ -3744,9 +3649,9 @@ again:
        return ret;
 }
 
-int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
-                                  struct btrfs_fs_info *fs_info)
+int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)
 {
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_block_group_cache *cache;
        struct btrfs_transaction *cur_trans = trans->transaction;
        int ret = 0;
@@ -3809,8 +3714,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
 
                if (!ret && cache->disk_cache_state == BTRFS_DC_SETUP) {
                        cache->io_ctl.inode = NULL;
-                       ret = btrfs_write_out_cache(fs_info, trans,
-                                                   cache, path);
+                       ret = btrfs_write_out_cache(trans, cache, path);
                        if (ret == 0 && cache->io_ctl.inode) {
                                num_started++;
                                should_put = 0;
@@ -3824,8 +3728,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                        }
                }
                if (!ret) {
-                       ret = write_one_cache_group(trans, fs_info,
-                                                   path, cache);
+                       ret = write_one_cache_group(trans, path, cache);
                        /*
                         * One of the free space endio workers might have
                         * created a new block group while updating a free space
@@ -3842,8 +3745,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
                        if (ret == -ENOENT) {
                                wait_event(cur_trans->writer_wait,
                                   atomic_read(&cur_trans->num_writers) == 1);
-                               ret = write_one_cache_group(trans, fs_info,
-                                                           path, cache);
+                               ret = write_one_cache_group(trans, path, cache);
                        }
                        if (ret)
                                btrfs_abort_transaction(trans, ret);
@@ -6361,9 +6263,9 @@ void btrfs_delalloc_release_space(struct inode *inode,
 }
 
 static int update_block_group(struct btrfs_trans_handle *trans,
-                             struct btrfs_fs_info *info, u64 bytenr,
-                             u64 num_bytes, int alloc)
+                             u64 bytenr, u64 num_bytes, int alloc)
 {
+       struct btrfs_fs_info *info = trans->fs_info;
        struct btrfs_block_group_cache *cache = NULL;
        u64 total = num_bytes;
        u64 old_val;
@@ -6444,7 +6346,6 @@ static int update_block_group(struct btrfs_trans_handle *trans,
                if (list_empty(&cache->dirty_list)) {
                        list_add_tail(&cache->dirty_list,
                                      &trans->transaction->dirty_bgs);
-                       trans->transaction->num_dirty_bgs++;
                        trans->delayed_ref_updates++;
                        btrfs_get_block_group(cache);
                }
@@ -6607,9 +6508,9 @@ out_lock:
        return ret;
 }
 
-int btrfs_exclude_logged_extents(struct btrfs_fs_info *fs_info,
-                                struct extent_buffer *eb)
+int btrfs_exclude_logged_extents(struct extent_buffer *eb)
 {
+       struct btrfs_fs_info *fs_info = eb->fs_info;
        struct btrfs_file_extent_item *item;
        struct btrfs_key key;
        int found_type;
@@ -7198,7 +7099,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                        goto out;
                }
 
-               ret = update_block_group(trans, info, bytenr, num_bytes, 0);
+               ret = update_block_group(trans, bytenr, num_bytes, 0);
                if (ret) {
                        btrfs_abort_transaction(trans, ret);
                        goto out;
@@ -8370,7 +8271,7 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
        if (ret)
                return ret;
 
-       ret = update_block_group(trans, fs_info, ins->objectid, ins->offset, 1);
+       ret = update_block_group(trans, ins->objectid, ins->offset, 1);
        if (ret) { /* -ENOENT, logic error */
                btrfs_err(fs_info, "update block group failed for %llu %llu",
                        ins->objectid, ins->offset);
@@ -8460,7 +8361,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
        if (ret)
                return ret;
 
-       ret = update_block_group(trans, fs_info, extent_key.objectid,
+       ret = update_block_group(trans, extent_key.objectid,
                                 fs_info->nodesize, 1);
        if (ret) { /* -ENOENT, logic error */
                btrfs_err(fs_info, "update block group failed for %llu %llu",
@@ -8563,7 +8464,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, buf, level);
        btrfs_tree_lock(buf);
-       clean_tree_block(fs_info, buf);
+       btrfs_clean_tree_block(buf);
        clear_bit(EXTENT_BUFFER_STALE, &buf->bflags);
 
        btrfs_set_lock_blocking_write(buf);
@@ -9258,14 +9159,14 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
                                             ret);
                        }
                }
-               /* make block locked assertion in clean_tree_block happy */
+               /* make block locked assertion in btrfs_clean_tree_block happy */
                if (!path->locks[level] &&
                    btrfs_header_generation(eb) == trans->transid) {
                        btrfs_tree_lock(eb);
                        btrfs_set_lock_blocking_write(eb);
                        path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
                }
-               clean_tree_block(fs_info, eb);
+               btrfs_clean_tree_block(eb);
        }
 
        if (eb == root->node) {
@@ -9921,12 +9822,10 @@ void btrfs_dec_block_group_ro(struct btrfs_block_group_cache *cache)
  */
 int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr)
 {
-       struct btrfs_root *root = fs_info->extent_root;
        struct btrfs_block_group_cache *block_group;
        struct btrfs_space_info *space_info;
        struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
        struct btrfs_device *device;
-       struct btrfs_trans_handle *trans;
        u64 min_free;
        u64 dev_min = 1;
        u64 dev_nr = 0;
@@ -10025,13 +9924,6 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr)
                min_free = div64_u64(min_free, dev_min);
        }
 
-       /* We need to do this so that we can look at pending chunks */
-       trans = btrfs_join_transaction(root);
-       if (IS_ERR(trans)) {
-               ret = PTR_ERR(trans);
-               goto out;
-       }
-
        mutex_lock(&fs_info->chunk_mutex);
        list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
                u64 dev_offset;
@@ -10042,7 +9934,7 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr)
                 */
                if (device->total_bytes > device->bytes_used + min_free &&
                    !test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state)) {
-                       ret = find_free_dev_extent(trans, device, min_free,
+                       ret = find_free_dev_extent(device, min_free,
                                                   &dev_offset, NULL);
                        if (!ret)
                                dev_nr++;
@@ -10058,7 +9950,6 @@ int btrfs_can_relocate(struct btrfs_fs_info *fs_info, u64 bytenr)
                           "no space to allocate a new chunk for block group %llu",
                           block_group->key.objectid);
        mutex_unlock(&fs_info->chunk_mutex);
-       btrfs_end_transaction(trans);
 out:
        btrfs_put_block_group(block_group);
        return ret;
@@ -10159,7 +10050,7 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info)
                        if (block_group->iref)
                                break;
                        spin_unlock(&block_group->lock);
-                       block_group = next_block_group(info, block_group);
+                       block_group = next_block_group(block_group);
                }
                if (!block_group) {
                        if (last == 0)
@@ -10660,7 +10551,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, u64 bytes_used,
        struct btrfs_block_group_cache *cache;
        int ret;
 
-       btrfs_set_log_full_commit(fs_info, trans);
+       btrfs_set_log_full_commit(trans);
 
        cache = btrfs_create_block_group_cache(fs_info, chunk_offset, size);
        if (!cache)
@@ -10952,10 +10843,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
        memcpy(&key, &block_group->key, sizeof(key));
 
        mutex_lock(&fs_info->chunk_mutex);
-       if (!list_empty(&em->list)) {
-               /* We're in the transaction->pending_chunks list. */
-               free_extent_map(em);
-       }
        spin_lock(&block_group->lock);
        block_group->removed = 1;
        /*
@@ -10982,25 +10869,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
         * the transaction commit has completed.
         */
        remove_em = (atomic_read(&block_group->trimming) == 0);
-       /*
-        * Make sure a trimmer task always sees the em in the pinned_chunks list
-        * if it sees block_group->removed == 1 (needs to lock block_group->lock
-        * before checking block_group->removed).
-        */
-       if (!remove_em) {
-               /*
-                * Our em might be in trans->transaction->pending_chunks which
-                * is protected by fs_info->chunk_mutex ([lock|unlock]_chunks),
-                * and so is the fs_info->pinned_chunks list.
-                *
-                * So at this point we must be holding the chunk_mutex to avoid
-                * any races with chunk allocation (more specifically at
-                * volumes.c:contains_pending_extent()), to ensure it always
-                * sees the em, either in the pending_chunks list or in the
-                * pinned_chunks list.
-                */
-               list_move_tail(&em->list, &fs_info->pinned_chunks);
-       }
        spin_unlock(&block_group->lock);
 
        if (remove_em) {
@@ -11008,11 +10876,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 
                em_tree = &fs_info->mapping_tree.map_tree;
                write_lock(&em_tree->lock);
-               /*
-                * The em might be in the pending_chunks list, so make sure the
-                * chunk mutex is locked, since remove_extent_mapping() will
-                * delete us from that list.
-                */
                remove_extent_mapping(em_tree, em);
                write_unlock(&em_tree->lock);
                /* once for the tree */
@@ -11315,11 +11178,12 @@ int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
  * held back allocations.
  */
 static int btrfs_trim_free_extents(struct btrfs_device *device,
-                                  u64 minlen, u64 *trimmed)
+                                  struct fstrim_range *range, u64 *trimmed)
 {
-       u64 start = 0, len = 0;
+       u64 start, len = 0, end = 0;
        int ret;
 
+       start = max_t(u64, range->start, SZ_1M);
        *trimmed = 0;
 
        /* Discard not supported = nothing to do. */
@@ -11338,43 +11202,52 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
 
        while (1) {
                struct btrfs_fs_info *fs_info = device->fs_info;
-               struct btrfs_transaction *trans;
                u64 bytes;
 
                ret = mutex_lock_interruptible(&fs_info->chunk_mutex);
                if (ret)
                        break;
 
-               ret = down_read_killable(&fs_info->commit_root_sem);
-               if (ret) {
+               find_first_clear_extent_bit(&device->alloc_state, start,
+                                           &start, &end,
+                                           CHUNK_TRIMMED | CHUNK_ALLOCATED);
+               /*
+                * If find_first_clear_extent_bit find a range that spans the
+                * end of the device it will set end to -1, in this case it's up
+                * to the caller to trim the value to the size of the device.
+                */
+               end = min(end, device->total_bytes - 1);
+               len = end - start + 1;
+
+               /* We didn't find any extents */
+               if (!len) {
                        mutex_unlock(&fs_info->chunk_mutex);
+                       ret = 0;
                        break;
                }
 
-               spin_lock(&fs_info->trans_lock);
-               trans = fs_info->running_transaction;
-               if (trans)
-                       refcount_inc(&trans->use_count);
-               spin_unlock(&fs_info->trans_lock);
-
-               if (!trans)
-                       up_read(&fs_info->commit_root_sem);
-
-               ret = find_free_dev_extent_start(trans, device, minlen, start,
-                                                &start, &len);
-               if (trans) {
-                       up_read(&fs_info->commit_root_sem);
-                       btrfs_put_transaction(trans);
+               /* Keep going until we satisfy minlen or reach end of space */
+               if (len < range->minlen) {
+                       mutex_unlock(&fs_info->chunk_mutex);
+                       start += len;
+                       continue;
                }
 
-               if (ret) {
+               /* If we are out of the passed range break */
+               if (start > range->start + range->len - 1) {
                        mutex_unlock(&fs_info->chunk_mutex);
-                       if (ret == -ENOSPC)
-                               ret = 0;
                        break;
                }
 
-               ret = btrfs_issue_discard(device->bdev, start, len, &bytes);
+               start = max(range->start, start);
+               len = min(range->len, len);
+
+               ret = btrfs_issue_discard(device->bdev, start, len,
+                                         &bytes);
+               if (!ret)
+                       set_extent_bits(&device->alloc_state, start,
+                                       start + bytes - 1,
+                                       CHUNK_TRIMMED);
                mutex_unlock(&fs_info->chunk_mutex);
 
                if (ret)
@@ -11383,6 +11256,10 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
                start += len;
                *trimmed += bytes;
 
+               /* We've trimmed enough */
+               if (*trimmed >= range->len)
+                       break;
+
                if (fatal_signal_pending(current)) {
                        ret = -ERESTARTSYS;
                        break;
@@ -11419,7 +11296,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        int ret = 0;
 
        cache = btrfs_lookup_first_block_group(fs_info, range->start);
-       for (; cache; cache = next_block_group(fs_info, cache)) {
+       for (; cache; cache = next_block_group(cache)) {
                if (cache->key.objectid >= (range->start + range->len)) {
                        btrfs_put_block_group(cache);
                        break;
@@ -11466,8 +11343,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
        mutex_lock(&fs_info->fs_devices->device_list_mutex);
        devices = &fs_info->fs_devices->devices;
        list_for_each_entry(device, devices, dev_list) {
-               ret = btrfs_trim_free_extents(device, range->minlen,
-                                             &group_trimmed);
+               ret = btrfs_trim_free_extents(device, range, &group_trimmed);
                if (ret) {
                        dev_failed++;
                        dev_ret = ret;