iscsi: Generate and verify DIF to metadata space in read or write I/O

Generate and insert DIF for write I/O by stream fashion in
spdk_iscsi_read_pdu().

Verify DIF for read I/O in spdk_iscsi_conn_write_pdu().

Verification can be done in spdk_iscsi_build_iovs(), but how many
writes to socket is not known beforehand, and same range may be
verified multiple times. So verify DIF before starting to write to
socket.

Change-Id: I860637758164b7d518c38fe92356562cbbe3d8f8
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/446406
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-03-07 12:49:49 +09:00 committed by Changpeng Liu
parent 466ca6d494
commit 136c3fb461
2 changed files with 40 additions and 3 deletions

View File

@ -1297,12 +1297,40 @@ spdk_iscsi_conn_flush_pdus(void *_conn)
return 1;
}
static int
spdk_iscsi_dif_verify(struct spdk_iscsi_pdu *pdu, struct spdk_dif_ctx *dif_ctx)
{
struct iovec iov;
struct spdk_dif_error err_blk = {};
uint32_t num_blocks;
int rc;
iov.iov_base = pdu->data;
iov.iov_len = pdu->data_buf_len;
num_blocks = pdu->data_buf_len / dif_ctx->block_size;
rc = spdk_dif_verify(&iov, 1, num_blocks, dif_ctx, &err_blk);
if (rc != 0) {
SPDK_ERRLOG("DIF error detected. type=%d, offset=%" PRIu32 "\n",
err_blk.err_type, err_blk.err_offset);
}
return rc;
}
void
spdk_iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
{
uint32_t crc32c;
int rc;
if (spdk_unlikely(spdk_iscsi_get_dif_ctx(conn, pdu, &pdu->dif_ctx))) {
rc = spdk_iscsi_dif_verify(pdu, &pdu->dif_ctx);
if (rc != 0) {
spdk_iscsi_conn_free_pdu(conn, pdu);
conn->state = ISCSI_CONN_STATE_EXITING;
return;
}
pdu->dif_insert_or_strip = true;
}

View File

@ -392,7 +392,7 @@ spdk_iscsi_conn_read_data_segment(struct spdk_iscsi_conn *conn,
{
struct spdk_dif_ctx dif_ctx;
struct iovec iovs[32];
int rc;
int rc, _rc;
if (spdk_likely(!spdk_iscsi_get_dif_ctx(conn, pdu, &dif_ctx))) {
return spdk_iscsi_conn_read_data(conn,
@ -405,11 +405,20 @@ spdk_iscsi_conn_read_data_segment(struct spdk_iscsi_conn *conn,
pdu->data_valid_bytes, segment_len, NULL,
&dif_ctx);
if (rc > 0) {
return spdk_iscsi_conn_readv_data(conn, iovs, rc);
rc = spdk_iscsi_conn_readv_data(conn, iovs, rc);
if (rc > 0) {
_rc = spdk_dif_generate_stream(pdu->data_buf, pdu->data_buf_len,
pdu->data_valid_bytes, rc,
&dif_ctx);
if (_rc != 0) {
SPDK_ERRLOG("DIF generate failed\n");
rc = _rc;
}
}
} else {
SPDK_ERRLOG("Setup iovs for interleaved metadata failed\n");
return rc;
}
return rc;
}
}