uas: Fix memleak of non-submitted urbs
Not all urbs we've allocated are necessarily also submitted, non-submitted urbs will not be free-ed by their completion handler. So we need to free them manually. There are 2 scenarios where this can happen: 1) We have failed to submit some urbs at abort / disconnect 2) When running over usb-2 we may have never tried to submit the data urbs when completing the scsi cmnd, because we never got a READ/WRITE_READY iu Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
616f0e6cab
commit
4c5481efb4
|
@ -249,6 +249,25 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller)
|
||||||
(ci->state & IS_IN_WORK_LIST) ? " work" : "");
|
(ci->state & IS_IN_WORK_LIST) ? " work" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd)
|
||||||
|
{
|
||||||
|
struct uas_cmd_info *cmdinfo;
|
||||||
|
|
||||||
|
if (!cmnd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmdinfo = (void *)&cmnd->SCp;
|
||||||
|
|
||||||
|
if (cmdinfo->state & SUBMIT_CMD_URB)
|
||||||
|
usb_free_urb(cmdinfo->cmd_urb);
|
||||||
|
|
||||||
|
/* data urbs may have never gotten their submit flag set */
|
||||||
|
if (!(cmdinfo->state & DATA_IN_URB_INFLIGHT))
|
||||||
|
usb_free_urb(cmdinfo->data_in_urb);
|
||||||
|
if (!(cmdinfo->state & DATA_OUT_URB_INFLIGHT))
|
||||||
|
usb_free_urb(cmdinfo->data_out_urb);
|
||||||
|
}
|
||||||
|
|
||||||
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
|
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
|
||||||
{
|
{
|
||||||
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
|
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
|
||||||
|
@ -263,6 +282,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
|
||||||
WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
|
WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
|
||||||
cmdinfo->state |= COMMAND_COMPLETED;
|
cmdinfo->state |= COMMAND_COMPLETED;
|
||||||
devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL;
|
devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL;
|
||||||
|
uas_free_unsubmitted_urbs(cmnd);
|
||||||
cmnd->scsi_done(cmnd);
|
cmnd->scsi_done(cmnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -738,6 +758,8 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
|
||||||
if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
|
if (cmdinfo->state & DATA_OUT_URB_INFLIGHT)
|
||||||
data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
|
data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
|
||||||
|
|
||||||
|
uas_free_unsubmitted_urbs(cmnd);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&devinfo->lock, flags);
|
spin_unlock_irqrestore(&devinfo->lock, flags);
|
||||||
|
|
||||||
if (data_in_urb) {
|
if (data_in_urb) {
|
||||||
|
|
Loading…
Reference in New Issue