提交 d6891682 编写于 作者: J Jeff Skirvin 提交者: James Bottomley

[SCSI] isci: Fix tag leak in tasks and terminated requests.

Make sure terminated requests and completed task tags are freed.
Signed-off-by: NJeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: NDan Williams <dan.j.williams@intel.com>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 c2cb8a5f
...@@ -552,11 +552,27 @@ static void isci_request_cleanup_completed_loiterer( ...@@ -552,11 +552,27 @@ static void isci_request_cleanup_completed_loiterer(
if (isci_request != NULL) { if (isci_request != NULL) {
spin_lock_irqsave(&isci_host->scic_lock, flags); spin_lock_irqsave(&isci_host->scic_lock, flags);
isci_free_tag(isci_host, isci_request->io_tag);
isci_request_change_state(isci_request, unallocated);
list_del_init(&isci_request->dev_node); list_del_init(&isci_request->dev_node);
spin_unlock_irqrestore(&isci_host->scic_lock, flags); spin_unlock_irqrestore(&isci_host->scic_lock, flags);
} }
} }
static int isci_request_is_dealloc_managed(enum isci_request_status stat)
{
switch (stat) {
case aborted:
case aborting:
case terminating:
case completed:
case dead:
return true;
default:
return false;
}
}
/** /**
* isci_terminate_request_core() - This function will terminate the given * isci_terminate_request_core() - This function will terminate the given
* request, and wait for it to complete. This function must only be called * request, and wait for it to complete. This function must only be called
...@@ -574,7 +590,6 @@ static void isci_terminate_request_core(struct isci_host *ihost, ...@@ -574,7 +590,6 @@ static void isci_terminate_request_core(struct isci_host *ihost,
enum sci_status status = SCI_SUCCESS; enum sci_status status = SCI_SUCCESS;
bool was_terminated = false; bool was_terminated = false;
bool needs_cleanup_handling = false; bool needs_cleanup_handling = false;
enum isci_request_status request_status;
unsigned long flags; unsigned long flags;
unsigned long termination_completed = 1; unsigned long termination_completed = 1;
struct completion *io_request_completion; struct completion *io_request_completion;
...@@ -702,23 +717,11 @@ static void isci_terminate_request_core(struct isci_host *ihost, ...@@ -702,23 +717,11 @@ static void isci_terminate_request_core(struct isci_host *ihost,
* needs to be detached and freed here. * needs to be detached and freed here.
*/ */
spin_lock_irqsave(&isci_request->state_lock, flags); spin_lock_irqsave(&isci_request->state_lock, flags);
request_status = isci_request->status;
needs_cleanup_handling
if ((isci_request->ttype == io_task) /* TMFs are in their own thread */ = isci_request_is_dealloc_managed(
&& ((request_status == aborted) isci_request->status);
|| (request_status == aborting)
|| (request_status == terminating)
|| (request_status == completed)
|| (request_status == dead)
)
) {
/* The completion routine won't free a request in
* the aborted/aborting/etc. states, so we do
* it here.
*/
needs_cleanup_handling = true;
}
spin_unlock_irqrestore(&isci_request->state_lock, flags); spin_unlock_irqrestore(&isci_request->state_lock, flags);
} }
...@@ -1329,8 +1332,16 @@ isci_task_request_complete(struct isci_host *ihost, ...@@ -1329,8 +1332,16 @@ isci_task_request_complete(struct isci_host *ihost,
*/ */
set_bit(IREQ_TERMINATED, &ireq->flags); set_bit(IREQ_TERMINATED, &ireq->flags);
/* As soon as something is in the terminate path, deallocation is
* managed there. Note that the final non-managed state of a task
* request is "completed".
*/
if ((ireq->status == completed) ||
!isci_request_is_dealloc_managed(ireq->status)) {
isci_request_change_state(ireq, unallocated); isci_request_change_state(ireq, unallocated);
isci_free_tag(ihost, ireq->io_tag);
list_del_init(&ireq->dev_node); list_del_init(&ireq->dev_node);
}
/* The task management part completes last. */ /* The task management part completes last. */
complete(tmf_complete); complete(tmf_complete);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册