Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751462AbaLQNB6 (ORCPT ); Wed, 17 Dec 2014 08:01:58 -0500 Received: from mail-qg0-f41.google.com ([209.85.192.41]:41339 "EHLO mail-qg0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750979AbaLQNB5 (ORCPT ); Wed, 17 Dec 2014 08:01:57 -0500 From: Marc Dionne X-Google-Original-From: Marc Dionne To: snitzer@redhat.com, linux-kernel@vger.kernel.org, dm-devel@redhat.com Cc: agk@redhat.com, Marc Dionne Subject: [PATCH] dm thin: Initialize refcount and completion earlier Date: Wed, 17 Dec 2014 07:59:59 -0500 Message-Id: <1418821199-6890-1-git-send-email-marc.dionne@your-file-system.com> X-Mailer: git-send-email 2.1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The commit 80e96c5484be (dm thin: do not allow thin device activation while pool is suspended) delayed the initialization of the completion and setting the initial refcount to 1 until after the new thin is added to the pool's active thins list and the pool lock is released. This opens a race with a worker thread that walks the list and calls thin_get/put, noticing that the refcount goes to 0 and calling complete, freezing up the system and giving the oops below: kernel: BUG: unable to handle kernel NULL pointer dereference at (null) kernel: IP: [] __wake_up_common+0x2b/0x90 kernel: Call Trace: kernel: [] __wake_up_locked+0x13/0x20 kernel: [] complete+0x37/0x50 kernel: [] thin_put+0x20/0x30 [dm_thin_pool] kernel: [] do_worker+0x667/0x870 [dm_thin_pool] kernel: [] ? __schedule+0x3ac/0x9a0 kernel: [] process_one_work+0x14f/0x400 kernel: [] worker_thread+0x6b/0x490 kernel: [] ? rescuer_thread+0x260/0x260 kernel: [] kthread+0xdb/0x100 kernel: [] ? kthread_create_on_node+0x170/0x170 kernel: [] ret_from_fork+0x7c/0xb0 kernel: [] ? kthread_create_on_node+0x170/0x170 Set the initial refcount and initialize the completion before dropping the pool lock. Signed-off-by: Marc Dionne --- drivers/md/dm-thin.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 8735543..4133223 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -3814,6 +3814,8 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) r = -EINVAL; goto bad; } + atomic_set(&tc->refcount, 1); + init_completion(&tc->can_destroy); list_add_tail_rcu(&tc->list, &tc->pool->active_thins); spin_unlock_irqrestore(&tc->pool->lock, flags); /* @@ -3826,9 +3828,6 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv) dm_put(pool_md); - atomic_set(&tc->refcount, 1); - init_completion(&tc->can_destroy); - return 0; bad: -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/