iscsi-target: Enable MaxXmitDataSegmentLength operation in login path

This patch activates MaxXmitDataSegmentLength usage that performs the
following sequence of events:

- Once the incoming initiator's MAXRECVDATASEGMENTLENGTH key is detected
  within iscsi_check_acceptor_state(), save the requested MRDSL into
  conn->conn_ops->MaxRecvDataSegmentLength

- Next change the outgoing target's MaxRecvDataSegmenthLength key=value
  based upon the local TPG's MaxXmitDataSegmentLength attribute value.

- Change iscsi_set_connection_parameters() to skip the assignment of
  conn->conn_ops->MaxRecvDataSegmentLength, now setup within
  iscsi_check_acceptor_state()

Also update iscsi_decode_text_input() -> iscsi_check_acceptor_state()
code-path to accept struct iscsi_conn *.

Cc: Mike Christie <michaelc@cs.wisc.edu>
Cc: Andy Grover <agrover@redhat.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Roland Dreier <roland@purestorage.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
Nicholas Bellinger 2012-09-29 21:49:59 -07:00
parent e004cb2592
commit 9977bb18c9
3 changed files with 44 additions and 12 deletions

View File

@ -550,7 +550,7 @@ static int iscsi_target_handle_csg_zero(
SENDER_INITIATOR|SENDER_RECEIVER, SENDER_INITIATOR|SENDER_RECEIVER,
login->req_buf, login->req_buf,
payload_length, payload_length,
conn->param_list); conn);
if (ret < 0) if (ret < 0)
return -1; return -1;
@ -627,7 +627,7 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
SENDER_INITIATOR|SENDER_RECEIVER, SENDER_INITIATOR|SENDER_RECEIVER,
login->req_buf, login->req_buf,
payload_length, payload_length,
conn->param_list); conn);
if (ret < 0) if (ret < 0)
return -1; return -1;

View File

@ -1065,7 +1065,8 @@ out:
return proposer_values; return proposer_values;
} }
static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value) static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value,
struct iscsi_conn *conn)
{ {
u8 acceptor_boolean_value = 0, proposer_boolean_value = 0; u8 acceptor_boolean_value = 0, proposer_boolean_value = 0;
char *negoitated_value = NULL; char *negoitated_value = NULL;
@ -1140,8 +1141,35 @@ static int iscsi_check_acceptor_state(struct iscsi_param *param, char *value)
return -1; return -1;
} }
if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
SET_PSTATE_REPLY_OPTIONAL(param); struct iscsi_param *param_mxdsl;
unsigned long long tmp;
int rc;
rc = strict_strtoull(param->value, 0, &tmp);
if (rc < 0)
return -1;
conn->conn_ops->MaxRecvDataSegmentLength = tmp;
pr_debug("Saving op->MaxRecvDataSegmentLength from"
" original initiator received value: %u\n",
conn->conn_ops->MaxRecvDataSegmentLength);
param_mxdsl = iscsi_find_param_from_key(
MAXXMITDATASEGMENTLENGTH,
conn->param_list);
if (!param_mxdsl)
return -1;
rc = iscsi_update_param_value(param,
param_mxdsl->value);
if (rc < 0)
return -1;
pr_debug("Updated %s to target MXDSL value: %s\n",
param->name, param->value);
}
} else if (IS_TYPE_NUMBER_RANGE(param)) { } else if (IS_TYPE_NUMBER_RANGE(param)) {
negoitated_value = iscsi_get_value_from_number_range( negoitated_value = iscsi_get_value_from_number_range(
param, value); param, value);
@ -1535,8 +1563,9 @@ int iscsi_decode_text_input(
u8 sender, u8 sender,
char *textbuf, char *textbuf,
u32 length, u32 length,
struct iscsi_param_list *param_list) struct iscsi_conn *conn)
{ {
struct iscsi_param_list *param_list = conn->param_list;
char *tmpbuf, *start = NULL, *end = NULL; char *tmpbuf, *start = NULL, *end = NULL;
tmpbuf = kzalloc(length + 1, GFP_KERNEL); tmpbuf = kzalloc(length + 1, GFP_KERNEL);
@ -1594,7 +1623,7 @@ int iscsi_decode_text_input(
} }
SET_PSTATE_RESPONSE_GOT(param); SET_PSTATE_RESPONSE_GOT(param);
} else { } else {
if (iscsi_check_acceptor_state(param, value) < 0) { if (iscsi_check_acceptor_state(param, value, conn) < 0) {
kfree(tmpbuf); kfree(tmpbuf);
return -1; return -1;
} }
@ -1755,10 +1784,13 @@ void iscsi_set_connection_parameters(
pr_debug("DataDigest: %s\n", pr_debug("DataDigest: %s\n",
param->value); param->value);
} else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) { } else if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH)) {
ops->MaxRecvDataSegmentLength = /*
simple_strtoul(param->value, &tmpptr, 0); * At this point iscsi_check_acceptor_state() will have
pr_debug("MaxRecvDataSegmentLength: %s\n", * set ops->MaxRecvDataSegmentLength from the original
param->value); * initiator provided value.
*/
pr_debug("MaxRecvDataSegmentLength: %u\n",
ops->MaxRecvDataSegmentLength);
} else if (!strcmp(param->name, OFMARKER)) { } else if (!strcmp(param->name, OFMARKER)) {
ops->OFMarker = !strcmp(param->value, YES); ops->OFMarker = !strcmp(param->value, YES);
pr_debug("OFMarker: %s\n", pr_debug("OFMarker: %s\n",

View File

@ -36,7 +36,7 @@ extern void iscsi_release_param_list(struct iscsi_param_list *);
extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_list *); extern struct iscsi_param *iscsi_find_param_from_key(char *, struct iscsi_param_list *);
extern int iscsi_extract_key_value(char *, char **, char **); extern int iscsi_extract_key_value(char *, char **, char **);
extern int iscsi_update_param_value(struct iscsi_param *, char *); extern int iscsi_update_param_value(struct iscsi_param *, char *);
extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_param_list *); extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *);
extern int iscsi_encode_text_output(u8, u8, char *, u32 *, extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
struct iscsi_param_list *); struct iscsi_param_list *);
extern int iscsi_check_negotiated_keys(struct iscsi_param_list *); extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);