iscsi: Add the support for long text response.
This patch adds the support for long text response. Change-Id: I8ef146069c9b8d86eb6df4c9e60cc6a3b2ff1ad7 Signed-off-by: Ziye Yang <ziye.yang@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/4993 Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
0e47be4b41
commit
abb6823d5d
@ -158,6 +158,12 @@ struct spdk_iscsi_conn {
|
|||||||
struct spdk_iscsi_tgt_node *target;
|
struct spdk_iscsi_tgt_node *target;
|
||||||
struct spdk_scsi_dev *dev;
|
struct spdk_scsi_dev *dev;
|
||||||
|
|
||||||
|
/* To handle the case that SendTargets response is split into
|
||||||
|
* multiple PDUs due to very small MaxRecvDataSegmentLength.
|
||||||
|
*/
|
||||||
|
uint32_t send_tgt_completed_size;
|
||||||
|
struct iscsi_param *params_text;
|
||||||
|
|
||||||
/* for fast access */
|
/* for fast access */
|
||||||
int header_digest;
|
int header_digest;
|
||||||
int data_digest;
|
int data_digest;
|
||||||
|
@ -2360,6 +2360,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pdu->data_segment_len == 0 && params == NULL) {
|
||||||
|
params = conn->params_text;
|
||||||
|
conn->params_text = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
data = calloc(1, alloc_len);
|
data = calloc(1, alloc_len);
|
||||||
if (!data) {
|
if (!data) {
|
||||||
SPDK_ERRLOG("calloc() failed for data segment\n");
|
SPDK_ERRLOG("calloc() failed for data segment\n");
|
||||||
@ -2406,6 +2411,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
|
|||||||
data_len);
|
data_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->send_tgt_completed_size != 0) {
|
||||||
|
F_bit = 0;
|
||||||
|
C_bit = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (iscsi_param_eq_val(conn->sess->params, "SessionType", "Discovery")) {
|
if (iscsi_param_eq_val(conn->sess->params, "SessionType", "Discovery")) {
|
||||||
iscsi_param_free(params);
|
iscsi_param_free(params);
|
||||||
@ -2414,7 +2424,11 @@ iscsi_pdu_payload_op_text(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iscsi_param_free(params);
|
if (spdk_likely(conn->send_tgt_completed_size == 0)) {
|
||||||
|
iscsi_param_free(params);
|
||||||
|
} else {
|
||||||
|
conn->params_text = params;
|
||||||
|
}
|
||||||
SPDK_LOGDUMP(iscsi, "Negotiated Params", data, data_len);
|
SPDK_LOGDUMP(iscsi, "Negotiated Params", data, data_len);
|
||||||
|
|
||||||
/* response PDU */
|
/* response PDU */
|
||||||
|
@ -49,6 +49,11 @@
|
|||||||
#define MAX_TMPBUF 4096
|
#define MAX_TMPBUF 4096
|
||||||
#define MAX_MASKBUF 128
|
#define MAX_MASKBUF 128
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_TMP_NAME_BUF (11 /* TargetName= */ + MAX_TARGET_NAME + 1 /* null */)
|
||||||
|
#define MAX_TMP_ADDR_BUF (14 /* TargetAddress= */ + MAX_PORTAL_ADDR + 1 /* : */ + \
|
||||||
|
MAX_PORTAL_PORT + 1 /* , */ + 10 /* max length of int in Decimal */ + 1 /* null */)
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
iscsi_ipv6_netmask_allow_addr(const char *netmask, const char *addr)
|
iscsi_ipv6_netmask_allow_addr(const char *netmask, const char *addr)
|
||||||
{
|
{
|
||||||
@ -295,16 +300,42 @@ iscsi_tgt_node_allow_iscsi_name(struct spdk_iscsi_tgt_node *target, const char *
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
iscsi_copy_str(char *data, int *total, int alloc_len,
|
||||||
|
int *previous_completed_len, int expected_size, char *src)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
assert(*previous_completed_len >= 0);
|
||||||
|
|
||||||
|
if (alloc_len - *total < 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*previous_completed_len < expected_size) {
|
||||||
|
len = spdk_min(alloc_len - *total, expected_size - *previous_completed_len);
|
||||||
|
memcpy((char *)data + *total, src + *previous_completed_len, len);
|
||||||
|
*total += len;
|
||||||
|
*previous_completed_len = 0;
|
||||||
|
} else {
|
||||||
|
*previous_completed_len -= expected_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
|
iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
|
||||||
struct spdk_iscsi_tgt_node *target,
|
struct spdk_iscsi_tgt_node *target,
|
||||||
uint8_t *data, int alloc_len, int total)
|
uint8_t *data, int alloc_len, int total,
|
||||||
|
int *previous_completed_len, bool *no_buf_space)
|
||||||
{
|
{
|
||||||
char buf[MAX_TMPBUF];
|
char buf[MAX_TMPBUF];
|
||||||
struct spdk_iscsi_portal_grp *pg;
|
struct spdk_iscsi_portal_grp *pg;
|
||||||
struct spdk_iscsi_pg_map *pg_map;
|
struct spdk_iscsi_pg_map *pg_map;
|
||||||
struct spdk_iscsi_portal *p;
|
struct spdk_iscsi_portal *p;
|
||||||
char *host;
|
char *host;
|
||||||
|
char tmp_buf[MAX_TMP_ADDR_BUF];
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
TAILQ_FOREACH(pg_map, &target->pg_map_head, tailq) {
|
TAILQ_FOREACH(pg_map, &target->pg_map_head, tailq) {
|
||||||
@ -318,13 +349,6 @@ iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(p, &pg->head, per_pg_tailq) {
|
TAILQ_FOREACH(p, &pg->head, per_pg_tailq) {
|
||||||
if (alloc_len - total < 1) {
|
|
||||||
/* TODO: long text responses support */
|
|
||||||
SPDK_ERRLOG("SPDK doesn't support long text responses now, "
|
|
||||||
"you can use larger MaxRecvDataSegmentLength"
|
|
||||||
"value in initiator\n");
|
|
||||||
return alloc_len;
|
|
||||||
}
|
|
||||||
host = p->host;
|
host = p->host;
|
||||||
/* wildcard? */
|
/* wildcard? */
|
||||||
if (strcasecmp(host, "[::]") == 0 || strcasecmp(host, "0.0.0.0") == 0) {
|
if (strcasecmp(host, "[::]") == 0 || strcasecmp(host, "0.0.0.0") == 0) {
|
||||||
@ -341,9 +365,23 @@ iscsi_send_tgt_portals(struct spdk_iscsi_conn *conn,
|
|||||||
}
|
}
|
||||||
SPDK_DEBUGLOG(iscsi, "TargetAddress=%s:%s,%d\n",
|
SPDK_DEBUGLOG(iscsi, "TargetAddress=%s:%s,%d\n",
|
||||||
host, p->port, pg->tag);
|
host, p->port, pg->tag);
|
||||||
len = snprintf((char *)data + total, alloc_len - total,
|
|
||||||
"TargetAddress=%s:%s,%d", host, p->port, pg->tag);
|
memset(tmp_buf, 0, sizeof(tmp_buf));
|
||||||
total += len + 1;
|
/* Caculate the whole string size */
|
||||||
|
len = snprintf(NULL, 0, "TargetAddress=%s:%s,%d", host, p->port, pg->tag);
|
||||||
|
assert(len < MAX_TMPBUF);
|
||||||
|
|
||||||
|
/* string contents are not fully copied */
|
||||||
|
if (*previous_completed_len < len) {
|
||||||
|
/* Copy the string into the temporary buffer */
|
||||||
|
snprintf(tmp_buf, len + 1, "TargetAddress=%s:%s,%d", host, p->port, pg->tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
*no_buf_space = iscsi_copy_str(data, &total, alloc_len, previous_completed_len,
|
||||||
|
len + 1, tmp_buf);
|
||||||
|
if (*no_buf_space) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +396,9 @@ iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
|
|||||||
int total;
|
int total;
|
||||||
int len;
|
int len;
|
||||||
int rc;
|
int rc;
|
||||||
|
int previous_completed_size = conn->send_tgt_completed_size;
|
||||||
|
bool no_buf_space = false;
|
||||||
|
char tmp_buf[MAX_TMP_NAME_BUF];
|
||||||
|
|
||||||
if (conn == NULL) {
|
if (conn == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -384,17 +425,38 @@ iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = snprintf((char *)data + total, alloc_len - total, "TargetName=%s",
|
memset(tmp_buf, 0, sizeof(tmp_buf));
|
||||||
target->name);
|
/* Calculate the whole string size */
|
||||||
total += len + 1;
|
len = snprintf(NULL, 0, "TargetName=%s", target->name);
|
||||||
|
assert(len < MAX_TMPBUF);
|
||||||
|
|
||||||
total = iscsi_send_tgt_portals(conn, target, data, alloc_len, total);
|
/* String contents are not copyied */
|
||||||
if (alloc_len - total < 1) {
|
if (previous_completed_size < len) {
|
||||||
|
/* Copy the string into the temporary buffer */
|
||||||
|
snprintf(tmp_buf, len + 1, "TargetName=%s", target->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
no_buf_space = iscsi_copy_str(data, &total, alloc_len, &previous_completed_size,
|
||||||
|
len + 1, tmp_buf);
|
||||||
|
if (no_buf_space) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
total = iscsi_send_tgt_portals(conn, target, data, alloc_len, total,
|
||||||
|
&previous_completed_size, &no_buf_space);
|
||||||
|
if (no_buf_space) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&g_iscsi.mutex);
|
pthread_mutex_unlock(&g_iscsi.mutex);
|
||||||
|
|
||||||
|
/* Only set it when it is not succesufully completed */
|
||||||
|
if (no_buf_space) {
|
||||||
|
conn->send_tgt_completed_size += total;
|
||||||
|
} else {
|
||||||
|
conn->send_tgt_completed_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user