Merge of the trunk's r3400-3401:

- Full buffers must always be processed, otherwise bad things could happen

 - Make scst_get_full_buf and scst_put_full_buf consistent with the naming convention



git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/2.1.0.x@3415 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2011-04-26 00:20:26 +00:00
parent 6084197aa1
commit 8c8aadaa6d
4 changed files with 68 additions and 88 deletions

View File

@@ -3524,6 +3524,10 @@ void scst_copy_sg(struct scst_cmd *cmd, enum scst_sg_copy_dir copy_dir);
* instead of direct access. Returns the buffer length for success, 0 for EOD,
* negative error code otherwise.
*
* Never EVER use this function to process only "the first page" of the buffer.
* The first SG entry can be as low as few bytes long. Use scst_get_buf_full()
* instead for such cases.
*
* "Buf" argument returns the mapped buffer
*
* The "put" function unmaps the buffer.
@@ -3727,8 +3731,8 @@ static inline int scst_get_out_buf_count(struct scst_cmd *cmd)
return (cmd->out_sg_cnt == 0) ? 1 : cmd->out_sg_cnt;
}
int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf);
void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf);
int scst_get_buf_full(struct scst_cmd *cmd, uint8_t **buf);
void scst_put_buf_full(struct scst_cmd *cmd, uint8_t *buf);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) && !defined(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20))

View File

@@ -1266,7 +1266,7 @@ static void vdisk_exec_unmap(struct scst_cmd *cmd, struct scst_vdisk_thr *thr)
goto out;
}
length = scst_get_full_buf(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length == 0)
goto out_put;
@@ -1364,7 +1364,7 @@ static void vdisk_exec_unmap(struct scst_cmd *cmd, struct scst_vdisk_thr *thr)
}
out_put:
scst_put_full_buf(cmd, address);
scst_put_buf_full(cmd, address);
out:
TRACE_EXIT();
@@ -1393,11 +1393,11 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
goto out;
}
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
TRACE_DBG("length %d", length);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -1674,7 +1674,7 @@ static void vdisk_exec_inquiry(struct scst_cmd *cmd)
memcpy(address, buf, length);
out_put:
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (length < cmd->resp_data_len)
scst_set_resp_data_len(cmd, length);
@@ -1697,10 +1697,10 @@ static void vdisk_exec_request_sense(struct scst_cmd *cmd)
sl = scst_set_sense(b, sizeof(b), cmd->dev->d_sense,
SCST_LOAD_SENSE(scst_sense_no_sense));
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
TRACE_DBG("length %d", length);
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d)", length);
PRINT_ERROR("scst_get_buf_full() failed: %d)", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
goto out;
@@ -1710,7 +1710,7 @@ static void vdisk_exec_request_sense(struct scst_cmd *cmd)
memcpy(address, b, length);
scst_set_resp_data_len(cmd, length);
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
out:
TRACE_EXIT();
@@ -1896,10 +1896,10 @@ static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
if (!virt_dev->blockio)
dev_spec |= DPOFUA;
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -2008,7 +2008,7 @@ static void vdisk_exec_mode_sense(struct scst_cmd *cmd)
memcpy(address, buf, offset);
out_put:
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (offset < cmd->resp_data_len)
scst_set_resp_data_len(cmd, offset);
@@ -2081,10 +2081,10 @@ static void vdisk_exec_mode_select(struct scst_cmd *cmd)
virt_dev = cmd->dev->dh_priv;
mselect_6 = (MODE_SELECT == cmd->cdb[0]);
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -2159,7 +2159,7 @@ static void vdisk_exec_mode_select(struct scst_cmd *cmd)
}
out_put:
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
out:
TRACE_EXIT();
@@ -2227,10 +2227,10 @@ static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
buffer[6] = (blocksize >> (BYTE * 1)) & 0xFF;
buffer[7] = (blocksize >> (BYTE * 0)) & 0xFF;
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -2241,7 +2241,7 @@ static void vdisk_exec_read_capacity(struct scst_cmd *cmd)
memcpy(address, buffer, length);
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (length < cmd->resp_data_len)
scst_set_resp_data_len(cmd, length);
@@ -2320,10 +2320,10 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
#endif
}
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -2334,7 +2334,7 @@ static void vdisk_exec_read_capacity16(struct scst_cmd *cmd)
memcpy(address, buffer, length);
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (length < cmd->resp_data_len)
scst_set_resp_data_len(cmd, length);
@@ -2378,10 +2378,10 @@ static void vdisk_exec_read_toc(struct scst_cmd *cmd)
goto out;
}
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_buf_full() failed: %d", length);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_hardw_error));
}
@@ -2425,7 +2425,7 @@ static void vdisk_exec_read_toc(struct scst_cmd *cmd)
off = length;
memcpy(address, buffer, off);
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (off < cmd->resp_data_len)
scst_set_resp_data_len(cmd, off);

View File

@@ -2122,6 +2122,8 @@ void scst_set_resp_data_len(struct scst_cmd *cmd, int resp_data_len)
if (resp_data_len == cmd->bufflen)
goto out;
TRACE_DBG("cmd %p, resp_data_len %d", cmd, resp_data_len);
scst_adjust_sg(cmd, cmd->sg, &cmd->sg_cnt, resp_data_len);
cmd->resid_possible = 1;
@@ -3798,7 +3800,7 @@ static void scst_complete_request_sense(struct scst_cmd *req_cmd)
sBUG_ON(orig_cmd == NULL);
len = scst_get_buf_first(req_cmd, &buf);
len = scst_get_buf_full(req_cmd, &buf);
if (scsi_status_is_good(req_cmd->status) && (len > 0) &&
SCST_SENSE_VALID(buf) && (!SCST_NO_SENSE(buf))) {
@@ -3814,7 +3816,7 @@ static void scst_complete_request_sense(struct scst_cmd *req_cmd)
}
if (len > 0)
scst_put_buf(req_cmd, buf);
scst_put_buf_full(req_cmd, buf);
TRACE_MGMT_DBG("Adding orig cmd %p to head of active "
"cmd list", orig_cmd);
@@ -4858,7 +4860,7 @@ out:
EXPORT_SYMBOL_GPL(scst_copy_sg);
/**
* scst_get_full_buf - return linear buffer for command
* scst_get_buf_full - return linear buffer for command
* @cmd: scst command
* @buf: pointer on the resulting pointer
*
@@ -4866,7 +4868,7 @@ EXPORT_SYMBOL_GPL(scst_copy_sg);
* and copies the buffer there. Returns length of the buffer or negative
* error code otherwise.
*/
int scst_get_full_buf(struct scst_cmd *cmd, uint8_t **buf)
int scst_get_buf_full(struct scst_cmd *cmd, uint8_t **buf)
{
int res = 0;
@@ -4918,17 +4920,17 @@ out:
TRACE_EXIT_RES(res);
return res;
}
EXPORT_SYMBOL(scst_get_full_buf);
EXPORT_SYMBOL(scst_get_buf_full);
/**
* scst_put_full_buf - unmaps linear buffer for command
* scst_put_buf_full - unmaps linear buffer for command
* @cmd: scst command
* @buf: pointer on the buffer to unmap
*
* Reverse operation for scst_get_full_buf. If the buffer was vmalloced(),
* Reverse operation for scst_get_buf_full. If the buffer was vmalloced(),
* it vfree() the buffer.
*/
void scst_put_full_buf(struct scst_cmd *cmd, uint8_t *buf)
void scst_put_buf_full(struct scst_cmd *cmd, uint8_t *buf)
{
TRACE_ENTRY();
@@ -4963,7 +4965,7 @@ out:
TRACE_EXIT();
return;
}
EXPORT_SYMBOL(scst_put_full_buf);
EXPORT_SYMBOL(scst_put_buf_full);
static const int SCST_CDB_LENGTH[8] = { 6, 10, 10, 0, 16, 12, 0, 0 };
@@ -5703,7 +5705,7 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd,
int buffer_size, sector_size, sh;
uint8_t *buffer;
buffer_size = scst_get_buf_first(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
if (buffer_size < 0) {
PRINT_ERROR("%s: Unable to get the"
@@ -5715,7 +5717,7 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd,
sector_size =
((buffer[4] << 24) | (buffer[5] << 16) |
(buffer[6] << 8) | (buffer[7] << 0));
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
if (sector_size != 0)
sh = scst_calc_block_shift(sector_size);
else
@@ -5766,7 +5768,7 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
buffer_size = scst_get_buf_first(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
if (buffer_size < 0) {
PRINT_ERROR("%s: Unable to get the buffer (%d)",
@@ -5804,7 +5806,7 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
switch (opcode) {
case MODE_SENSE:
case MODE_SELECT:
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
break;
}

View File

@@ -1713,7 +1713,7 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
goto out_err;
}
buffer_size = scst_get_buf_first(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size == 0))
goto out_compl;
else if (unlikely(buffer_size < 0))
@@ -1733,25 +1733,9 @@ static int scst_report_luns_local(struct scst_cmd *cmd)
struct list_head *head = &cmd->sess->sess_tgt_dev_list[i];
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
if (!overflow) {
if (offs >= buffer_size) {
scst_put_buf(cmd, buffer);
buffer_size = scst_get_buf_next(cmd,
&buffer);
if (buffer_size > 0) {
memset(buffer, 0, buffer_size);
offs = 0;
} else {
overflow = 1;
goto inc_dev_cnt;
}
}
if ((buffer_size - offs) < 8) {
PRINT_ERROR("Buffer allocated for "
"REPORT LUNS command doesn't "
"allow to fit 8 byte entry "
"(buffer_size=%d)",
buffer_size);
goto out_put_hw_err;
overflow = 1;
goto inc_dev_cnt;
}
*(__force __be64 *)&buffer[offs]
= scst_pack_lun(tgt_dev->lun,
@@ -1762,23 +1746,15 @@ inc_dev_cnt:
dev_cnt++;
}
}
if (!overflow)
scst_put_buf(cmd, buffer);
/* Set the response header */
buffer_size = scst_get_buf_first(cmd, &buffer);
if (unlikely(buffer_size == 0))
goto out_compl;
else if (unlikely(buffer_size < 0))
goto out_hw_err;
dev_cnt *= 8;
buffer[0] = (dev_cnt >> 24) & 0xff;
buffer[1] = (dev_cnt >> 16) & 0xff;
buffer[2] = (dev_cnt >> 8) & 0xff;
buffer[3] = dev_cnt & 0xff;
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
dev_cnt += 8;
if (dev_cnt < cmd->resp_data_len)
@@ -1825,16 +1801,13 @@ out_done:
return res;
out_put_err:
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
out_err:
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_compl;
out_put_hw_err:
scst_put_buf(cmd, buffer);
out_hw_err:
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_hardw_error));
goto out_compl;
@@ -1865,7 +1838,7 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
TRACE(TRACE_SCSI, "%s: Returning stored sense", cmd->op_name);
buffer_size = scst_get_buf_first(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size == 0))
goto out_unlock_compl;
else if (unlikely(buffer_size < 0))
@@ -1909,7 +1882,7 @@ static int scst_request_sense_local(struct scst_cmd *cmd)
memcpy(buffer, tgt_dev->tgt_dev_sense, sl);
}
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
tgt_dev->tgt_dev_valid_sense_len = 0;
@@ -2143,7 +2116,7 @@ static int scst_persistent_reserve_in_local(struct scst_cmd *cmd)
goto out_done;
}
buffer_size = scst_get_full_buf(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
if (buffer_size < 0)
scst_set_busy(cmd);
@@ -2188,7 +2161,7 @@ out_complete:
out_unlock:
scst_pr_write_unlock(dev);
scst_put_full_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
out_done:
cmd->scst_cmd_done(cmd, SCST_CMD_STATE_DEFAULT, SCST_CONTEXT_SAME);
@@ -2262,7 +2235,7 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
goto out_done;
}
buffer_size = scst_get_full_buf(cmd, &buffer);
buffer_size = scst_get_buf_full(cmd, &buffer);
if (unlikely(buffer_size <= 0)) {
if (buffer_size < 0)
scst_set_busy(cmd);
@@ -2275,7 +2248,7 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
TRACE_PR("Scope must be SCOPE_LU for action %x", action);
scst_set_cmd_error(cmd,
SCST_LOAD_SENSE(scst_sense_invalid_field_in_cdb));
goto out_put_full_buf;
goto out_put_buf_full;
}
/* Check SPEC_I_PT (PR_REGISTER_AND_MOVE has another format) */
@@ -2284,7 +2257,7 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
TRACE_PR("SPEC_I_PT must be zero for action %x", action);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_cdb));
goto out_put_full_buf;
goto out_put_buf_full;
}
/* Check ALL_TG_PT (PR_REGISTER_AND_MOVE has another format) */
@@ -2293,7 +2266,7 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
TRACE_PR("ALL_TG_PT must be zero for action %x", action);
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
scst_sense_invalid_field_in_cdb));
goto out_put_full_buf;
goto out_put_buf_full;
}
scst_pr_write_lock(dev);
@@ -2348,8 +2321,8 @@ static int scst_persistent_reserve_out_local(struct scst_cmd *cmd)
out_unlock:
scst_pr_write_unlock(dev);
out_put_full_buf:
scst_put_full_buf(cmd, buffer);
out_put_buf_full:
scst_put_buf_full(cmd, buffer);
out_done:
if (SCST_EXEC_COMPLETED == res) {
@@ -3074,7 +3047,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
uint8_t *address;
bool err = false;
length = scst_get_buf_first(cmd, &address);
length = scst_get_buf_full(cmd, &address);
if (length < 0) {
PRINT_ERROR("%s", "Unable to get "
"MODE_SENSE buffer");
@@ -3086,7 +3059,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
address[2] |= 0x80; /* Write Protect*/
else if (length > 3 && cmd->cdb[0] == MODE_SENSE_10)
address[3] |= 0x80; /* Write Protect*/
scst_put_buf(cmd, address);
scst_put_buf_full(cmd, address);
if (err)
goto out;
@@ -3104,8 +3077,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
int buflen;
bool err = false;
/* ToDo: all pages ?? */
buflen = scst_get_buf_first(cmd, &buffer);
buflen = scst_get_buf_full(cmd, &buffer);
if (buflen > SCST_INQ_BYTE3 && !cmd->tgtt->fake_aca) {
#ifdef CONFIG_SCST_EXTRACHECKS
if (buffer[SCST_INQ_BYTE3] & SCST_INQ_NORMACA_BIT) {
@@ -3125,7 +3097,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
err = true;
}
if (buflen > 0)
scst_put_buf(cmd, buffer);
scst_put_buf_full(cmd, buffer);
if (err)
goto out;
@@ -3507,14 +3479,16 @@ static int scst_xmit_response(struct scst_cmd *cmd)
sg = cmd->sg;
if (sg != NULL) {
TRACE(TRACE_SND_BOT, "Xmitting data for cmd %p "
"(sg_cnt %d, sg %p, sg[0].page %p)",
cmd, cmd->tgt_sg_cnt, sg,
(void *)sg_page(&sg[0]));
"(sg_cnt %d, sg %p, sg[0].page %p, buf %p, "
"resp len %d)", cmd, cmd->tgt_sg_cnt,
sg, (void *)sg_page(&sg[0]), sg_virt(sg),
cmd->resp_data_len);
for (i = 0, j = 0; i < cmd->tgt_sg_cnt; ++i, ++j) {
if (unlikely(sg_is_chain(&sg[j]))) {
sg = sg_chain_ptr(&sg[j]);
j = 0;
}
TRACE(TRACE_SND_BOT, "sg %d", j);
PRINT_BUFF_FLAG(TRACE_SND_BOT,
"Xmitting sg", sg_virt(&sg[j]),
sg[j].length);