Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2713cce authored by Arvind Kumar's avatar Arvind Kumar Committed by James Bottomley
Browse files

[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: default avatarArvind Kumar <arvindkumar@vmware.com>
Tested-by: default avatarEwan Milne <emilne@redhat.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 4909cc2b
Loading
Loading
Loading
Loading
+47 −4
Original line number Diff line number Diff line
/*
 * Linux driver for VMware's para-virtualized SCSI HBA.
 *
 * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
 * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
@@ -62,6 +62,7 @@ struct pvscsi_ctx {
	dma_addr_t		dataPA;
	dma_addr_t		sensePA;
	dma_addr_t		sglPA;
	struct completion	*abort_cmp;
};

struct pvscsi_adapter {
@@ -177,6 +178,7 @@ static void pvscsi_release_context(struct pvscsi_adapter *adapter,
				   struct pvscsi_ctx *ctx)
{
	ctx->cmd = NULL;
	ctx->abort_cmp = NULL;
	list_add(&ctx->list, &adapter->cmd_pool);
}

@@ -496,15 +498,27 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
{
	struct pvscsi_ctx *ctx;
	struct scsi_cmnd *cmd;
	struct completion *abort_cmp;
	u32 btstat = e->hostStatus;
	u32 sdstat = e->scsiStatus;

	ctx = pvscsi_get_context(adapter, e->context);
	cmd = ctx->cmd;
	abort_cmp = ctx->abort_cmp;
	pvscsi_unmap_buffers(adapter, ctx);
	pvscsi_release_context(adapter, ctx);
	cmd->result = 0;
	if (abort_cmp) {
		/*
		 * The command was requested to be aborted. Just signal that
		 * the request completed and swallow the actual cmd completion
		 * here. The abort handler will post a completion for this
		 * command indicating that it got successfully aborted.
		 */
		complete(abort_cmp);
		return;
	}

	cmd->result = 0;
	if (sdstat != SAM_STAT_GOOD &&
	    (btstat == BTSTAT_SUCCESS ||
	     btstat == BTSTAT_LINKED_COMMAND_COMPLETED ||
@@ -726,6 +740,8 @@ static int pvscsi_abort(struct scsi_cmnd *cmd)
	struct pvscsi_adapter *adapter = shost_priv(cmd->device->host);
	struct pvscsi_ctx *ctx;
	unsigned long flags;
	int result = SUCCESS;
	DECLARE_COMPLETION_ONSTACK(abort_cmp);

	scmd_printk(KERN_DEBUG, cmd, "task abort on host %u, %p\n",
		    adapter->host->host_no, cmd);
@@ -748,13 +764,40 @@ static int pvscsi_abort(struct scsi_cmnd *cmd)
		goto out;
	}

	/*
	 * Mark that the command has been requested to be aborted and issue
	 * the abort.
	 */
	ctx->abort_cmp = &abort_cmp;

	pvscsi_abort_cmd(adapter, ctx);
	spin_unlock_irqrestore(&adapter->hw_lock, flags);
	/* Wait for 2 secs for the completion. */
	wait_for_completion_timeout(&abort_cmp, msecs_to_jiffies(2000));
	spin_lock_irqsave(&adapter->hw_lock, flags);

	pvscsi_process_completion_ring(adapter);
	if (!completion_done(&abort_cmp)) {
		/*
		 * Failed to abort the command, unmark the fact that it
		 * was requested to be aborted.
		 */
		ctx->abort_cmp = NULL;
		result = FAILED;
		scmd_printk(KERN_DEBUG, cmd,
			    "Failed to get completion for aborted cmd %p\n",
			    cmd);
		goto out;
	}

	/*
	 * Successfully aborted the command.
	 */
	cmd->result = (DID_ABORT << 16);
	cmd->scsi_done(cmd);

out:
	spin_unlock_irqrestore(&adapter->hw_lock, flags);
	return SUCCESS;
	return result;
}

/*
+2 −2
Original line number Diff line number Diff line
/*
 * VMware PVSCSI header file
 *
 * Copyright (C) 2008-2009, VMware, Inc. All Rights Reserved.
 * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
@@ -26,7 +26,7 @@

#include <linux/types.h>

#define PVSCSI_DRIVER_VERSION_STRING   "1.0.2.0-k"
#define PVSCSI_DRIVER_VERSION_STRING   "1.0.3.0-k"

#define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128