Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp697345ybz; Fri, 1 May 2020 07:01:08 -0700 (PDT) X-Google-Smtp-Source: APiQypLnnc/UuCYk6qiXR3RVnzFyhMHe6FmUpj+X2h1NnguWkHZf89o2zzk7R+4y/Qwv0Q3T+lIp X-Received: by 2002:a50:ee0e:: with SMTP id g14mr3719873eds.34.1588341668068; Fri, 01 May 2020 07:01:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588341668; cv=none; d=google.com; s=arc-20160816; b=id9GSlKStqPhJF1uJEVaFqzCNmgL61kCoSl5suk7sPHeQr6gK8Tu0Q9PgrM0j0eWZh I4Tm4ANgUcWzMiJZRKbNjthNJamOYgHAuHYLtwFuKmWoPQCjU0SwOuEOZiCQgcYlHRBw 63Ex23GPFScyfc1Df9nf8xIqWalVkdkuPMBIME4jSjzAFYG+BlhWncpxmUmN3/JFB4pB 3+qijUyLrEb9k7VRh71h9vQyFcCnpsnmgLGikg/hmLMhgchJPwfhSMmm2O0C2Euwy/wW i+GvXDb3GpNMjsmS0sc0Lo/iloIXT2czNNzjYWb2cdC4oiSl3gFNX7rN9F7RC9nFvW5N Hutg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=JKWCHP1lDLHt7PccwVdHVhgSYleQk024YoHr2m8fpS4=; b=O5zduv3kn5WkSa+bdZ1oVENGHQV48vA2a39t6EwYFyQgzo1I/F+XLieraOG3c639QY ZX1/zdka8aNfOHANAO3gfc3EwHfIVHRLJKN6FnScoPKVcCS2qyPkBij8dGV1GOcUrOhO DL5dkuPPMDJ3cGL6rRtJT7dhD/aWuTWR3Z04xWNAdtC3EKJ/V5jF683Wgc7bqGX5/ASg X3p7BF3vXFVAqV16UzgN4jH6kaXbZhPYTa7C8XDMdv9DH5dxIry94bJaWdStb6Ye5FBu BcRKHZbmMxJM4QBDGaqLr0ngLWSUSvWzcm70q8njS2Oy8mVk9MzlPmju6OufGlkdaFYL 04Hw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=L+1lbP5D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bc23si1646337edb.241.2020.05.01.07.00.44; Fri, 01 May 2020 07:01:08 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=L+1lbP5D; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729908AbgEANaR (ORCPT + 99 others); Fri, 1 May 2020 09:30:17 -0400 Received: from mail.kernel.org ([198.145.29.99]:54098 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729898AbgEANaN (ORCPT ); Fri, 1 May 2020 09:30:13 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 2B6ED208C3; Fri, 1 May 2020 13:30:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588339812; bh=PfmHYvVYYPHRR8l7nqz1iLpSdLhmCb4oaAshHsMMEv0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L+1lbP5DUt4pzWSY7nIrGpsLmCjCUcPfKkuLj6iFlZA8MGAMZMY6uEQfdeSw25XGv SXXNuyU21BrbxzsNbfQ/4bV/moO3Q2MBRpd/wRAZg4ns2ijv4ntKiaN5ihLsEVAkQD sVqsjSjPUObl0FH7/1k67bAKV09X0IbkjmTqRuIo= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Oliver Neukum Subject: [PATCH 4.9 57/80] UAS: fix deadlock in error handling and PM flushing work Date: Fri, 1 May 2020 15:21:51 +0200 Message-Id: <20200501131530.792275212@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200501131513.810761598@linuxfoundation.org> References: <20200501131513.810761598@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Oliver Neukum commit f6cc6093a729ede1ff5658b493237c42b82ba107 upstream. A SCSI error handler and block runtime PM must not allocate memory with GFP_KERNEL. Furthermore they must not wait for tasks allocating memory with GFP_KERNEL. That means that they cannot share a workqueue with arbitrary tasks. Fix this for UAS using a private workqueue. Signed-off-by: Oliver Neukum Fixes: f9dc024a2da1f ("uas: pre_reset and suspend: Fix a few races") Cc: stable Link: https://lore.kernel.org/r/20200415141750.811-2-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -82,6 +82,19 @@ static void uas_free_streams(struct uas_ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix, int status); +/* + * This driver needs its own workqueue, as we need to control memory allocation. + * + * In the course of error handling and power management uas_wait_for_pending_cmnds() + * needs to flush pending work items. In these contexts we cannot allocate memory + * by doing block IO as we would deadlock. For the same reason we cannot wait + * for anything allocating memory not heeding these constraints. + * + * So we have to control all work items that can be on the workqueue we flush. + * Hence we cannot share a queue and need our own. + */ +static struct workqueue_struct *workqueue; + static void uas_do_work(struct work_struct *work) { struct uas_dev_info *devinfo = @@ -110,7 +123,7 @@ static void uas_do_work(struct work_stru if (!err) cmdinfo->state &= ~IS_IN_WORK_LIST; else - schedule_work(&devinfo->work); + queue_work(workqueue, &devinfo->work); } out: spin_unlock_irqrestore(&devinfo->lock, flags); @@ -135,7 +148,7 @@ static void uas_add_work(struct uas_cmd_ lockdep_assert_held(&devinfo->lock); cmdinfo->state |= IS_IN_WORK_LIST; - schedule_work(&devinfo->work); + queue_work(workqueue, &devinfo->work); } static void uas_zap_pending(struct uas_dev_info *devinfo, int result) @@ -1236,7 +1249,31 @@ static struct usb_driver uas_driver = { .id_table = uas_usb_ids, }; -module_usb_driver(uas_driver); +static int __init uas_init(void) +{ + int rv; + + workqueue = alloc_workqueue("uas", WQ_MEM_RECLAIM, 0); + if (!workqueue) + return -ENOMEM; + + rv = usb_register(&uas_driver); + if (rv) { + destroy_workqueue(workqueue); + return -ENOMEM; + } + + return 0; +} + +static void __exit uas_exit(void) +{ + usb_deregister(&uas_driver); + destroy_workqueue(workqueue); +} + +module_init(uas_init); +module_exit(uas_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(