diff options
Diffstat (limited to 'usr')
-rw-r--r-- | usr/Makefile | 6 | ||||
-rw-r--r-- | usr/config.h | 3 | ||||
-rw-r--r-- | usr/idbm.c | 2 | ||||
-rw-r--r-- | usr/idbm.h | 2 | ||||
-rw-r--r-- | usr/initiator.c | 27 | ||||
-rw-r--r-- | usr/initiator.h | 18 | ||||
-rw-r--r-- | usr/iscsi_sysfs.c | 172 | ||||
-rw-r--r-- | usr/iscsi_sysfs.h | 23 | ||||
-rw-r--r-- | usr/iscsiadm.c | 201 | ||||
-rw-r--r-- | usr/iscsid.c | 3 | ||||
-rw-r--r-- | usr/mgmt_ipc.c | 26 | ||||
-rw-r--r-- | usr/mgmt_ipc.h | 23 | ||||
-rw-r--r-- | usr/netlink.c | 3 | ||||
-rw-r--r-- | usr/transport.c | 17 | ||||
-rw-r--r-- | usr/transport.h | 16 | ||||
-rw-r--r-- | usr/types.h | 6 | ||||
-rw-r--r-- | usr/util.c | 1 |
17 files changed, 462 insertions, 87 deletions
diff --git a/usr/Makefile b/usr/Makefile index 714242f..09c9c6a 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -12,12 +12,12 @@ KSUBLEVEL=$(shell cat $(KSRC)/Makefile | awk -F= '/^SUBLEVEL =/ {print $$2}' | \ ifeq ($(OSNAME),Linux) ifeq ($(KSUBLEVEL),11) - IPC_CFLAGS=-DNETLINK_ISCSI=12 + IPC_CFLAGS=-DNETLINK_ISCSI=12 -D_GNU_SOURCE else ifeq ($(KSUBLEVEL),12) - IPC_CFLAGS=-DNETLINK_ISCSI=12 + IPC_CFLAGS=-DNETLINK_ISCSI=12 -D_GNU_SOURCE else - IPC_CFLAGS=-DNETLINK_ISCSI=8 + IPC_CFLAGS=-DNETLINK_ISCSI=8 -D_GNU_SOURCE endif endif IPC_OBJ=netlink.o diff --git a/usr/config.h b/usr/config.h index 7d00238..b938e62 100644 --- a/usr/config.h +++ b/usr/config.h @@ -109,6 +109,7 @@ struct iscsi_tcp_config { struct iscsi_conn_operational_config { int MaxRecvDataSegmentLength; + int MaxXmitDataSegmentLength; int HeaderDigest; int DataDigest; int IFMarker; @@ -120,6 +121,8 @@ struct iscsi_conn_operational_config { * both by TargetName and Subnet. */ struct iscsi_session_operational_config { + int DataPDUInOrder; + int DataSequenceInOrder; int protocol; int InitialR2T; int ImmediateData; @@ -2,6 +2,8 @@ * iSCSI Discovery Database Library * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -2,6 +2,8 @@ * iSCSI Discovery Database Library * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@@googlegroups.com * * This program is free software; you can redistribute it and/or modify diff --git a/usr/initiator.c b/usr/initiator.c index bf6f468..c4ee7f6 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -2,6 +2,8 @@ * iSCSI Session Management and Slow-path Control * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -1643,6 +1645,31 @@ static int match_session(void *data, char *targetname, int tpgt, char *address, } iscsi_session_t* +session_find_by_sid(int sid) +{ + iscsi_provider_t *p; + iscsi_session_t *session; + struct qelem *pitem, *sitem; + + pitem = providers.q_forw; + while (pitem != &providers) { + p = (iscsi_provider_t *)pitem; + + sitem = p->sessions.q_forw; + while (sitem != &p->sessions) { + session = (iscsi_session_t *)sitem; + + if (session->id == sid) + return session; + sitem = sitem->q_forw; + } + pitem = pitem->q_forw; + } + + return NULL; +} + +iscsi_session_t* session_find_by_rec(node_rec_t *rec) { iscsi_provider_t *p; diff --git a/usr/initiator.h b/usr/initiator.h index a4fb435..1c192c4 100644 --- a/usr/initiator.h +++ b/usr/initiator.h @@ -64,23 +64,6 @@ enum iscsi_login_status { LOGIN_REDIRECT = 9, }; -typedef enum iscsi_conn_state_e { - STATE_FREE = 0, - STATE_XPT_WAIT = 1, - STATE_IN_LOGIN = 2, - STATE_LOGGED_IN = 3, - STATE_IN_LOGOUT = 4, - STATE_LOGOUT_REQUESTED = 5, - STATE_CLEANUP_WAIT = 6, -} iscsi_conn_state_e; - -typedef enum iscsi_session_r_stage_e { - R_STAGE_NO_CHANGE = 0, - R_STAGE_SESSION_CLEANUP = 1, - R_STAGE_SESSION_REOPEN = 2, - R_STAGE_SESSION_REDIRECT = 3, -} iscsi_session_r_stage_e; - typedef enum iscsi_event_e { EV_UNKNOWN = 0, EV_CONN_RECV_PDU = 1, @@ -377,6 +360,7 @@ extern int iscsi_io_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, /* initiator.c */ extern int session_login_task(node_rec_t *rec, queue_task_t *qtask); extern int session_logout_task(iscsi_session_t *session, queue_task_t *qtask); +extern iscsi_session_t *session_find_by_sid(int sid); extern iscsi_session_t *session_find_by_rec(node_rec_t *rec); extern int session_is_running(node_rec_t *rec); extern void* recvpool_get(iscsi_conn_t *conn, int ev_size); diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c index 5141748..a6054cc 100644 --- a/usr/iscsi_sysfs.c +++ b/usr/iscsi_sysfs.c @@ -1,3 +1,19 @@ +/* + * iSCSI sysfs + * + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <fcntl.h> #include <unistd.h> #include <stdlib.h> @@ -21,6 +37,9 @@ #include "version.h" #define ISCSI_TRANSPORT_DIR "/sys/class/iscsi_transport" +#define ISCSI_SESSION_DIR "/sys/class/iscsi_session" +#define ISCSI_CONN_DIR "/sys/class/iscsi_connection" + #define ISCSI_MAX_SYSFS_BUFFER NI_MAXHOST /* tmp buffer used by sysfs functions */ @@ -41,7 +60,7 @@ int read_sysfs_file(char *filename, void *value, char *format) sscanf(buffer, format, value); else { log_debug(5, "Could not read %s.\n", filename); - err = errno; + err = ENODATA; } fclose(file); } else { @@ -76,7 +95,7 @@ static int read_transports(void) init_providers(); n = scandir(ISCSI_TRANSPORT_DIR, &namelist, trans_filter, - alphasort); + versionsort); if (n < 0) { log_error("Could not scan %s.", ISCSI_TRANSPORT_DIR); return n; @@ -132,6 +151,66 @@ static int read_transports(void) return 0; } +static void get_negotiated_session_param(int sid, char *param, int *value) +{ + /* set to invalid */ + *value = -1; + + memset(sysfs_file, 0, PATH_MAX); + sprintf(sysfs_file, ISCSI_SESSION_DIR"/session%d/%s", sid, param); + read_sysfs_file(sysfs_file, value, "%d\n"); +} + +static void get_negotiated_conn_param(int sid, char *param, int *value) +{ + /* set to invalid */ + *value = -1; + + memset(sysfs_file, 0, PATH_MAX); + sprintf(sysfs_file, ISCSI_CONN_DIR"/connection%d:0/%s", sid, param); + read_sysfs_file(sysfs_file, value, "%d\n"); +} + +/* called must check for -1=invalid value */ +void get_negotiated_conn_conf(int sid, + struct iscsi_conn_operational_config *conf) +{ + memset(conf, 0, sizeof(*conf)); + + get_negotiated_conn_param(sid, "data_digest", + &conf->DataDigest); + get_negotiated_conn_param(sid, "header_digest", + &conf->HeaderDigest); + get_negotiated_conn_param(sid, "max_xmit_dlength", + &conf->MaxXmitDataSegmentLength); + get_negotiated_conn_param(sid, "max_recv_dlength", + &conf->MaxRecvDataSegmentLength); +} + +/* called must check for -1=invalid value */ +void get_negotiated_session_conf(int sid, + struct iscsi_session_operational_config *conf) +{ + memset(conf, 0, sizeof(*conf)); + + get_negotiated_session_param(sid, "data_pdu_in_order", + &conf->DataPDUInOrder); + get_negotiated_session_param(sid, "data_seq_in_order", + &conf->DataSequenceInOrder); + get_negotiated_session_param(sid, "erl", + &conf->ERL); + get_negotiated_session_param(sid, "first_burst_len", + &conf->FirstBurstLength); + get_negotiated_session_param(sid, "max_burst_len", + &conf->MaxBurstLength); + get_negotiated_session_param(sid, "immediate_data", + &conf->ImmediateData); + get_negotiated_session_param(sid, "initial_r2t", + &conf->InitialR2T); + get_negotiated_session_param(sid, "max_outstanding_r2t", + &conf->MaxOutstandingR2T); +} + int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, int *port, int *tpgt, char *session) { @@ -139,11 +218,11 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, if (sscanf(session, "session%d", sid) != 1) { log_error("invalid session '%s'", session); - return errno; + return -EINVAL; } memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, "/sys/class/iscsi_session/%s/targetname", session); + sprintf(sysfs_file, ISCSI_SESSION_DIR"/%s/targetname", session); ret = read_sysfs_file(sysfs_file, targetname, "%s\n"); if (ret) { log_error("could not read session targetname: %d", ret); @@ -151,7 +230,7 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, } memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, "/sys/class/iscsi_session/%s/tpgt", session); + sprintf(sysfs_file, ISCSI_SESSION_DIR"/%s/tpgt", session); ret = read_sysfs_file(sysfs_file, tpgt, "%u\n"); if (ret) { log_error("could not read session tpgt: %d", ret); @@ -160,7 +239,7 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, /* some HW drivers do not export addr and port */ memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, "/sys/class/iscsi_connection/connection%d:0/" + sprintf(sysfs_file, ISCSI_CONN_DIR"/connection%d:0/" "persistent_address", *sid); memset(addr, 0, NI_MAXHOST); ret = read_sysfs_file(sysfs_file, addr, "%s\n"); @@ -168,8 +247,7 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, /* fall back to current address */ log_debug(5, "could not read pers conn addr: %d", ret); memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, - "/sys/class/iscsi_connection/connection%d:0/address", + sprintf(sysfs_file, ISCSI_CONN_DIR"/connection%d:0/address", *sid); memset(addr, 0, NI_MAXHOST); ret = read_sysfs_file(sysfs_file, addr, "%s\n"); @@ -178,7 +256,7 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, } memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, "/sys/class/iscsi_connection/connection%d:0/" + sprintf(sysfs_file, ISCSI_CONN_DIR"/connection%d:0/" "persistent_port", *sid); *port = -1; ret = read_sysfs_file(sysfs_file, port, "%u\n"); @@ -186,8 +264,7 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, /* fall back to current port */ log_debug(5, "Could not read pers conn port %d\n", ret); memset(sysfs_file, 0, PATH_MAX); - sprintf(sysfs_file, - "/sys/class/iscsi_connection/connection%d:0/port", + sprintf(sysfs_file, ISCSI_CONN_DIR"/connection%d:0/port", *sid); *port = -1; ret = read_sysfs_file(sysfs_file, port, "%u\n"); @@ -203,9 +280,8 @@ int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, int sysfs_for_each_session(void *data, int *nr_found, int (* fn)(void *, char *, int, char *, int, int)) { - DIR *dirfd; - struct dirent *dent; - int rc = 0, sid, port, tpgt; + struct dirent **namelist; + int rc = 0, sid, port, tpgt, n, i; char *targetname, *address; targetname = malloc(TARGET_NAME_MAXLEN + 1); @@ -218,22 +294,19 @@ int sysfs_for_each_session(void *data, int *nr_found, goto free_target; } - sprintf(sysfs_file, "/sys/class/iscsi_session"); - dirfd = opendir(sysfs_file); - if (!dirfd) { - rc = -EINVAL; + sprintf(sysfs_file, ISCSI_SESSION_DIR); + n = scandir(sysfs_file, &namelist, trans_filter, + versionsort); + if (n <= 0) goto free_address; - } - - while ((dent = readdir(dirfd))) { - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) - continue; + for (i = 0; i < n; i++) { rc = get_sessioninfo_by_sysfs_id(&sid, targetname, address, - &port, &tpgt, dent->d_name); - if (rc < 0) { + &port, &tpgt, + namelist[i]->d_name); + if (rc) { log_error("could not find session info for %s", - dent->d_name); + namelist[i]->d_name); continue; } @@ -243,7 +316,10 @@ int sysfs_for_each_session(void *data, int *nr_found, (*nr_found)++; } - closedir(dirfd); + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + free_address: free(address); free_target: @@ -260,7 +336,7 @@ uint32_t get_host_no_from_sid(uint32_t sid, int *err) memset(buf, 0, PATH_MAX); memset(path, 0, PATH_MAX); - sprintf(path, "/sys/class/iscsi_session/session%d/device", sid); + sprintf(path, ISCSI_SESSION_DIR"/session%d/device", sid); if (readlink(path, buf, PATH_MAX) < 0) { log_error("Could not get link for %s\n", path); *err = errno; @@ -355,7 +431,7 @@ iscsi_provider_t *get_transport_by_sid(uint32_t sid) int set_exp_statsn(iscsi_conn_t *conn) { sprintf(sysfs_file, - "/sys/class/iscsi_connection/connection%d:%d/exp_statsn", + ISCSI_CONN_DIR"/connection%d:%d/exp_statsn", conn->session->id, conn->id); if (read_sysfs_file(sysfs_file, &conn->exp_statsn, "%u\n")) { log_error("Could not read %s. Using zero fpr exp_statsn\n", @@ -368,23 +444,27 @@ int set_exp_statsn(iscsi_conn_t *conn) int sysfs_for_each_device(int host_no, uint32_t sid, void (* fn)(int host_no, int lun)) { - DIR *dirfd; - struct dirent *dent; - int h, b, t, l; - - sprintf(sysfs_file, "/sys/class/iscsi_session/session%d/device/target%d:0:0", sid, host_no); - dirfd = opendir(sysfs_file); - if (!dirfd) - return errno; + struct dirent **namelist; + int h, b, t, l, i, n; - while ((dent = readdir(dirfd))) { - if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) - continue; + sprintf(sysfs_file, ISCSI_SESSION_DIR"/session%d/device/target%d:0:0", + sid, host_no); + n = scandir(sysfs_file, &namelist, trans_filter, + versionsort); + if (n <= 0) + return 0; - if (sscanf(dent->d_name, "%d:%d:%d:%d\n", &h, &b, &t, &l) != 4) + for (i = 0; i < n; i++) { + if (sscanf(namelist[i]->d_name, "%d:%d:%d:%d\n", + &h, &b, &t, &l) != 4) continue; fn(h, l); } + + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + return 0; } @@ -476,12 +556,20 @@ iscsi_provider_t *get_transport_by_session(char *sys_session) return get_transport_by_sid(sid); } +int get_iscsi_kernel_version(char *buf) +{ + if (read_sysfs_file(ISCSI_VERSION_FILE, buf, "%s\n")) + return -ENODATA; + else + return 0; +} + void check_class_version(void) { char version[20]; int i; - if (read_sysfs_file(ISCSI_VERSION_FILE, version, "%s\n")) + if (get_iscsi_kernel_version(version)) goto fail; log_warning("transport class version %s. iscsid version %s\n", diff --git a/usr/iscsi_sysfs.h b/usr/iscsi_sysfs.h index 06910a7..b0ba4cc 100644 --- a/usr/iscsi_sysfs.h +++ b/usr/iscsi_sysfs.h @@ -1,3 +1,19 @@ +/* + * iSCSI sysfs + * + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ #ifndef ISCSI_SYSFS_H #define ISCSI_SYSFS_H @@ -6,7 +22,10 @@ struct iscsi_session; struct iscsi_conn; +struct iscsi_session_operational_config; +struct iscsi_conn_operational_config; +extern int get_iscsi_kernel_version(char *buf); extern void check_class_version(void); extern int get_sessioninfo_by_sysfs_id(int *sid, char *targetname, char *addr, int *port, int *tpgt, @@ -16,6 +35,10 @@ extern int sysfs_for_each_session(void *data, int *nr_found, int (* fn)(void *, char *, int, char *, int, int)); extern uint32_t get_host_no_from_sid(uint32_t sid, int *err); extern int set_exp_statsn(struct iscsi_conn *conn); +extern void get_negotiated_session_conf(int sid, + struct iscsi_session_operational_config *conf); +extern void get_negotiated_conn_conf(int sid, + struct iscsi_conn_operational_config *conf); extern pid_t scan_host(struct iscsi_session *session); extern pid_t __scan_host(int hostno, int async); extern void set_device_online(int hostno, int lun); diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c index b45bddc..ba65080 100644 --- a/usr/iscsiadm.c +++ b/usr/iscsiadm.c @@ -2,6 +2,8 @@ * iSCSI Administration Utility * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -215,7 +217,7 @@ sys_to_rec(idbm_t *db, node_rec_t *rec, char *sysfs_device) log_debug(2, "%s: session %s", __FUNCTION__, sys_session); rc = get_sessioninfo_by_sysfs_id(&sid, targetname, address, &port, &tpgt, sys_session); - if (rc < 0) { + if (rc) { log_error("Unable to find a record for iscsi %s (sys %s)", sys_session, sysfs_device); goto free_address; @@ -497,24 +499,186 @@ config_init(void) return 0; } +static void print_scsi_device_info(int host_no, int lun) +{ + printf("scsi%d Channel 00 Id 0 Lun: %d\n", host_no, lun); +} + static int print_session(void *data, char *targetname, int tpgt, char *address, int port, int sid) { + int extended = *((int *)data), host_no = -1, err = 0; iscsi_provider_t *provider; + iscsiadm_req_t req; + iscsiadm_rsp_t rsp; + struct iscsi_session_operational_config session_conf; + struct iscsi_conn_operational_config conn_conf; + static char *conn_state[] = { + "FREE", + "TRANSPORT WAIT", + "IN LOGIN", + "LOGGED IN", + "IN LOGOUT", + "LOGOUT REQUESTED", + "CLEANUP WAIT", + }; + static char *session_state[] = { + "NO CHANGE", + "CLEANUP" + "REPOEN" + "REDIRECT" + }; provider = get_transport_by_sid(sid); - printf("%s: [%d] %s:%d,%d %s\n", provider ? provider->name : "NA", - sid, address, port, tpgt, targetname); + if (!extended) { + printf("%s: [%d] %s:%d,%d %s\n", + provider ? provider->name : "NA", + sid, address, port, tpgt, targetname); + return 0; + } + + /* TODO: how to pipe modinfo version info here */ + printf("************************************\n"); + printf("Session (sid %d) using module %s:\n", sid, + provider ? provider->name : "NA"); + printf("************************************\n"); + printf("TargetName: %s\n", targetname); + printf("Portal Group Tag: %d\n", tpgt); + printf("Network Portal: %s:%d\n", address, port); + + /* for now this is all we do for qla4xxx */ + if (!provider) + return 0; + + get_negotiated_session_conf(sid, &session_conf); + get_negotiated_conn_conf(sid, &conn_conf); + + /* + * get iscsid's conn and session state. This may be slightly different + * the kernel's view. + * + * TODO: get kernel state and qla4xxx info + */ + memset(&req, 0, sizeof(iscsiadm_req_t)); + req.command = MGMT_IPC_SESSION_INFO; + req.u.session.sid = sid; + + if (do_iscsid(&ipc_fd, &req, &rsp)) { + printf("Could not get extended session info for session sid " + "%d\n", sid); + return -EINVAL; + } + + if (rsp.u.session_state.conn_state < 0 || + rsp.u.session_state.conn_state > STATE_CLEANUP_WAIT) + printf("Invalid iSCSI Connection State\n"); + else + printf("iSCSI Connection State: %s\n", + conn_state[rsp.u.session_state.conn_state]); + + if (rsp.u.session_state.session_state < 0 || + rsp.u.session_state.session_state > R_STAGE_SESSION_REDIRECT) + printf("Invalid iscsid Session State\n"); + else + printf("Internal iscsid Session State: %s\n", + session_state[rsp.u.session_state.session_state]); + + printf("\n"); + printf("************************\n"); + printf("Negotiated iSCSI params:\n"); + printf("************************\n"); + + printf("HeaderDigest: %s\n", + conn_conf.HeaderDigest ? "CRC32C" : "None"); + printf("DataDigest: %s\n", + conn_conf.DataDigest ? "CRC32C" : "None"); + printf("MaxRecvDataSegmentLength: %d\n", + conn_conf.MaxRecvDataSegmentLength); + printf("MaxXmitDataSegmentLength: %d\n", + conn_conf.MaxXmitDataSegmentLength); + printf("FirstBurstLength: %d\n", + session_conf.FirstBurstLength); + printf("MaxBurstLength: %d\n", + session_conf.MaxBurstLength); + printf("ImmediateData: %s\n", + session_conf.ImmediateData ? "Yes" : "No"); + printf("InitialR2T: %s\n", + session_conf.InitialR2T ? "Yes" : "No"); + printf("MaxOutstandingR2T: %d\n", + session_conf.MaxOutstandingR2T); + printf("\n"); + + printf("************************\n"); + printf("Attached SCSI devices:\n"); + printf("************************\n"); + + host_no = get_host_no_from_sid(sid, &err); + if (err) { + printf("Host No: Unknown\n"); + return err; + } + printf("Host No: %d\n", host_no); + sysfs_for_each_device(host_no, sid, print_scsi_device_info); + printf("\n"); + return 0; } -static int session_activelist(void) +static int print_session_by_sid(int sid, int extended) { - int num_found = 0; + char session[64]; + char *targetname; + char *address; + int tmp_sid, rc, port, tpgt; + + snprintf(session, 63, "session%d", sid); + + targetname = malloc(TARGET_NAME_MAXLEN + 1); + if (!targetname) + return -ENOMEM; + + address = malloc(NI_MAXHOST + 1); + if (!address) { + rc = -ENOMEM; + goto free_target; + } + + rc = get_sessioninfo_by_sysfs_id(&tmp_sid, targetname, address, &port, + &tpgt, session); + if (rc) { + printf("Could not print session info for sid %d\n", sid); + goto free_address; + } + rc = print_session(&extended, targetname, tpgt, address, port, sid); + +free_address: + free(address); +free_target: + free(targetname); + return rc; - sysfs_for_each_session(NULL, &num_found, print_session); - return num_found; +} + +static int session_activelist(int extended) +{ + char version[20]; + int num_found = 0, err = 0; + + if (extended) { + if (get_iscsi_kernel_version(version)) + printf("iSCSI Transport Class version %s\n", + version); + printf("%s version %s\n", program_name, ISCSI_VERSION_STR); + } + + sysfs_for_each_session(&extended, &num_found, print_session); + if (err) { + printf("Can not get list of active sessions (%d)", err); + return err; + } else if (!num_found) + printf("no active sessions\n"); + return 0; } static int rescan_session(void *data, char *targetname, int tpgt, char *address, @@ -532,8 +696,7 @@ static int rescan_session(void *data, char *targetname, int tpgt, char *address, return 0; } - -static int session_rescan(int sid) +static int session_rescan(void) { int num_found = 0; @@ -1033,7 +1196,7 @@ found_node_rec: goto out; } } else if (mode == MODE_SESSION) { - if ((rc = verify_mode_params(argc, argv, "Rdrmus", 1))) { + if ((rc = verify_mode_params(argc, argv, "iRdrmus", 1))) { log_error("session mode: option '-%c' is not " "allowed or supported", rc); rc = -1; @@ -1052,6 +1215,11 @@ found_node_rec: goto out; } + if (do_info) { + rc = print_session_by_sid(sid, 1); + goto out; + } + if (do_stats) { if ((rc = session_stats(sid)) > 0) { iscsid_handle_error(rc); @@ -1068,6 +1236,7 @@ found_node_rec: rc = -1; goto out; } + if (do_stats) { log_error("--stats requires target id"); rc = -1; @@ -1075,18 +1244,16 @@ found_node_rec: } if (do_rescan) { - rc = session_rescan(-1); + rc = session_rescan(); goto out; } - if ((rc = session_activelist()) < 0) { - log_error("can not get list of active " - "sessions (%d)", rc); - rc = -1; + if (do_info) { + rc = session_activelist(1); goto out; - } else if (!rc) { - printf("no active sessions\n"); } + + rc = session_activelist(0); } } else { log_error("This mode is not yet supported"); diff --git a/usr/iscsid.c b/usr/iscsid.c index 132282c..cf2c936 100644 --- a/usr/iscsid.c +++ b/usr/iscsid.c @@ -2,6 +2,9 @@ * iSCSI Initiator Daemon * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify diff --git a/usr/mgmt_ipc.c b/usr/mgmt_ipc.c index 0d8fd4d..7216bd5 100644 --- a/usr/mgmt_ipc.c +++ b/usr/mgmt_ipc.c @@ -2,6 +2,8 @@ * iSCSI Administrator Utility Socket Interface * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * Originally based on: @@ -161,6 +163,23 @@ mgmt_ipc_cfg_initiatorname(queue_task_t *qtask, iscsiadm_rsp_t *rsp) } static mgmt_ipc_err_e +mgmt_ipc_session_info(queue_task_t *qtask, int sid, iscsiadm_rsp_t *rsp) +{ + iscsi_session_t *session; + struct msg_session_state *info; + + if (!(session = session_find_by_sid(sid))) { + log_error("session with sid %d not found!", sid); + return MGMT_IPC_ERR_NOT_FOUND; + } + + info = &rsp->u.session_state; + info->conn_state = session->conn[0].state; + info->session_state = session->r_stage; + return MGMT_IPC_OK; +} + +static mgmt_ipc_err_e mgmt_ipc_cfg_initiatoralias(queue_task_t *qtask, iscsiadm_rsp_t *rsp) { strcpy(rsp->u.config.var, dconfig->initiator_alias); @@ -332,6 +351,11 @@ mgmt_ipc_handle(int accept_fd) &rsp); immrsp = 1; break; + case MGMT_IPC_SESSION_INFO: + rsp.err = mgmt_ipc_session_info(qtask, req.u.session.sid, + &rsp); + immrsp = 1; + break; case MGMT_IPC_CONN_ADD: rsp.err = mgmt_ipc_conn_add(qtask, req.u.conn.cid); break; @@ -358,6 +382,8 @@ mgmt_ipc_handle(int accept_fd) default: log_error("unknown request: %s(%d) %u", __FUNCTION__, __LINE__, req.command); + rsp.err = MGMT_IPC_ERR_INVALID_REQ; + immrsp = 1; break; } diff --git a/usr/mgmt_ipc.h b/usr/mgmt_ipc.h index 0f1f72d..d081a02 100644 --- a/usr/mgmt_ipc.h +++ b/usr/mgmt_ipc.h @@ -43,6 +43,7 @@ typedef enum mgmt_ipc_err { MGMT_IPC_ERR_ACCESS = 13, MGMT_IPC_ERR_TRANS_CAPS = 14, MGMT_IPC_ERR_EXISTS = 15, + MGMT_IPC_ERR_INVALID_REQ = 16, } mgmt_ipc_err_e; typedef enum iscsiadm_cmd { @@ -58,8 +59,26 @@ typedef enum iscsiadm_cmd { MGMT_IPC_CONFIG_FILE = 10, MGMT_IPC_IMMEDIATE_STOP = 11, MGMT_IPC_SESSION_SYNC = 12, + MGMT_IPC_SESSION_INFO = 13, } iscsiadm_cmd_e; +typedef enum iscsi_conn_state_e { + STATE_FREE, + STATE_XPT_WAIT, + STATE_IN_LOGIN, + STATE_LOGGED_IN, + STATE_IN_LOGOUT, + STATE_LOGOUT_REQUESTED, + STATE_CLEANUP_WAIT, +} iscsi_conn_state_e; + +typedef enum iscsi_session_r_stage_e { + R_STAGE_NO_CHANGE, + R_STAGE_SESSION_CLEANUP, + R_STAGE_SESSION_REOPEN, + R_STAGE_SESSION_REDIRECT, +} iscsi_session_r_stage_e; + /* IPC Request */ typedef struct iscsiadm_req { iscsiadm_cmd_e command; @@ -96,6 +115,10 @@ typedef struct iscsiadm_rsp { struct msg_config { char var[VALUE_MAXLEN]; } config; + struct msg_session_state { + iscsi_session_r_stage_e session_state; + iscsi_conn_state_e conn_state; + } session_state; } u; } iscsiadm_rsp_t; diff --git a/usr/netlink.c b/usr/netlink.c index cb5b53f..0a49452 100644 --- a/usr/netlink.c +++ b/usr/netlink.c @@ -2,6 +2,8 @@ * iSCSI Netlink/Linux Interface * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify @@ -23,7 +25,6 @@ #include <unistd.h> #include <stdint.h> #include <errno.h> -#include <dirent.h> #include <asm/types.h> #include <sys/socket.h> #include <sys/types.h> diff --git a/usr/transport.c b/usr/transport.c index b583b82..06d7e2e 100644 --- a/usr/transport.c +++ b/usr/transport.c @@ -1,9 +1,24 @@ +/* + * iSCSI transport + * + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 <stdlib.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include <errno.h> -#include <dirent.h> #include "initiator.h" #include "transport.h" diff --git a/usr/transport.h b/usr/transport.h index bfa0aed..8bc4043 100644 --- a/usr/transport.h +++ b/usr/transport.h @@ -1,3 +1,19 @@ +/* + * iSCSI transport + * + * Copyright (C) 2006 Mike Christie + * Copyright (C) 2006 Red Hat, Inc. All rights reserved. + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ #ifndef ISCSI_TRANSPORT_H #define ISCSI_TRANSPORT_H diff --git a/usr/types.h b/usr/types.h index 366501c..63dd5cc 100644 --- a/usr/types.h +++ b/usr/types.h @@ -10,11 +10,7 @@ #include <netinet/in.h> #include <stdint.h> #include <sys/types.h> - -struct qelem { - struct qelem *q_forw; - struct qelem *q_back; -}; +#include <search.h> #define DATASEG_MAX 8192 #define HDRSEG_MAX 48+4 @@ -5,7 +5,6 @@ #include <ctype.h> #include <string.h> #include <errno.h> -#include <dirent.h> #include <pwd.h> #include <sys/types.h> #include <sys/stat.h> |