From patchwork Thu Mar 9 10:16:21 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 9612951 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9BE51604D9 for ; Thu, 9 Mar 2017 10:16:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8AD3E285E6 for ; Thu, 9 Mar 2017 10:16:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7FBAE285ED; Thu, 9 Mar 2017 10:16:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 12AC8285E6 for ; Thu, 9 Mar 2017 10:16:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754427AbdCIKQl (ORCPT ); Thu, 9 Mar 2017 05:16:41 -0500 Received: from mx2.suse.de ([195.135.220.15]:51938 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753856AbdCIKQe (ORCPT ); Thu, 9 Mar 2017 05:16:34 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 934F4AC3B; Thu, 9 Mar 2017 10:16:31 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id A03C81E05D4; Thu, 9 Mar 2017 11:16:29 +0100 (CET) From: Jan Kara To: Jens Axboe Cc: Tejun Heo , linux-block@vger.kernel.org, Dan Williams , Omar Sandoval , Arthur Marsh , linux-scsi@vger.kernel.org, Jan Kara Subject: [PATCH 1/4] block: Allow bdi re-registration Date: Thu, 9 Mar 2017 11:16:21 +0100 Message-Id: <20170309101624.25901-2-jack@suse.cz> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20170309101624.25901-1-jack@suse.cz> References: <20170309101624.25901-1-jack@suse.cz> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP SCSI can call device_add_disk() several times for one request queue when a device in unbound and bound, creating new gendisk each time. This will lead to bdi being repeatedly registered and unregistered. This was not a big problem until commit 165a5e22fafb "block: Move bdi_unregister() to del_gendisk()" since bdi was only registered repeatedly (bdi_register() handles repeated calls fine, only we ended up leaking reference to gendisk due to overwriting bdi->owner) but unregistered only in blk_cleanup_queue() which didn't get called repeatedly. After 165a5e22fafb we were doing correct bdi_register() - bdi_unregister() cycles however bdi_unregister() is not prepared for it. So make sure bdi_unregister() cleans up bdi in such a way that it is prepared for a possible following bdi_register() call. An easy way to provoke this behavior is to enable CONFIG_DEBUG_TEST_DRIVER_REMOVE and use scsi_debug driver to create a scsi disk which immediately hangs without this fix. Fixes: 165a5e22fafb127ecb5914e12e8c32a1f0d3f820 Tested-by: Omar Sandoval Signed-off-by: Jan Kara Acked-by: Tejun Heo --- mm/backing-dev.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 6d861d090e9f..51325489aae5 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -710,6 +710,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi) */ atomic_dec(&bdi->usage_cnt); wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt)); + /* + * Reinitialize usage_cnt so that we hold reference when @bdi gets + * re-registered. + */ + atomic_set(&bdi->usage_cnt, 1); } /** @@ -857,6 +862,8 @@ int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner) MINOR(owner->devt)); if (rc) return rc; + /* Leaking owner reference... */ + WARN_ON(bdi->owner); bdi->owner = owner; get_device(owner); return 0;