From 8c8aadaa6d6124d601b894dc4f60d83b7314a878 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Tue, 26 Apr 2011 00:20:26 +0000 Subject: [PATCH] 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 --- scst/include/scst.h | 8 +++- scst/src/dev_handlers/scst_vdisk.c | 46 +++++++++---------- scst/src/scst_lib.c | 28 +++++------ scst/src/scst_targ.c | 74 ++++++++++-------------------- 4 files changed, 68 insertions(+), 88 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 52f75af70..fee86250a 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_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)) diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index 3276610e6..7858214c7 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -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); diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 0c614f781..6c0ddae0e 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_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; } diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 6c28a1258..df25f2c20 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_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);