Files
scst/iscsi-scst/kernel/param.c
Vladislav Bolkhovitin bc7c69bfc4 - Fixed a major IET-derived iSCSI RFC violation: sessions and connections were not working
- A lot of cleanups and minor fixes, mostly IET-derived



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@685 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2009-03-03 18:13:23 +00:00

264 lines
8.1 KiB
C

/*
* Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org>
* Copyright (C) 2007 - 2008 Vladislav Bolkhovitin
* Copyright (C) 2007 - 2008 CMS Distribution Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "iscsi.h"
#include "digest.h"
#define CHECK_PARAM(info, iparam, word, min, max) \
do { \
if (!(info)->partial || ((info)->partial & 1 << key_##word)) \
if ((iparam)[key_##word] < (min) || \
(iparam)[key_##word] > (max)) { \
PRINT_ERROR("%s: %u is out of range (%u %u)", \
#word, (iparam)[key_##word], (min), (max)); \
if ((iparam)[key_##word] < (min)) \
(iparam)[key_##word] = (min); \
else \
(iparam)[key_##word] = (max); \
} \
} while (0)
#define SET_PARAM(param, info, iparam, word) \
({ \
int changed = 0; \
if (!(info)->partial || ((info)->partial & 1 << key_##word)) { \
if ((param)->word != (iparam)[key_##word]) \
changed = 1; \
(param)->word = (iparam)[key_##word]; \
} \
changed; \
})
#define GET_PARAM(param, info, iparam, word) \
do { \
(iparam)[key_##word] = (param)->word; \
} while (0)
static const char *get_bool_name(int val)
{
if (val)
return "Yes";
else
return "No";
}
static const char *get_digest_name(int val)
{
if (val == DIGEST_NONE)
return "None";
else if (val == DIGEST_CRC32C)
return "CRC32C";
else
return "Unknown";
}
static void log_params(struct iscsi_sess_param *param)
{
PRINT_INFO("Negotiated parameters: InitialR2T %s, ImmediateData %s, "
"MaxConnections %d, MaxRecvDataSegmentLength %d, "
"MaxXmitDataSegmentLength %d, ",
get_bool_name(param->initial_r2t),
get_bool_name(param->immediate_data), param->max_connections,
param->max_recv_data_length, param->max_xmit_data_length);
PRINT_INFO(" MaxBurstLength %d, FirstBurstLength %d, "
"DefaultTime2Wait %d, DefaultTime2Retain %d, ",
param->max_burst_length, param->first_burst_length,
param->default_wait_time, param->default_retain_time);
PRINT_INFO(" MaxOutstandingR2T %d, DataPDUInOrder %s, "
"DataSequenceInOrder %s, ErrorRecoveryLevel %d, ",
param->max_outstanding_r2t,
get_bool_name(param->data_pdu_inorder),
get_bool_name(param->data_sequence_inorder),
param->error_recovery_level);
PRINT_INFO(" HeaderDigest %s, DataDigest %s, OFMarker %s, "
"IFMarker %s, OFMarkInt %d, IFMarkInt %d",
get_digest_name(param->header_digest),
get_digest_name(param->data_digest),
get_bool_name(param->ofmarker),
get_bool_name(param->ifmarker),
param->ofmarkint, param->ifmarkint);
}
/* target_mutex supposed to be locked */
static void sess_param_check(struct iscsi_kern_param_info *info)
{
int32_t *iparam = info->session_param;
CHECK_PARAM(info, iparam, max_connections, 1, 1);
CHECK_PARAM(info, iparam, max_recv_data_length, 512,
(int32_t) (ISCSI_CONN_IOV_MAX * PAGE_SIZE));
CHECK_PARAM(info, iparam, max_xmit_data_length, 512,
(int32_t) (ISCSI_CONN_IOV_MAX * PAGE_SIZE));
CHECK_PARAM(info, iparam, error_recovery_level, 0, 0);
CHECK_PARAM(info, iparam, data_pdu_inorder, 0, 1);
CHECK_PARAM(info, iparam, data_sequence_inorder, 0, 1);
digest_alg_available(&iparam[key_header_digest]);
digest_alg_available(&iparam[key_data_digest]);
CHECK_PARAM(info, iparam, ofmarker, 0, 0);
CHECK_PARAM(info, iparam, ifmarker, 0, 0);
}
/* target_mutex supposed to be locked */
static void sess_param_set(struct iscsi_sess_param *param,
struct iscsi_kern_param_info *info)
{
int32_t *iparam = info->session_param;
SET_PARAM(param, info, iparam, initial_r2t);
SET_PARAM(param, info, iparam, immediate_data);
SET_PARAM(param, info, iparam, max_connections);
SET_PARAM(param, info, iparam, max_recv_data_length);
SET_PARAM(param, info, iparam, max_xmit_data_length);
SET_PARAM(param, info, iparam, max_burst_length);
SET_PARAM(param, info, iparam, first_burst_length);
SET_PARAM(param, info, iparam, default_wait_time);
SET_PARAM(param, info, iparam, default_retain_time);
SET_PARAM(param, info, iparam, max_outstanding_r2t);
SET_PARAM(param, info, iparam, data_pdu_inorder);
SET_PARAM(param, info, iparam, data_sequence_inorder);
SET_PARAM(param, info, iparam, error_recovery_level);
SET_PARAM(param, info, iparam, header_digest);
SET_PARAM(param, info, iparam, data_digest);
SET_PARAM(param, info, iparam, ofmarker);
SET_PARAM(param, info, iparam, ifmarker);
SET_PARAM(param, info, iparam, ofmarkint);
SET_PARAM(param, info, iparam, ifmarkint);
}
static void sess_param_get(struct iscsi_sess_param *param,
struct iscsi_kern_param_info *info)
{
int32_t *iparam = info->session_param;
GET_PARAM(param, info, iparam, initial_r2t);
GET_PARAM(param, info, iparam, immediate_data);
GET_PARAM(param, info, iparam, max_connections);
GET_PARAM(param, info, iparam, max_recv_data_length);
GET_PARAM(param, info, iparam, max_xmit_data_length);
GET_PARAM(param, info, iparam, max_burst_length);
GET_PARAM(param, info, iparam, first_burst_length);
GET_PARAM(param, info, iparam, default_wait_time);
GET_PARAM(param, info, iparam, default_retain_time);
GET_PARAM(param, info, iparam, max_outstanding_r2t);
GET_PARAM(param, info, iparam, data_pdu_inorder);
GET_PARAM(param, info, iparam, data_sequence_inorder);
GET_PARAM(param, info, iparam, error_recovery_level);
GET_PARAM(param, info, iparam, header_digest);
GET_PARAM(param, info, iparam, data_digest);
GET_PARAM(param, info, iparam, ofmarker);
GET_PARAM(param, info, iparam, ifmarker);
GET_PARAM(param, info, iparam, ofmarkint);
GET_PARAM(param, info, iparam, ifmarkint);
}
/* target_mutex supposed to be locked */
static void trgt_param_check(struct iscsi_kern_param_info *info)
{
int32_t *iparam = info->target_param;
CHECK_PARAM(info, iparam, queued_cmnds, MIN_NR_QUEUED_CMNDS,
MAX_NR_QUEUED_CMNDS);
}
/* target_mutex supposed to be locked */
static void trgt_param_set(struct iscsi_target *target,
struct iscsi_kern_param_info *info)
{
struct iscsi_trgt_param *param = &target->trgt_param;
int32_t *iparam = info->target_param;
SET_PARAM(param, info, iparam, queued_cmnds);
}
/* target_mutex supposed to be locked */
static void trgt_param_get(struct iscsi_trgt_param *param,
struct iscsi_kern_param_info *info)
{
int32_t *iparam = info->target_param;
GET_PARAM(param, info, iparam, queued_cmnds);
}
/* target_mutex supposed to be locked */
static int trgt_param(struct iscsi_target *target,
struct iscsi_kern_param_info *info, int set)
{
if (set) {
struct iscsi_trgt_param *prm;
trgt_param_check(info);
trgt_param_set(target, info);
prm = &target->trgt_param;
PRINT_INFO("Target parameter changed: QueuedCommands %d",
prm->queued_cmnds);
} else
trgt_param_get(&target->trgt_param, info);
return 0;
}
/* target_mutex supposed to be locked */
static int sess_param(struct iscsi_target *target,
struct iscsi_kern_param_info *info, int set)
{
struct iscsi_session *session = NULL;
struct iscsi_sess_param *param;
int err = -ENOENT;
if (set)
sess_param_check(info);
if (info->sid) {
session = session_lookup(target, info->sid);
if (!session)
goto out;
if (set && !list_empty(&session->conn_list)) {
err = -EBUSY;
goto out;
}
param = &session->sess_param;
} else
param = &target->trgt_sess_param;
if (set) {
sess_param_set(param, info);
if (session != NULL)
log_params(param);
} else
sess_param_get(param, info);
err = 0;
out:
return err;
}
/* target_mutex supposed to be locked */
int iscsi_param_set(struct iscsi_target *target,
struct iscsi_kern_param_info *info, int set)
{
int err;
if (info->param_type == key_session)
err = sess_param(target, info, set);
else if (info->param_type == key_target)
err = trgt_param(target, info, set);
else
err = -EINVAL;
return err;
}