Commit b90f90d2 authored by Salyzyn, Mark's avatar Salyzyn, Mark Committed by James Bottomley

[SCSI] aacraid: add SCSI SYNCHONIZE_CACHE range checking

Customer running an application that issues SYNCHRONIZE_CACHE calls
directly noticed the broad stroke of the current implementation in the
aacraid driver resulting in multiple applications feeding I/O to the
storage causing the issuing application to stall for long periods of
time. By only waiting for the current WRITE commands, rather than all
commands, to complete; and those that are in range of the
SYNCHRONIZE_CACHE call that would associate more tightly with the
issuing application before telling the Firmware to flush it's dirty
cache, we managed to reduce the stalling. The Firmware itself still
flushes all the dirty cache associated with the array ignoring the
range, it just does so in a more timely manner.
Signed-off-by: default avatarMark Salyzyn <aacraid@adaptec.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 80b1c7bd
...@@ -1688,23 +1688,23 @@ static void synchronize_callback(void *context, struct fib *fibptr) ...@@ -1688,23 +1688,23 @@ static void synchronize_callback(void *context, struct fib *fibptr)
if (!aac_valid_context(cmd, fibptr)) if (!aac_valid_context(cmd, fibptr))
return; return;
dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n",
smp_processor_id(), jiffies)); smp_processor_id(), jiffies));
BUG_ON(fibptr == NULL); BUG_ON(fibptr == NULL);
synchronizereply = fib_data(fibptr); synchronizereply = fib_data(fibptr);
if (le32_to_cpu(synchronizereply->status) == CT_OK) if (le32_to_cpu(synchronizereply->status) == CT_OK)
cmd->result = DID_OK << 16 | cmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else { else {
struct scsi_device *sdev = cmd->device; struct scsi_device *sdev = cmd->device;
struct aac_dev *dev = fibptr->dev; struct aac_dev *dev = fibptr->dev;
u32 cid = sdev_id(sdev); u32 cid = sdev_id(sdev);
printk(KERN_WARNING printk(KERN_WARNING
"synchronize_callback: synchronize failed, status = %d\n", "synchronize_callback: synchronize failed, status = %d\n",
le32_to_cpu(synchronizereply->status)); le32_to_cpu(synchronizereply->status));
cmd->result = DID_OK << 16 | cmd->result = DID_OK << 16 |
COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *)&dev->fsa_dev[cid].sense_data, set_sense((u8 *)&dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR, HARDWARE_ERROR,
...@@ -1712,7 +1712,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) ...@@ -1712,7 +1712,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0, ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
0, 0); 0, 0);
memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data, memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
min(sizeof(dev->fsa_dev[cid].sense_data), min(sizeof(dev->fsa_dev[cid].sense_data),
sizeof(cmd->sense_buffer))); sizeof(cmd->sense_buffer)));
} }
...@@ -1730,6 +1730,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) ...@@ -1730,6 +1730,9 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
struct scsi_device *sdev = scsicmd->device; struct scsi_device *sdev = scsicmd->device;
int active = 0; int active = 0;
struct aac_dev *aac; struct aac_dev *aac;
u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
(scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
unsigned long flags; unsigned long flags;
/* /*
...@@ -1738,7 +1741,51 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) ...@@ -1738,7 +1741,51 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
*/ */
spin_lock_irqsave(&sdev->list_lock, flags); spin_lock_irqsave(&sdev->list_lock, flags);
list_for_each_entry(cmd, &sdev->cmd_list, list) list_for_each_entry(cmd, &sdev->cmd_list, list)
if (cmd != scsicmd && cmd->SCp.phase == AAC_OWNER_FIRMWARE) { if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
u64 cmnd_lba;
u32 cmnd_count;
if (cmd->cmnd[0] == WRITE_6) {
cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
(cmd->cmnd[2] << 8) |
cmd->cmnd[3];
cmnd_count = cmd->cmnd[4];
if (cmnd_count == 0)
cmnd_count = 256;
} else if (cmd->cmnd[0] == WRITE_16) {
cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
((u64)cmd->cmnd[3] << 48) |
((u64)cmd->cmnd[4] << 40) |
((u64)cmd->cmnd[5] << 32) |
((u64)cmd->cmnd[6] << 24) |
(cmd->cmnd[7] << 16) |
(cmd->cmnd[8] << 8) |
cmd->cmnd[9];
cmnd_count = (cmd->cmnd[10] << 24) |
(cmd->cmnd[11] << 16) |
(cmd->cmnd[12] << 8) |
cmd->cmnd[13];
} else if (cmd->cmnd[0] == WRITE_12) {
cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
(cmd->cmnd[3] << 16) |
(cmd->cmnd[4] << 8) |
cmd->cmnd[5];
cmnd_count = (cmd->cmnd[6] << 24) |
(cmd->cmnd[7] << 16) |
(cmd->cmnd[8] << 8) |
cmd->cmnd[9];
} else if (cmd->cmnd[0] == WRITE_10) {
cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
(cmd->cmnd[3] << 16) |
(cmd->cmnd[4] << 8) |
cmd->cmnd[5];
cmnd_count = (cmd->cmnd[7] << 8) |
cmd->cmnd[8];
} else
continue;
if (((cmnd_lba + cmnd_count) < lba) ||
(count && ((lba + count) < cmnd_lba)))
continue;
++active; ++active;
break; break;
} }
...@@ -1767,7 +1814,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) ...@@ -1767,7 +1814,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
synchronizecmd->count = synchronizecmd->count =
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
/* /*
...@@ -1789,7 +1836,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) ...@@ -1789,7 +1836,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
return 0; return 0;
} }
printk(KERN_WARNING printk(KERN_WARNING
"aac_synchronize: aac_fib_send failed with status: %d.\n", status); "aac_synchronize: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext); aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext); aac_fib_free(cmd_fibcontext);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment