From patchwork Fri Apr 27 09:31:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 155403 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id C530FB6F9F for ; Fri, 27 Apr 2012 19:32:21 +1000 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SNhX5-0005WR-Nd; Fri, 27 Apr 2012 09:32:07 +0000 Received: from mail-pz0-f48.google.com ([209.85.210.48]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SNhX4-0005WE-7Z for kernel-team@lists.ubuntu.com; Fri, 27 Apr 2012 09:32:06 +0000 Received: by dakb39 with SMTP id b39so684280dak.21 for ; Fri, 27 Apr 2012 02:32:05 -0700 (PDT) Received: by 10.68.223.234 with SMTP id qx10mr22709348pbc.154.1335519125249; Fri, 27 Apr 2012 02:32:05 -0700 (PDT) Received: from localhost ([183.37.200.43]) by mx.google.com with ESMTPS id gl7sm3006961pbc.10.2012.04.27.02.32.03 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 27 Apr 2012 02:32:04 -0700 (PDT) From: ming.lei@canonical.com To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/6] UAS: Re-add workqueue items if submission fails. Date: Fri, 27 Apr 2012 17:31:43 +0800 Message-Id: <1335519112-8372-2-git-send-email-ming.lei@canonical.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1335519112-8372-1-git-send-email-ming.lei@canonical.com> References: <1335519112-8372-1-git-send-email-ming.lei@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com From: Sarah Sharp If the original submission (or allocation) of the URBs for a SCSI command fails, the UAS driver sticks the command structure in a workqueue and schedules uas_do_work() to run. That function removes the entire queue before walking across it and attempting to resubmit. Unfortunately, if the second submission fails, we will leak memory (because an allocated URB was not submitted) and possibly leave the SCSI command partially enqueued on some of the stream rings. Fix this by checking whether the second submission failed and re-queueing the command to the UAS workqueue and scheduling it. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1d10d5b..4bbaf6e 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -125,29 +125,38 @@ struct uas_cmd_info { /* I hate forward declarations, but I actually have a loop */ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo, gfp_t gfp); +static void uas_do_work(struct work_struct *work); +static DECLARE_WORK(uas_work, uas_do_work); static DEFINE_SPINLOCK(uas_work_lock); static LIST_HEAD(uas_work_list); static void uas_do_work(struct work_struct *work) { struct uas_cmd_info *cmdinfo; + struct uas_cmd_info *temp; struct list_head list; + int err; spin_lock_irq(&uas_work_lock); list_replace_init(&uas_work_list, &list); spin_unlock_irq(&uas_work_lock); - list_for_each_entry(cmdinfo, &list, list) { + list_for_each_entry_safe(cmdinfo, temp, &list, list) { struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + if (err) { + list_del(&cmdinfo->list); + spin_lock_irq(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock_irq(&uas_work_lock); + schedule_work(&uas_work); + } } } -static DECLARE_WORK(uas_work, uas_do_work); - static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer;