Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] vmw_pvscsi: Fix pvscsi_abort() function.

This change ensures that pvscsi_abort() function returns SUCCESS
only when the command in question was actually completed, otherwise
returns FAILURE. The code before change, was causing a bug where
driver tries to complete a command to the mid-layer while the mid-layer
has already requested the driver to abort that command, in response
to which the driver has responded with SUCCESS causing mid-layer
to free the command struct.

Signed-off-by: Arvind Kumar <arvindkumar@vmware.com>
Tested-by: Ewan Milne <emilne@redhat.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Arvind Kumar and committed by
James Bottomley
a2713cce 4909cc2b

+50 -7
+48 -5
drivers/scsi/vmw_pvscsi.c
··· 1 1 /* 2 2 * Linux driver for VMware's para-virtualized SCSI HBA. 3 3 * 4 - * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved. 4 + * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved. 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify it 7 7 * under the terms of the GNU General Public License as published by the ··· 62 62 dma_addr_t dataPA; 63 63 dma_addr_t sensePA; 64 64 dma_addr_t sglPA; 65 + struct completion *abort_cmp; 65 66 }; 66 67 67 68 struct pvscsi_adapter { ··· 178 177 struct pvscsi_ctx *ctx) 179 178 { 180 179 ctx->cmd = NULL; 180 + ctx->abort_cmp = NULL; 181 181 list_add(&ctx->list, &adapter->cmd_pool); 182 182 } 183 183 ··· 498 496 { 499 497 struct pvscsi_ctx *ctx; 500 498 struct scsi_cmnd *cmd; 499 + struct completion *abort_cmp; 501 500 u32 btstat = e->hostStatus; 502 501 u32 sdstat = e->scsiStatus; 503 502 504 503 ctx = pvscsi_get_context(adapter, e->context); 505 504 cmd = ctx->cmd; 505 + abort_cmp = ctx->abort_cmp; 506 506 pvscsi_unmap_buffers(adapter, ctx); 507 507 pvscsi_release_context(adapter, ctx); 508 - cmd->result = 0; 508 + if (abort_cmp) { 509 + /* 510 + * The command was requested to be aborted. Just signal that 511 + * the request completed and swallow the actual cmd completion 512 + * here. The abort handler will post a completion for this 513 + * command indicating that it got successfully aborted. 514 + */ 515 + complete(abort_cmp); 516 + return; 517 + } 509 518 519 + cmd->result = 0; 510 520 if (sdstat != SAM_STAT_GOOD && 511 521 (btstat == BTSTAT_SUCCESS || 512 522 btstat == BTSTAT_LINKED_COMMAND_COMPLETED || ··· 740 726 struct pvscsi_adapter *adapter = shost_priv(cmd->device->host); 741 727 struct pvscsi_ctx *ctx; 742 728 unsigned long flags; 729 + int result = SUCCESS; 730 + DECLARE_COMPLETION_ONSTACK(abort_cmp); 743 731 744 732 scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n", 745 733 adapter->host->host_no, cmd); ··· 764 748 goto out; 765 749 } 766 750 767 - pvscsi_abort_cmd(adapter, ctx); 751 + /* 752 + * Mark that the command has been requested to be aborted and issue 753 + * the abort. 754 + */ 755 + ctx->abort_cmp = &abort_cmp; 768 756 769 - pvscsi_process_completion_ring(adapter); 757 + pvscsi_abort_cmd(adapter, ctx); 758 + spin_unlock_irqrestore(&adapter->hw_lock, flags); 759 + /* Wait for 2 secs for the completion. */ 760 + wait_for_completion_timeout(&abort_cmp, msecs_to_jiffies(2000)); 761 + spin_lock_irqsave(&adapter->hw_lock, flags); 762 + 763 + if (!completion_done(&abort_cmp)) { 764 + /* 765 + * Failed to abort the command, unmark the fact that it 766 + * was requested to be aborted. 767 + */ 768 + ctx->abort_cmp = NULL; 769 + result = FAILED; 770 + scmd_printk(KERN_DEBUG, cmd, 771 + "Failed to get completion for aborted cmd %p\n", 772 + cmd); 773 + goto out; 774 + } 775 + 776 + /* 777 + * Successfully aborted the command. 778 + */ 779 + cmd->result = (DID_ABORT << 16); 780 + cmd->scsi_done(cmd); 770 781 771 782 out: 772 783 spin_unlock_irqrestore(&adapter->hw_lock, flags); 773 - return SUCCESS; 784 + return result; 774 785 } 775 786 776 787 /*
+2 -2
drivers/scsi/vmw_pvscsi.h
··· 1 1 /* 2 2 * VMware PVSCSI header file 3 3 * 4 - * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved. 4 + * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved. 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify it 7 7 * under the terms of the GNU General Public License as published by the ··· 26 26 27 27 #include <linux/types.h> 28 28 29 - #define PVSCSI_DRIVER_VERSION_STRING "1.0.2.0-k" 29 + #define PVSCSI_DRIVER_VERSION_STRING "1.0.3.0-k" 30 30 31 31 #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 32 32