btrfs: get fs_info from trans in write_one_cache_group
[sfrench/cifs-2.6.git] / fs / btrfs / extent-tree.c
index c5880329ae37c661b4e87b3cafc0599e776f242d..ef901d1685797a20e361022d588f158157645eea 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)
 {
@@ -2910,12 +2909,6 @@ static void delayed_ref_async_start(struct btrfs_work *work)
                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;
@@ -3322,10 +3315,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;
@@ -3673,8 +3666,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
@@ -3824,8 +3816,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 +3833,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);
@@ -6607,9 +6597,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;
@@ -8563,7 +8553,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 +9248,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 +9911,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 +10013,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 +10023,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 +10039,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;
@@ -10952,10 +10932,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 +10958,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 +10965,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 +11267,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 +11291,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 +11345,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;
@@ -11466,8 +11432,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;