mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-20 15:02:18 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user