2011/10/13 Josef Bacik <josef@xxxxxxxxxx>:
[...]
>> >> [ 175.956273] kernel BUG at fs/btrfs/inode.c:2176!
>> >
>> > Ok I think I see what's happening, this patch replaces the previous one, let me
>> > know how it goes. Thanks,
>> >
>>
>> Getting a slightly different BUG this time:
>>
>
> Ok looks like I've fixed the original problem and now we're hitting a problem
> with the free space cache. This patch will replace the last one, its all the
> fixes up to now and a new set of BUG_ON()'s to figure out which free space cache
> inode is screwing us up. Thanks,
>
> Josef
>
>
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index fc0de68..e595372 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -3334,7 +3334,7 @@ out:
> * shrink metadata reservation for delalloc
> */
> static int shrink_delalloc(struct btrfs_trans_handle *trans,
> - struct btrfs_root *root, u64 to_reclaim, int sync)
> + struct btrfs_root *root, u64 to_reclaim, int retries)
> {
> struct btrfs_block_rsv *block_rsv;
> struct btrfs_space_info *space_info;
> @@ -3365,12 +3365,10 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
> }
>
> max_reclaim = min(reserved, to_reclaim);
> + if (max_reclaim > (2 * 1024 * 1024))
> + nr_pages = max_reclaim >> PAGE_CACHE_SHIFT;
>
> while (loops < 1024) {
> - /* 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);
> @@ -3384,14 +3382,22 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
> if (reserved == 0 || reclaimed >= max_reclaim)
> break;
>
> - if (trans && trans->transaction->blocked)
> + if (trans)
> return -EAGAIN;
>
> - time_left = schedule_timeout_interruptible(1);
> + if (!retries) {
> + time_left = schedule_timeout_interruptible(1);
>
> - /* We were interrupted, exit */
> - if (time_left)
> - break;
> + /* We were interrupted, exit */
> + if (time_left)
> + break;
> + } else {
> + /*
> + * We've already done this song and dance once, let's
> + * really wait for some work to get done.
> + */
> + btrfs_wait_ordered_extents(root, 0, 0);
> + }
>
> /* 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
> @@ -3399,15 +3405,13 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
> * just too many writers without enough free space
> */
>
> - if (loops > 3) {
> + if (!retries && loops > 3) {
> smp_mb();
> if (progress != space_info->reservation_progress)
> break;
> }
>
> }
> - if (reclaimed < to_reclaim && !trans)
> - btrfs_wait_ordered_extents(root, 0, 0);
> return reclaimed >= to_reclaim;
> }
>
> @@ -3552,7 +3556,7 @@ again:
> * We do synchronous shrinking since we don't actually unreserve
> * metadata until after the IO is completed.
> */
> - ret = shrink_delalloc(trans, root, num_bytes, 1);
> + ret = shrink_delalloc(trans, root, num_bytes, retries);
> if (ret < 0)
> goto out;
>
> @@ -3568,17 +3572,6 @@ again:
> goto again;
> }
>
> - /*
> - * Not enough space to be reclaimed, don't bother committing the
> - * transaction.
> - */
> - spin_lock(&space_info->lock);
> - if (space_info->bytes_pinned < orig_bytes)
> - ret = -ENOSPC;
> - spin_unlock(&space_info->lock);
> - if (ret)
> - goto out;
> -
> ret = -EAGAIN;
> if (trans)
> goto out;
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index d6ba353..cb63904 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -782,7 +782,8 @@ static noinline int cow_file_range(struct inode *inode,
> struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
> int ret = 0;
>
> - BUG_ON(btrfs_is_free_space_inode(root, inode));
> + BUG_ON(root == root->fs_info->tree_root);
> + BUG_ON(BTRFS_I(inode)->location.objectid == BTRFS_FREE_INO_OBJECTID);
> trans = btrfs_join_transaction(root);
> BUG_ON(IS_ERR(trans));
> trans->block_rsv = &root->fs_info->delalloc_block_rsv;
> @@ -2790,7 +2791,8 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
> return ERR_PTR(-ENOMEM);
> }
>
> - trans = btrfs_start_transaction(root, 0);
> + /* 1 for the orphan item */
> + trans = btrfs_start_transaction(root, 1);
> if (IS_ERR(trans)) {
> btrfs_free_path(path);
> root->fs_info->enospc_unlink = 0;
Could it be, that the missing space for the orphan item, is the reason
for our warning?
[ 105.209232] ------------[ cut here ]------------
[ 105.214458] WARNING: at fs/btrfs/inode.c:2114
btrfs_orphan_commit_root+0xb0/0xc0 [btrfs]()
[ 105.223794] Hardware name: ProLiant DL180 G6
[ 105.228930] Modules linked in: btrfs zlib_deflate libcrc32c bonding
ipv6 serio_raw pcspkr ghes hed iTCO_wdt iTCO_vendor_support
i7core_edac edac_core ixgbe dca mdio iomemory_vsl(P) hpsa squashfs
[last unloaded: scsi_wait_scan]
[ 105.253539] Pid: 1774, comm: kworker/0:2 Tainted: P
3.0.6-1.fits.2.el6.x86_64 #1
[ 105.263015] Call Trace:
[ 105.265956] [<ffffffff8106344f>] warn_slowpath_common+0x7f/0xc0
[ 105.272841] [<ffffffff810634aa>] warn_slowpath_null+0x1a/0x20
[ 105.279503] [<ffffffffa022bef0>] btrfs_orphan_commit_root+0xb0/0xc0 [btrfs]
[ 105.287564] [<ffffffffa0226ce5>] commit_fs_roots+0xc5/0x1b0 [btrfs]
[ 105.294824] [<ffffffffa0227c36>]
btrfs_commit_transaction+0x3c6/0x820 [btrfs]
[ 105.303044] [<ffffffff810507c0>] ? __dequeue_entity+0x30/0x50
[ 105.309745] [<ffffffff81086410>] ? wake_up_bit+0x40/0x40
[ 105.315944] [<ffffffffa0228090>] ?
btrfs_commit_transaction+0x820/0x820 [btrfs]
[ 105.324404] [<ffffffffa02280af>] do_async_commit+0x1f/0x30 [btrfs]
[ 105.331590] [<ffffffff8107e8b8>] process_one_work+0x128/0x450
[ 105.338291] [<ffffffff810816cb>] worker_thread+0x17b/0x3c0
[ 105.344708] [<ffffffff81081550>] ? manage_workers+0x220/0x220
[ 105.351407] [<ffffffff81085d96>] kthread+0x96/0xa0
[ 105.357040] [<ffffffff815639c4>] kernel_thread_helper+0x4/0x10
[ 105.363824] [<ffffffff81085d00>] ? kthread_worker_fn+0x1a0/0x1a0
[ 105.370776] [<ffffffff815639c0>] ? gs_change+0x13/0x13
[ 105.376771] ---[ end trace 144230b62b45be67 ]---
Thanks,
Christian
> @@ -2901,6 +2903,11 @@ out:
> return ERR_PTR(err);
> }
>
> + ret = btrfs_block_rsv_migrate(trans->block_rsv,
> + &root->fs_info->global_block_rsv,
> + btrfs_calc_trans_metadata_size(root, 1));
> + BUG_ON(ret);
> +
> trans->block_rsv = &root->fs_info->global_block_rsv;
> return trans;
> }
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html