Skip to content

Commit e62063d

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason: "This is a small collection of fixes, including a regression fix from Liu Bo that solves rare crashes with compression on. I've merged my for-linus up to 3.12-rc3 because the top commit is only meant for 3.12. The rest of the fixes are also available in my master branch on top of my last 3.11 based pull" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: btrfs: Fix crash due to not allocating integrity data for a bioset Btrfs: fix a use-after-free bug in btrfs_dev_replace_finishing Btrfs: eliminate races in worker stopping code Btrfs: fix crash of compressed writes Btrfs: fix transid verify errors when recovering log tree
2 parents 85f6d2d + b208c2f commit e62063d

File tree

6 files changed

+39
-17
lines changed

6 files changed

+39
-17
lines changed

fs/btrfs/async-thread.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ static void check_idle_worker(struct btrfs_worker_thread *worker)
107107
worker->idle = 1;
108108

109109
/* the list may be empty if the worker is just starting */
110-
if (!list_empty(&worker->worker_list)) {
110+
if (!list_empty(&worker->worker_list) &&
111+
!worker->workers->stopping) {
111112
list_move(&worker->worker_list,
112113
&worker->workers->idle_list);
113114
}
@@ -127,7 +128,8 @@ static void check_busy_worker(struct btrfs_worker_thread *worker)
127128
spin_lock_irqsave(&worker->workers->lock, flags);
128129
worker->idle = 0;
129130

130-
if (!list_empty(&worker->worker_list)) {
131+
if (!list_empty(&worker->worker_list) &&
132+
!worker->workers->stopping) {
131133
list_move_tail(&worker->worker_list,
132134
&worker->workers->worker_list);
133135
}
@@ -412,6 +414,7 @@ void btrfs_stop_workers(struct btrfs_workers *workers)
412414
int can_stop;
413415

414416
spin_lock_irq(&workers->lock);
417+
workers->stopping = 1;
415418
list_splice_init(&workers->idle_list, &workers->worker_list);
416419
while (!list_empty(&workers->worker_list)) {
417420
cur = workers->worker_list.next;
@@ -455,6 +458,7 @@ void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
455458
workers->ordered = 0;
456459
workers->atomic_start_pending = 0;
457460
workers->atomic_worker_start = async_helper;
461+
workers->stopping = 0;
458462
}
459463

460464
/*
@@ -480,24 +484,33 @@ static int __btrfs_start_workers(struct btrfs_workers *workers)
480484
atomic_set(&worker->num_pending, 0);
481485
atomic_set(&worker->refs, 1);
482486
worker->workers = workers;
483-
worker->task = kthread_run(worker_loop, worker,
484-
"btrfs-%s-%d", workers->name,
485-
workers->num_workers + 1);
487+
worker->task = kthread_create(worker_loop, worker,
488+
"btrfs-%s-%d", workers->name,
489+
workers->num_workers + 1);
486490
if (IS_ERR(worker->task)) {
487491
ret = PTR_ERR(worker->task);
488-
kfree(worker);
489492
goto fail;
490493
}
494+
491495
spin_lock_irq(&workers->lock);
496+
if (workers->stopping) {
497+
spin_unlock_irq(&workers->lock);
498+
goto fail_kthread;
499+
}
492500
list_add_tail(&worker->worker_list, &workers->idle_list);
493501
worker->idle = 1;
494502
workers->num_workers++;
495503
workers->num_workers_starting--;
496504
WARN_ON(workers->num_workers_starting < 0);
497505
spin_unlock_irq(&workers->lock);
498506

507+
wake_up_process(worker->task);
499508
return 0;
509+
510+
fail_kthread:
511+
kthread_stop(worker->task);
500512
fail:
513+
kfree(worker);
501514
spin_lock_irq(&workers->lock);
502515
workers->num_workers_starting--;
503516
spin_unlock_irq(&workers->lock);

fs/btrfs/async-thread.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ struct btrfs_workers {
107107

108108
/* extra name for this worker, used for current->name */
109109
char *name;
110+
111+
int stopping;
110112
};
111113

112114
void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);

fs/btrfs/dev-replace.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
535535
list_add(&tgt_device->dev_alloc_list, &fs_info->fs_devices->alloc_list);
536536

537537
btrfs_rm_dev_replace_srcdev(fs_info, src_device);
538-
if (src_device->bdev) {
539-
/* zero out the old super */
540-
btrfs_scratch_superblock(src_device);
541-
}
538+
542539
/*
543540
* this is again a consistent state where no dev_replace procedure
544541
* is running, the target device is part of the filesystem, the

fs/btrfs/extent_io.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,16 @@ int __init extent_io_init(void)
145145
offsetof(struct btrfs_io_bio, bio));
146146
if (!btrfs_bioset)
147147
goto free_buffer_cache;
148+
149+
if (bioset_integrity_create(btrfs_bioset, BIO_POOL_SIZE))
150+
goto free_bioset;
151+
148152
return 0;
149153

154+
free_bioset:
155+
bioset_free(btrfs_bioset);
156+
btrfs_bioset = NULL;
157+
150158
free_buffer_cache:
151159
kmem_cache_destroy(extent_buffer_cache);
152160
extent_buffer_cache = NULL;
@@ -1614,7 +1622,7 @@ static noinline u64 find_lock_delalloc_range(struct inode *inode,
16141622
*start = delalloc_start;
16151623
*end = delalloc_end;
16161624
free_extent_state(cached_state);
1617-
return found;
1625+
return 0;
16181626
}
16191627

16201628
/*

fs/btrfs/transaction.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,11 +1838,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
18381838
assert_qgroups_uptodate(trans);
18391839
update_super_roots(root);
18401840

1841-
if (!root->fs_info->log_root_recovering) {
1842-
btrfs_set_super_log_root(root->fs_info->super_copy, 0);
1843-
btrfs_set_super_log_root_level(root->fs_info->super_copy, 0);
1844-
}
1845-
1841+
btrfs_set_super_log_root(root->fs_info->super_copy, 0);
1842+
btrfs_set_super_log_root_level(root->fs_info->super_copy, 0);
18461843
memcpy(root->fs_info->super_for_commit, root->fs_info->super_copy,
18471844
sizeof(*root->fs_info->super_copy));
18481845

fs/btrfs/volumes.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,7 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
17161716
struct btrfs_device *srcdev)
17171717
{
17181718
WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex));
1719+
17191720
list_del_rcu(&srcdev->dev_list);
17201721
list_del_rcu(&srcdev->dev_alloc_list);
17211722
fs_info->fs_devices->num_devices--;
@@ -1725,9 +1726,13 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
17251726
}
17261727
if (srcdev->can_discard)
17271728
fs_info->fs_devices->num_can_discard--;
1728-
if (srcdev->bdev)
1729+
if (srcdev->bdev) {
17291730
fs_info->fs_devices->open_devices--;
17301731

1732+
/* zero out the old super */
1733+
btrfs_scratch_superblock(srcdev);
1734+
}
1735+
17311736
call_rcu(&srcdev->rcu, free_device);
17321737
}
17331738

0 commit comments

Comments
 (0)