diff --git a/scst/include/scst.h b/scst/include/scst.h index 52f75af70..1b1504a01 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -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. diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 1addabd77..4b35741a4 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -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); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 0c614f781..fff48555e 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -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; } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 6c28a1258..c24e09004 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -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);