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

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3400 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Vladislav Bolkhovitin
2011-04-23 21:13:50 +00:00
parent 8cb2e02e62
commit 7078c0b26b
4 changed files with 49 additions and 69 deletions
+4
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_full_buf()
* instead for such cases.
*
* "Buf" argument returns the mapped buffer
*
* The "put" function unmaps the buffer.
+21 -21
View File
@@ -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_full_buf(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_full_buf() 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_full_buf(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_full_buf(cmd, &address);
TRACE_DBG("length %d", length);
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d)", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(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_full_buf(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(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_full_buf(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(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_full_buf(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(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_full_buf(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(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_full_buf(cmd, &address);
if (unlikely(length <= 0)) {
if (length < 0) {
PRINT_ERROR("scst_get_buf_first() failed: %d", length);
PRINT_ERROR("scst_get_full_buf() 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_full_buf(cmd, address);
if (off < cmd->resp_data_len)
scst_set_resp_data_len(cmd, off);
+8 -6
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_full_buf(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_full_buf(req_cmd, buf);
TRACE_MGMT_DBG("Adding orig cmd %p to head of active "
"cmd list", orig_cmd);
@@ -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_full_buf(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_full_buf(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_full_buf(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_full_buf(cmd, buffer);
break;
}
+16 -42
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_full_buf(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_full_buf(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_full_buf(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_full_buf(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_full_buf(cmd, buffer);
tgt_dev->tgt_dev_valid_sense_len = 0;
@@ -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_full_buf(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_full_buf(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_full_buf(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_full_buf(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);