diff options
author | dmitry_yus <dmitry_yus@d7303112-9cec-0310-bdd2-e83a94d6c2b6> | 2005-04-09 02:33:23 +0000 |
---|---|---|
committer | dmitry_yus <dmitry_yus@d7303112-9cec-0310-bdd2-e83a94d6c2b6> | 2005-04-09 02:33:23 +0000 |
commit | a4b4adc25d2b02baee7049fa4c24120cfb5d1000 (patch) | |
tree | b4ad4a18dfaa6942e4d8f553e7c1793ac180e4ec | |
parent | d92ebb97cbe99d52735163c70dd2b3458c2e4330 (diff) | |
download | open-iscsi-a4b4adc25d2b02baee7049fa4c24120cfb5d1000.tar.gz |
kernel ipc cleanup. added and implemented iscsi_ipc callback structure
receive pool for control PDU's per-connection added
git-svn-id: svn://svn.berlios.de/open-iscsi@222 d7303112-9cec-0310-bdd2-e83a94d6c2b6
-rw-r--r-- | include/iscsi_iftrans.h | 16 | ||||
-rw-r--r-- | kernel/iscsi_if.c | 10 | ||||
-rw-r--r-- | kernel/iscsi_tcp.c | 49 | ||||
-rw-r--r-- | usr/Makefile | 2 | ||||
-rw-r--r-- | usr/discovery.c | 35 | ||||
-rw-r--r-- | usr/initiator.c | 495 | ||||
-rw-r--r-- | usr/initiator.h | 64 | ||||
-rw-r--r-- | usr/io.c | 49 | ||||
-rw-r--r-- | usr/ioctl.c | 472 | ||||
-rw-r--r-- | usr/iscsiadm.c | 22 | ||||
-rw-r--r-- | usr/iscsid.c | 19 | ||||
-rw-r--r-- | usr/iscsid.h | 9 | ||||
-rw-r--r-- | usr/login.c | 4 | ||||
-rw-r--r-- | usr/mgmt_ipc.c (renamed from usr/ipc.c) | 86 | ||||
-rw-r--r-- | usr/mgmt_ipc.h (renamed from usr/ipc.h) | 68 | ||||
-rw-r--r-- | usr/netlink.c | 400 |
16 files changed, 725 insertions, 1075 deletions
diff --git a/include/iscsi_iftrans.h b/include/iscsi_iftrans.h index fcea0c3..75248ef 100644 --- a/include/iscsi_iftrans.h +++ b/include/iscsi_iftrans.h @@ -38,7 +38,7 @@ * @stop_cnx: suspend connection * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. * - * API provided by generic iSCSI Data Path module + * API provided by iSCSI Initiator Data Path module */ struct iscsi_transport { struct module *owner; @@ -68,12 +68,16 @@ struct iscsi_transport { }; /* - * up calls + * transport registration upcalls */ -int iscsi_register_transport(struct iscsi_transport *t); -int iscsi_unregister_transport(struct iscsi_transport *t); -int iscsi_control_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, +extern int iscsi_register_transport(struct iscsi_transport *t); +extern int iscsi_unregister_transport(struct iscsi_transport *t); + +/* + * control plane "up" calls + */ +extern void iscsi_cnx_error(iscsi_cnx_t cp_cnx, enum iscsi_err error); +extern int iscsi_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, char *data, uint32_t data_size); -void iscsi_control_cnx_error(iscsi_cnx_t cp_cnx, enum iscsi_err error); #endif /* ISCSI_IFTRANS_H */ diff --git a/kernel/iscsi_if.c b/kernel/iscsi_if.c index 49c6adb..76cee24 100644 --- a/kernel/iscsi_if.c +++ b/kernel/iscsi_if.c @@ -266,7 +266,7 @@ iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb) return 0; } -int iscsi_control_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, +int iscsi_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { struct nlmsghdr *nlh; @@ -285,7 +285,7 @@ int iscsi_control_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, skb = mempool_zone_get_skb(&cnx->z_pdu); if (!skb) { - iscsi_control_cnx_error(cp_cnx, ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(cp_cnx, ISCSI_ERR_CNX_FAILED); printk("iscsi%d: can not deliver control PDU: OOM\n", cnx->host->host_no); return -ENOMEM; @@ -307,9 +307,9 @@ int iscsi_control_recv_pdu(iscsi_cnx_t cp_cnx, struct iscsi_hdr *hdr, return rc; } -EXPORT_SYMBOL_GPL(iscsi_control_recv_pdu); +EXPORT_SYMBOL_GPL(iscsi_recv_pdu); -void iscsi_control_cnx_error(iscsi_cnx_t cp_cnx, enum iscsi_err error) +void iscsi_cnx_error(iscsi_cnx_t cp_cnx, enum iscsi_err error) { struct nlmsghdr *nlh; struct sk_buff *skb; @@ -342,7 +342,7 @@ void iscsi_control_cnx_error(iscsi_cnx_t cp_cnx, enum iscsi_err error) printk("iscsi%d: detected cnx error (%d)\n", cnx->host->host_no, error); } -EXPORT_SYMBOL_GPL(iscsi_control_cnx_error); +EXPORT_SYMBOL_GPL(iscsi_cnx_error); static int iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, diff --git a/kernel/iscsi_tcp.c b/kernel/iscsi_tcp.c index f5a1b67..d5fc5fc 100644 --- a/kernel/iscsi_tcp.c +++ b/kernel/iscsi_tcp.c @@ -157,8 +157,8 @@ iscsi_hdr_extract(struct iscsi_conn *conn) printk("iscsi_tcp: PDU gather failed! " "copylen %d conn->in.copy %d\n", copylen, conn->in.copy); - iscsi_control_cnx_error(conn->handle, - ISCSI_ERR_PDU_GATHER_FAILED); + iscsi_cnx_error(conn->handle, + ISCSI_ERR_PDU_GATHER_FAILED); return 0; } debug_tcp("PDU gather #2 %d bytes!\n", copylen); @@ -572,8 +572,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) if (!conn->in.datalen) { struct iscsi_mgmt_task *mtask; - rc = iscsi_control_recv_pdu( - conn->handle, hdr, NULL, 0); + rc = iscsi_recv_pdu(conn->handle, hdr, NULL, 0); mtask = (struct iscsi_mgmt_task *) session->imm_cmds[conn->in.itt - ISCSI_IMM_ITT_OFFSET]; @@ -604,8 +603,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: if (!conn->in.datalen) { - rc = iscsi_control_recv_pdu( - conn->handle, hdr, NULL, 0); + rc = iscsi_recv_pdu(conn->handle, hdr, NULL, 0); if (conn->login_mtask != mtask) { spin_lock(&session->lock); __kfifo_put(session->immpool.queue, @@ -637,8 +635,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) } else if (conn->in.itt == ISCSI_RESERVED_TAG) { if (conn->in.opcode == ISCSI_OP_NOOP_IN && !conn->in.datalen) { - rc = iscsi_control_recv_pdu( - conn->handle, hdr, NULL, 0); + rc = iscsi_recv_pdu(conn->handle, hdr, NULL, 0); } else { rc = ISCSI_ERR_BAD_OPCODE; } @@ -841,8 +838,8 @@ iscsi_data_recv(struct iscsi_conn *conn) goto exit; } - rc = iscsi_control_recv_pdu(conn->handle, - conn->in.hdr, conn->data, conn->in.datalen); + rc = iscsi_recv_pdu(conn->handle, conn->in.hdr, conn->data, + conn->in.datalen); if (mtask && conn->login_mtask != mtask) { spin_lock(&session->lock); @@ -892,7 +889,7 @@ more: if (rc == -EAGAIN) goto nomore; else { - iscsi_control_cnx_error(conn->handle, rc); + iscsi_cnx_error(conn->handle, rc); return 0; } } @@ -904,7 +901,7 @@ more: if (!rc && conn->in.datalen) { conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { - iscsi_control_cnx_error(conn->handle, rc); + iscsi_cnx_error(conn->handle, rc); return 0; } } @@ -922,7 +919,7 @@ more: conn->in.ctask->sent; goto again; } - iscsi_control_cnx_error(conn->handle, rc); + iscsi_cnx_error(conn->handle, rc); return 0; } conn->in.copy -= conn->in.padding; @@ -991,7 +988,7 @@ iscsi_tcp_state_change(struct sock *sk) session->state = ISCSI_STATE_FAILED; } spin_unlock_bh(&session->conn_lock); - iscsi_control_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); } old_state_change = conn->old_state_change; @@ -1076,7 +1073,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) conn->suspend = 1; } else if (res == -EPIPE) { conn->suspend = 1; - iscsi_control_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); } return res; @@ -1123,7 +1120,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, conn->suspend = 1; } else if (res == -EPIPE) { conn->suspend = 1; - iscsi_control_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); } return res; @@ -2181,7 +2178,7 @@ iscsi_conn_stop(iscsi_cnx_t cnxh, int flag) } static int -iscsi_send_pdu(iscsi_cnx_t cnxh, struct iscsi_hdr *hdr, char *data, +iscsi_conn_send_pdu(iscsi_cnx_t cnxh, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { struct iscsi_conn *conn = iscsi_ptr(cnxh); @@ -2339,12 +2336,11 @@ iscsi_eh_abort(struct scsi_cmnd *sc) conn->tmabort_state = TMABORT_INITIAL; - rc = iscsi_send_pdu(iscsi_handle(conn), + rc = iscsi_conn_send_pdu(iscsi_handle(conn), (struct iscsi_hdr *)hdr, NULL, 0); if (rc) { session->state = ISCSI_STATE_FAILED; - iscsi_control_cnx_error(conn->handle, - ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); debug_scsi("abort sent failure [itt 0x%x]", ctask->itt); } else { conn->tmabort_timer.expires = 3*HZ + jiffies; /*3 secs*/ @@ -2399,8 +2395,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) } spin_unlock_bh(&session->lock); session->state = ISCSI_STATE_FAILED; - iscsi_control_cnx_error(conn->handle, - ISCSI_ERR_CNX_FAILED); + iscsi_cnx_error(conn->handle, ISCSI_ERR_CNX_FAILED); continue; } @@ -2600,7 +2595,7 @@ iscsi_session_destroy(iscsi_snx_t snxh) } static int -iscsi_set_param(iscsi_cnx_t cnxh, enum iscsi_param param, uint32_t value) +iscsi_conn_set_param(iscsi_cnx_t cnxh, enum iscsi_param param, uint32_t value) { struct iscsi_conn *conn = iscsi_ptr(cnxh); struct iscsi_session *session = conn->session; @@ -2716,7 +2711,7 @@ iscsi_set_param(iscsi_cnx_t cnxh, enum iscsi_param param, uint32_t value) } static int -iscsi_get_param(iscsi_cnx_t cnxh, enum iscsi_param param, uint32_t *value) +iscsi_conn_get_param(iscsi_cnx_t cnxh, enum iscsi_param param, uint32_t *value) { struct iscsi_conn *conn = iscsi_ptr(cnxh); struct iscsi_session *session = conn->session; @@ -2784,11 +2779,11 @@ struct iscsi_transport iscsi_tcp_transport = { .create_cnx = iscsi_conn_create, .bind_cnx = iscsi_conn_bind, .destroy_cnx = iscsi_conn_destroy, - .set_param = iscsi_set_param, - .get_param = iscsi_get_param, + .set_param = iscsi_conn_set_param, + .get_param = iscsi_conn_get_param, .start_cnx = iscsi_conn_start, .stop_cnx = iscsi_conn_stop, - .send_pdu = iscsi_send_pdu, + .send_pdu = iscsi_conn_send_pdu, }; static int __init diff --git a/usr/Makefile b/usr/Makefile index ba1dd42..1bebd58 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -6,7 +6,7 @@ COMMON_SRCS = io.o auth.o login.o log.o md5.o sha1.o idbm.o all: $(PROGRAMS) -iscsid: $(COMMON_SRCS) iscsid.o ipc.o netlink.o initiator.o actor.o queue.o +iscsid: $(COMMON_SRCS) iscsid.o mgmt_ipc.o netlink.o initiator.o actor.o queue.o $(CC) $^ -ldb -o $@ iscsiadm: $(COMMON_SRCS) strings.o discovery.o iscsiadm.o diff --git a/usr/discovery.c b/usr/discovery.c index 371023c..08aa454 100644 --- a/usr/discovery.c +++ b/usr/discovery.c @@ -68,7 +68,7 @@ send_nop_reply(iscsi_session_t *session, struct iscsi_nopin *nop, log_debug(4, "sending nop reply for ttt %u, cmdsn %u, dlength %d", ntohl(out.ttt), ntohl(out.cmdsn), ntoh24(out.dlength)); - return iscsi_send_pdu(&session->cnx[0], (struct iscsi_hdr *)&out, + return iscsi_io_send_pdu(&session->cnx[0], (struct iscsi_hdr *)&out, ISCSI_DIGEST_NONE, data, ISCSI_DIGEST_NONE, timeout); } @@ -117,7 +117,7 @@ request_targets(iscsi_session_t *session) if (++session->itt == ISCSI_RESERVED_TAG) session->itt = 1; - if (!iscsi_send_pdu(&session->cnx[0], hdr, ISCSI_DIGEST_NONE, data, + if (!iscsi_io_send_pdu(&session->cnx[0], hdr, ISCSI_DIGEST_NONE, data, ISCSI_DIGEST_NONE, session->cnx[0].active_timeout)) { log_error("failed to send SendTargets PDU"); return 0; @@ -148,7 +148,7 @@ iterate_targets(iscsi_session_t *session, uint32_t ttt) if (++session->itt == ISCSI_RESERVED_TAG) session->itt = 1; - if (!iscsi_send_pdu(&session->cnx[0], pdu, ISCSI_DIGEST_NONE, data, + if (!iscsi_io_send_pdu(&session->cnx[0], pdu, ISCSI_DIGEST_NONE, data, ISCSI_DIGEST_NONE, session->cnx[0].active_timeout)) { log_error("failed to send empty text PDU"); return 0; @@ -1024,7 +1024,7 @@ iscsi_logout_and_disconnect(iscsi_session_t * session) /* * Send the logout request */ - rc = iscsi_send_pdu(&session->cnx[0], (struct iscsi_hdr *)&logout_req, + rc = iscsi_io_send_pdu(&session->cnx[0],(struct iscsi_hdr *)&logout_req, ISCSI_DIGEST_NONE, NULL, ISCSI_DIGEST_NONE, 3); if (!rc) { log_error( @@ -1036,8 +1036,9 @@ iscsi_logout_and_disconnect(iscsi_session_t * session) * Read the logout response */ memset(&logout_resp, 0, sizeof(logout_resp)); - rc = iscsi_recv_pdu(&session->cnx[0], (struct iscsi_hdr *)&logout_resp, - ISCSI_DIGEST_NONE, NULL, 0, ISCSI_DIGEST_NONE, 1); + rc = iscsi_io_recv_pdu(&session->cnx[0], + (struct iscsi_hdr *)&logout_resp, ISCSI_DIGEST_NONE, NULL, + 0, ISCSI_DIGEST_NONE, 1); if (!rc) { log_error("iscsid: logout - failed to receive logout resp"); goto done; @@ -1051,7 +1052,7 @@ done: /* * Close the socket. */ - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); } int @@ -1142,7 +1143,7 @@ set_address: reconnect: - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); session->cmdsn = 1; session->itt = 1; @@ -1175,7 +1176,7 @@ reconnect: sleep(login_delay); } - if (!iscsi_connect(&session->cnx[0])) { + if (!iscsi_io_connect(&session->cnx[0])) { /* FIXME: IPv6 */ log_error("connection to discovery address %u.%u.%u.%u " "failed", session->cnx[0].ip_address[0], @@ -1219,7 +1220,7 @@ reconnect: session->cnx[0].ip_address[1], session->cnx[0].ip_address[2], session->cnx[0].ip_address[3]); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); login_failures++; goto set_address; @@ -1236,7 +1237,7 @@ reconnect: session->cnx[0].ip_address[1], session->cnx[0].ip_address[2], session->cnx[0].ip_address[3]); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); return 1; } @@ -1303,7 +1304,7 @@ reconnect: session->cnx[0].ip_address[2], session->cnx[0].ip_address[3], status_class, status_detail); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); return 1; case ISCSI_STATUS_CLS_TARGET_ERR: /* FIXME: IPv6 */ @@ -1315,7 +1316,7 @@ reconnect: session->cnx[0].ip_address[2], session->cnx[0].ip_address[3], status_class, status_detail); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); login_failures++; goto reconnect; default: @@ -1328,7 +1329,7 @@ reconnect: session->cnx[0].ip_address[2], session->cnx[0].ip_address[3], status_class, status_detail); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); login_failures++; goto reconnect; } @@ -1433,7 +1434,7 @@ reconnect: data + unused_length(&sendtargets); timeout = msecs_until(&connection_timer); - if (iscsi_recv_pdu(&session->cnx[0], + if (iscsi_io_recv_pdu(&session->cnx[0], pdu, ISCSI_DIGEST_NONE, data, end_of_data - data, ISCSI_DIGEST_NONE, timeout)) { @@ -1490,7 +1491,7 @@ reconnect: "terminating", config->address, config->port); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); return 1; } } @@ -1507,7 +1508,7 @@ reconnect: "discovery session to %s:%d " "terminating after hangup", config->address, config->port); - iscsi_disconnect(&session->cnx[0]); + iscsi_io_disconnect(&session->cnx[0]); return 1; } } diff --git a/usr/initiator.c b/usr/initiator.c index 0769bf2..bad4c3a 100644 --- a/usr/initiator.c +++ b/usr/initiator.c @@ -34,7 +34,8 @@ #include "iscsid.h" #include "iscsi_if.h" #include "iscsi_ifev.h" -#include "ipc.h" +#include "mgmt_ipc.h" +#include "iscsi_ipc.h" #include "idbm.h" #include "log.h" @@ -42,6 +43,67 @@ static void __session_mainloop(void *data); static char sysfs_file[PATH_MAX]; +static int +__recvpool_alloc(iscsi_conn_t *conn) +{ + int i; + + for (i = 0; i < RECVPOOL_MAX; i++) { + conn->recvpool[i] = calloc(1, ipc->ctldev_bufmax); + if (!conn->recvpool[i]) { + int j; + for (j = 0; j < i; j++) + free(conn->recvpool[j]); + return -ENOMEM; + } + } + + return 0; +} + +static void +__recvpool_free(iscsi_conn_t *conn) +{ + int i; + + for (i = 0; i < RECVPOOL_MAX; i++) { + if (!conn->recvpool[i]) { + log_error("recvpool leak: %d bytes", + ipc->ctldev_bufmax); + } else + free(conn->recvpool[i]); + } +} + +void* recvpool_get(iscsi_conn_t *conn, int ev_size) +{ + int i; + + if (ev_size > ipc->ctldev_bufmax) + return NULL; + + for (i = 0; i < RECVPOOL_MAX; i++) { + if (conn->recvpool[i]) { + void *handle = conn->recvpool[i]; + conn->recvpool[i] = NULL; + return handle; + } + } + return NULL; +} + +void recvpool_put(iscsi_conn_t *conn, void *handle) +{ + int i; + + for (i = 0; i < RECVPOOL_MAX; i++) { + if (!conn->recvpool[i]) { + conn->recvpool[i] = handle; + break; + } + } +} + /* * To sync caches before actual scsi_remove_host() we * need manually walk through the sysfs scsi host and delete @@ -78,10 +140,10 @@ __login_response_status(iscsi_conn_t *conn, case LOGIN_IO_ERROR: case LOGIN_WRONG_PORTAL_GROUP: case LOGIN_REDIRECTION_FAILED: - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); return CNX_LOGIN_RETRY; default: - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); log_error("cnx %d giving up on login attempts", conn->id); break; } @@ -112,11 +174,11 @@ __check_iscsi_status_class(iscsi_session_t *session, int cid, log_error("cnx %d login rejected: redirection " "type 0x%x not supported", conn->id, status_detail); - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); return CNX_LOGIN_RETRY; } case ISCSI_STATUS_CLS_INITIATOR_ERR: - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); switch (status_detail) { case ISCSI_LOGIN_STATUS_AUTH_FAILED: @@ -162,7 +224,7 @@ __check_iscsi_status_class(iscsi_session_t *session, int cid, case ISCSI_STATUS_CLS_TARGET_ERR: log_error("cnx %d login rejected: target error " "(%02x/%02x)\n", conn->id, status_class, status_detail); - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); /* * We have no idea what the problem is. But spec says initiator * may retry later. @@ -172,7 +234,7 @@ __check_iscsi_status_class(iscsi_session_t *session, int cid, log_error("cnx %d login response with unknown status " "class 0x%x, detail 0x%x\n", conn->id, status_class, status_detail); - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); break; } @@ -257,6 +319,11 @@ __session_cnx_create(iscsi_session_t *session, int cid) iscsi_conn_t *conn = &session->cnx[cid]; cnx_rec_t *cnx = &session->nrec.cnx[cid]; + if (__recvpool_alloc(conn)) { + log_error("cannot allocate recvpool for cnx cid %d", cid); + return -ENOMEM; + } + /* connection's timeouts */ conn->id = cid; conn->login_timeout = cnx->timeo.login_timeout; @@ -309,7 +376,9 @@ __session_cnx_create(iscsi_session_t *session, int cid) void session_cnx_destroy(iscsi_session_t *session, int cid) { - /* nothing to do right now */ + iscsi_conn_t *conn = &session->cnx[cid]; + + __recvpool_free(conn); } static iscsi_session_t* @@ -392,13 +461,15 @@ __session_cnx_cleanup(iscsi_conn_t *conn) { iscsi_session_t *session = conn->session; - if (ksession_cnx_destroy(session->ctrl_fd, conn)) { + if (ipc->destroy_cnx(session->transport_handle, conn->handle, + conn->id)) { log_error("can not safely destroy connection %d", conn->id); return; } session_cnx_destroy(session, conn->id); - if (ksession_destroy(session->ctrl_fd, session)) { + if (ipc->destroy_session(session->transport_handle, session->handle, + session->id)) { log_error("can not safely destroy session %d", session->id); return; } @@ -407,13 +478,13 @@ __session_cnx_cleanup(iscsi_conn_t *conn) } static void -__session_ipc_login_cleanup(queue_task_t *qtask, ipc_err_e err, int cnx_cleanup) +__session_mgmt_ipc_login_cleanup(queue_task_t *qtask, mgmt_ipc_err_e err, int cnx_cleanup) { iscsi_conn_t *conn = qtask->conn; iscsi_session_t *session = conn->session; if (cnx_cleanup) { - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); __session_cnx_cleanup(conn); } else { session_cnx_destroy(session, conn->id); @@ -422,9 +493,9 @@ __session_ipc_login_cleanup(queue_task_t *qtask, ipc_err_e err, int cnx_cleanup) } qtask->u.login.rsp.err = err; - write(qtask->u.login.ipc_fd, &qtask->u.login.rsp, + write(qtask->u.login.mgmt_ipc_fd, &qtask->u.login.rsp, sizeof(qtask->u.login.rsp)); - close(qtask->u.login.ipc_fd); + close(qtask->u.login.mgmt_ipc_fd); free(qtask); } @@ -443,7 +514,7 @@ __send_nopin_rsp(iscsi_conn_t *conn, struct iscsi_nopin *rhdr, char *data) hdr.ttt = rhdr->ttt; hdr.itt = ISCSI_RESERVED_TAG; - return iscsi_send_pdu(conn, (struct iscsi_hdr*)&hdr, + return iscsi_io_send_pdu(conn, (struct iscsi_hdr*)&hdr, ISCSI_DIGEST_NONE, data, ISCSI_DIGEST_NONE, 0); } @@ -495,8 +566,8 @@ __session_cnx_recv_pdu(queue_item_t *item) if (iscsi_login_rsp(session, c)) { log_debug(1, "login_rsp ret (%d)", c->ret); - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); + __session_mgmt_ipc_login_cleanup(c->qtask, + MGMT_IPC_ERR_LOGIN_FAILURE, 1); return; } @@ -504,17 +575,91 @@ __session_cnx_recv_pdu(queue_item_t *item) /* more nego. needed! */ conn->state = STATE_IN_LOGIN; if (iscsi_login_req(session, c)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); + __session_mgmt_ipc_login_cleanup(c->qtask, + MGMT_IPC_ERR_LOGIN_FAILURE, 1); return; } } else { + int i, rc; + uint32_t one = 1, zero = 0; + struct cnxparam { + int param; + uint32_t *value; + int cnx_only; } cnxtbl[ISCSI_PARAM_MAX] = { + + { + .param = ISCSI_PARAM_MAX_RECV_DLENGTH, + .value = &conn->max_recv_dlength, + .cnx_only = 1, + }, { + .param = ISCSI_PARAM_MAX_XMIT_DLENGTH, + .value = &conn->max_xmit_dlength, + .cnx_only = 1, + }, { + .param = ISCSI_PARAM_HDRDGST_EN, + .value = &conn->hdrdgst_en, + .cnx_only = 1, + }, { + .param = ISCSI_PARAM_DATADGST_EN, + .value = &conn->datadgst_en, + .cnx_only = 1, + }, { + .param = ISCSI_PARAM_INITIAL_R2T_EN, + .value = &session->initial_r2t_en, + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_MAX_R2T, + .value = &one, /* FIXME: session->max_r2t */ + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_IMM_DATA_EN, + .value = &session->imm_data_en, + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_FIRST_BURST, + .value = &session->first_burst, + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_MAX_BURST, + .value = &session->max_burst, + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_PDU_INORDER_EN, + .value = &session->pdu_inorder_en, + .cnx_only = 0, + }, { + .param =ISCSI_PARAM_DATASEQ_INORDER_EN, + .value = &session->dataseq_inorder_en, + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_ERL, + .value = &zero, /* FIXME: session->erl */ + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_IFMARKER_EN, + .value = &zero,/* FIXME: session->ifmarker_en */ + .cnx_only = 0, + }, { + .param = ISCSI_PARAM_OFMARKER_EN, + .value = &zero,/* FIXME: session->ofmarker_en */ + .cnx_only = 0, + } + + /* + * FIXME: set these timeouts via set_param() API + * + * rec->session.timeo + * rec->session.timeo + * rec->session.err_timeo + */ + }; + /* almost! entered full-feature phase */ if (__login_response_status(conn, c->ret) != CNX_LOGIN_SUCCESS) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); + __session_mgmt_ipc_login_cleanup(c->qtask, + MGMT_IPC_ERR_LOGIN_FAILURE, 1); return; } @@ -522,140 +667,67 @@ __session_cnx_recv_pdu(queue_item_t *item) if (__check_iscsi_status_class(session, conn->id, c->status_class, c->status_detail) != CNX_LOGIN_SUCCESS) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); + __session_mgmt_ipc_login_cleanup(c->qtask, + MGMT_IPC_ERR_LOGIN_FAILURE, 1); return; } /* Entered full-feature phase! */ - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_MAX_RECV_DLENGTH, - conn->max_recv_dlength)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_MAX_XMIT_DLENGTH, - conn->max_xmit_dlength)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_HDRDGST_EN, conn->hdrdgst_en)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_DATADGST_EN, conn->datadgst_en)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (conn->id == 0) { - /* setup session's op. parameters just once */ - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_INITIAL_R2T_EN, - session->initial_r2t_en)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_MAX_R2T, - 1 /* FIXME: session->max_r2t */)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_IMM_DATA_EN, - session->imm_data_en)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_FIRST_BURST, - session->first_burst)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_MAX_BURST, - session->max_burst)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_PDU_INORDER_EN, - session->pdu_inorder_en)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_DATASEQ_INORDER_EN, - session->dataseq_inorder_en)) { - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_ERL, - 0 /* FIXME: session->erl */)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_IFMARKER_EN, - 0 /* FIXME: session->ifmarker_en */)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); + for (i = 0; i < ISCSI_PARAM_MAX; i++) { + if (conn->id != 0 && !cnxtbl[i].cnx_only) + continue; + if (ipc->set_param( + session->transport_handle, + conn->handle, cnxtbl[i].param, + *cnxtbl[i].value, &rc) || rc) { + log_error("can't set operational " + "parameter %d for cnx with " + "id = %d, retcode %d (%d)", + cnxtbl[i].param, conn->id, + rc, errno); + __session_mgmt_ipc_login_cleanup( + c->qtask, + MGMT_IPC_ERR_LOGIN_FAILURE, 1); return; } - if (ksession_set_param(session->ctrl_fd, conn, - ISCSI_PARAM_OFMARKER_EN, - 0 /* FIXME: session->ofmarker_en */)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_LOGIN_FAILURE, 1); - return; - } - - /* - * FIXME: set these timeouts via set_param() API - * - * rec->session.timeo - * rec->session.timeo - * rec->session.err_timeo - */ + log_debug(3, "set operational parameter %d " + "to %u", cnxtbl[i].param, + *cnxtbl[i].value); } - if (ksession_start_cnx(session->ctrl_fd, conn)) { - __session_ipc_login_cleanup(c->qtask, - IPC_ERR_INTERNAL, 1); + if (ipc->start_cnx(session->transport_handle, + conn->handle, &rc) || rc) { + __session_mgmt_ipc_login_cleanup(c->qtask, + MGMT_IPC_ERR_INTERNAL, 1); + log_error("can't start connection 0x%p with " + "id = %d, retcode %d (%d)", + (void*)conn->handle, conn->id, rc, + errno); return; } conn->state = STATE_LOGGED_IN; if (session->r_stage == R_STAGE_NO_CHANGE) { - c->qtask->u.login.rsp.err = IPC_OK; - write(c->qtask->u.login.ipc_fd, + c->qtask->u.login.rsp.err = MGMT_IPC_OK; + write(c->qtask->u.login.mgmt_ipc_fd, &c->qtask->u.login.rsp, sizeof(c->qtask->u.login.rsp)); - close(c->qtask->u.login.ipc_fd); + close(c->qtask->u.login.mgmt_ipc_fd); free(c->qtask); - } else + log_debug(3, "connection 0x%p is operational " + "now", (void*)conn->handle); + } else { session->r_stage = R_STAGE_NO_CHANGE; + log_debug(3, "connection 0x%p is operational " + "after recovery", (void*)conn->handle); + } } } else if (conn->state == STATE_LOGGED_IN) { struct iscsi_hdr hdr; /* read incomming PDU */ - if (!iscsi_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE, conn->data, + if (!iscsi_io_recv_pdu(conn, &hdr, ISCSI_DIGEST_NONE,conn->data, DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, ISCSI_DIGEST_NONE, 0)) { return; @@ -675,7 +747,7 @@ __session_cnx_recv_pdu(queue_item_t *item) static void __session_cnx_poll(queue_item_t *item) { - ipc_err_e err = IPC_OK; + mgmt_ipc_err_e err = MGMT_IPC_OK; queue_task_t *qtask = item->context; iscsi_conn_t *conn = qtask->conn; iscsi_login_context_t *c = &conn->login_context; @@ -683,7 +755,7 @@ __session_cnx_poll(queue_item_t *item) int rc; if (conn->state == STATE_XPT_WAIT) { - rc = iscsi_tcp_poll(conn); + rc = iscsi_io_tcp_poll(conn); if (rc == 0) { /* timedout: poll again */ queue_produce(session->queue, EV_CNX_POLL, qtask, 0, 0); @@ -699,30 +771,47 @@ __session_cnx_poll(queue_item_t *item) /* do not allocate new connection in case of reopen */ if (session->r_stage == R_STAGE_NO_CHANGE) { if (conn->id == 0 && - ksession_create(session->ctrl_fd, - session)) { - err = IPC_ERR_INTERNAL; + ipc->create_session( + session->transport_handle, + (ulong_t)session, + session->nrec.session.initial_cmdsn, + &session->handle, &session->id)) { + log_error("can't create session (%d)", + errno); + err = MGMT_IPC_ERR_INTERNAL; goto cleanup; } + log_debug(3, "created new iSCSI session, " + "handle 0x%p", (void*)session->handle); - if (ksession_cnx_create(session->ctrl_fd, - session, conn)) { - err = IPC_ERR_INTERNAL; + if (ipc->create_cnx(session->transport_handle, + session->handle, (ulong_t)conn, + session->id, conn->id, &conn->handle)) { + err = MGMT_IPC_ERR_INTERNAL; goto s_cleanup; } + log_debug(3, "created new iSCSI connection, " + "handle 0x%p", (void*)conn->handle); } - if (ksession_cnx_bind(session->ctrl_fd, session, - conn)) { - err = IPC_ERR_INTERNAL; + if (ipc->bind_cnx(session->transport_handle, + session->handle, conn->handle, conn->socket_fd, + (conn->id == 0), &rc) || rc) { + log_error("can't bind a cnx with id = %d, " + "retcode %d (%d)", conn->id, rc, + errno); + err = MGMT_IPC_ERR_INTERNAL; goto c_cleanup; } + log_debug(3, "bound iSCSI connection (handle 0x%p) to " + "session (handle 0x%p)", (void*)conn->handle, + (void*)session->handle); conn->kernel_io = 1; - conn->send_pdu_begin = ksession_send_pdu_begin; - conn->send_pdu_end = ksession_send_pdu_end; - conn->recv_pdu_begin = ksession_recv_pdu_begin; - conn->recv_pdu_end = ksession_recv_pdu_end; + conn->send_pdu_begin = ipc->send_pdu_begin; + conn->send_pdu_end = ipc->send_pdu_end; + conn->recv_pdu_begin = ipc->recv_pdu_begin; + conn->recv_pdu_end = ipc->recv_pdu_end; conn->send_pdu_timer_add = __send_pdu_timer_add; conn->send_pdu_timer_remove = __send_pdu_timer_remove; @@ -732,19 +821,19 @@ __session_cnx_poll(queue_item_t *item) c->bufsize = sizeof(conn->data); if (iscsi_login_begin(session, c)) { - err = IPC_ERR_LOGIN_FAILURE; + err = MGMT_IPC_ERR_LOGIN_FAILURE; goto c_cleanup; } conn->state = STATE_IN_LOGIN; if (iscsi_login_req(session, c)) { - err = IPC_ERR_LOGIN_FAILURE; + err = MGMT_IPC_ERR_LOGIN_FAILURE; goto c_cleanup; } } else { actor_delete(&conn->connect_timer); /* error during connect */ - err = IPC_ERR_TCP_FAILURE; + err = MGMT_IPC_ERR_TCP_FAILURE; goto cleanup; } } @@ -752,15 +841,17 @@ __session_cnx_poll(queue_item_t *item) return; c_cleanup: - if (ksession_cnx_destroy(session->ctrl_fd, conn)) { + if (ipc->destroy_cnx(session->transport_handle, conn->handle, + conn->id)) { log_error("can not safely destroy connection %d", conn->id); } s_cleanup: - if (ksession_destroy(session->ctrl_fd, session)) { + if (ipc->destroy_session(session->transport_handle, session->handle, + session->id)) { log_error("can not safely destroy session %d", session->id); } cleanup: - __session_ipc_login_cleanup(qtask, err, 0); + __session_mgmt_ipc_login_cleanup(qtask, err, 0); } static void @@ -787,20 +878,23 @@ __session_cnx_reopen(iscsi_conn_t *conn, int do_stop) session->reopen_qtask.conn = conn; if (do_stop) { - if (ksession_stop_cnx(session->ctrl_fd, conn, + if (ipc->stop_cnx(session->transport_handle, conn->handle, STOP_CNX_RECOVER)) { - log_error("can not safely stop connection %d", - conn->id); + log_error("can't stop connection 0x%p with " + "id = %d (%d)", (void*)conn->handle, + conn->id, errno); return -1; } - iscsi_disconnect(conn); + log_debug(3, "connection 0x%p is stopped for recovery", + (void*)conn->handle); + iscsi_io_disconnect(conn); } - rc = iscsi_tcp_connect(conn, 1); + rc = iscsi_io_tcp_connect(conn, 1); if (rc < 0 && errno != EINPROGRESS) { log_error("cannot make a connection to %s:%d (%d)", inet_ntoa(conn->addr.sin_addr), conn->port, errno); - return IPC_ERR_TCP_FAILURE; + return MGMT_IPC_ERR_TCP_FAILURE; } conn->state = STATE_XPT_WAIT; @@ -810,7 +904,7 @@ __session_cnx_reopen(iscsi_conn_t *conn, int do_stop) actor_timer(&conn->connect_timer, conn->login_timeout*1000, __connect_timedout, &session->reopen_qtask); - return IPC_OK; + return MGMT_IPC_OK; } static void @@ -825,8 +919,8 @@ __session_cnx_timer(queue_item_t *item) log_debug(6, "cnx_timer popped at XPT_WAIT: login"); /* timeout during initial connect. * clean connection. write ipc rsp */ - __session_ipc_login_cleanup(qtask, - IPC_ERR_TCP_TIMEOUT, 0); + __session_mgmt_ipc_login_cleanup(qtask, + MGMT_IPC_ERR_TCP_TIMEOUT, 0); } else if (session->r_stage == R_STAGE_SESSION_REOPEN) { log_debug(6, "cnx_timer popped at XPT_WAIT: reopen"); /* timeout during reopen connect. @@ -839,20 +933,22 @@ __session_cnx_timer(queue_item_t *item) } } } else if (conn->state == STATE_IN_LOGIN) { - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); if (session->r_stage == R_STAGE_NO_CHANGE) { log_debug(6, "cnx_timer popped at IN_LOGIN"); /* send pdu timeout. clean connection. write rsp */ - if (ksession_cnx_destroy(session->ctrl_fd, conn)) { + if (ipc->destroy_cnx(session->transport_handle, + conn->handle, conn->id)) { log_error("can not safely destroy " "connection %d", conn->id); } - if (ksession_destroy(session->ctrl_fd, session)) { + if (ipc->destroy_session(session->transport_handle, + session->handle, session->id)) { log_error("can not safely destroy session %d", session->id); } - __session_ipc_login_cleanup(qtask, - IPC_ERR_PDU_TIMEOUT, 0); + __session_mgmt_ipc_login_cleanup(qtask, + MGMT_IPC_ERR_PDU_TIMEOUT, 0); } else if (session->r_stage == R_STAGE_SESSION_REOPEN) { if (--session->reopen_cnt > 0) { if (__session_cnx_reopen(conn, 1)) @@ -924,12 +1020,16 @@ __session_cnx_error(queue_item_t *item) __session_cnx_cleanup(conn); return; } else { - if (ksession_stop_cnx(session->ctrl_fd, conn, STOP_CNX_TERM)) { - log_error("can not safely stop connection %d", - conn->id); + if (ipc->stop_cnx(session->transport_handle, conn->handle, + STOP_CNX_TERM)) { + log_error("can't stop connection 0x%p with " + "id = %d (%d)", (void*)conn->handle, + conn->id, errno); return; } - iscsi_disconnect(conn); + log_debug(3, "connection 0x%p is stopped for termination", + (void*)conn->handle); + iscsi_io_disconnect(conn); } __session_cnx_cleanup(conn); @@ -981,8 +1081,10 @@ __get_transport_by_name(char *transport_name) struct iscsi_uevent ev; int i; - if (ktrans_list(control_fd, &ev)) + if (ipc->trans_list(&ev)) { + log_error("can't retreive transport list (%d)", errno); return 0; + } for (i = 0; i < ISCSI_TRANSPORT_MAX; i++) { if (ev.r.t_list.elements[i].handle) { @@ -1003,33 +1105,33 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) uint64_t transport_handle; if (!rec->active_cnx) - return IPC_ERR_INVAL; + return MGMT_IPC_ERR_INVAL; transport_handle = __get_transport_by_name(rec->transport_name); if (!transport_handle) - return IPC_ERR_TRANS_NOT_FOUND; + return MGMT_IPC_ERR_TRANS_NOT_FOUND; session = __session_create(rec, transport_handle); if (!session) - return IPC_ERR_LOGIN_FAILURE; + return MGMT_IPC_ERR_LOGIN_FAILURE; /* FIXME: login all connections! marked as "automatic" */ /* create leading connection */ if (__session_cnx_create(session, 0)) { __session_destroy(session); - return IPC_ERR_LOGIN_FAILURE; + return MGMT_IPC_ERR_LOGIN_FAILURE; } conn = &session->cnx[0]; qtask->conn = conn; - rc = iscsi_tcp_connect(conn, 1); + rc = iscsi_io_tcp_connect(conn, 1); if (rc < 0 && errno != EINPROGRESS) { log_error("cannot make a connection to %s:%d (%d)", inet_ntoa(conn->addr.sin_addr), conn->port, errno); session_cnx_destroy(session, 0); __session_destroy(session); - return IPC_ERR_TCP_FAILURE; + return MGMT_IPC_ERR_TCP_FAILURE; } conn->state = STATE_XPT_WAIT; @@ -1038,7 +1140,7 @@ session_login_task(node_rec_t *rec, queue_task_t *qtask) actor_timer(&conn->connect_timer, conn->login_timeout*1000, __connect_timedout, qtask); - return IPC_OK; + return MGMT_IPC_OK; } int @@ -1050,7 +1152,7 @@ session_logout_task(iscsi_session_t *session, queue_task_t *qtask) conn = &session->cnx[0]; if (conn->state != STATE_LOGGED_IN && conn->state != STATE_CLEANUP_WAIT) { - return IPC_ERR_INTERNAL; + return MGMT_IPC_ERR_INTERNAL; } /* FIXME: implement Logout Request */ @@ -1058,28 +1160,37 @@ session_logout_task(iscsi_session_t *session, queue_task_t *qtask) __session_delete_luns(session); /* stop if connection is logged in */ - if (conn->state == STATE_LOGGED_IN && - ksession_stop_cnx(session->ctrl_fd, conn, STOP_CNX_TERM)) { - return IPC_ERR_INTERNAL; + if (conn->state == STATE_LOGGED_IN) { + if (ipc->stop_cnx(session->transport_handle, conn->handle, + STOP_CNX_TERM)) { + log_error("can't stop connection 0x%p with " + "id = %d (%d)", (void*)conn->handle, + conn->id, errno); + return MGMT_IPC_ERR_INTERNAL; + } + log_debug(3, "connection 0x%p is stopped for termination", + (void*)conn->handle); } - iscsi_disconnect(conn); + iscsi_io_disconnect(conn); - if (ksession_cnx_destroy(session->ctrl_fd, conn)) { - return IPC_ERR_INTERNAL; + if (ipc->destroy_cnx(session->transport_handle, conn->handle, + conn->id)) { + return MGMT_IPC_ERR_INTERNAL; } session_cnx_destroy(session, conn->id); - if (ksession_destroy(session->ctrl_fd, session)) { - return IPC_ERR_INTERNAL; + if (ipc->destroy_session(session->transport_handle, session->handle, + session->id)) { + return MGMT_IPC_ERR_INTERNAL; } __session_destroy(session); - qtask->u.login.rsp.err = IPC_OK; - write(qtask->u.login.ipc_fd, &qtask->u.login.rsp, + qtask->u.login.rsp.err = MGMT_IPC_OK; + write(qtask->u.login.mgmt_ipc_fd, &qtask->u.login.rsp, sizeof(qtask->u.login.rsp)); - close(qtask->u.login.ipc_fd); + close(qtask->u.login.mgmt_ipc_fd); free(qtask); - return IPC_OK; + return MGMT_IPC_OK; } diff --git a/usr/initiator.h b/usr/initiator.h index 7f55e29..dad4aff 100644 --- a/usr/initiator.h +++ b/usr/initiator.h @@ -2,7 +2,7 @@ * iSCSI Initiator * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman - * maintained by open-iscsi@@googlegroups.com + * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -27,7 +27,7 @@ #include "iscsi_if.h" #include "iscsi_ifev.h" #include "auth.h" -#include "ipc.h" +#include "mgmt_ipc.h" #include "config.h" #include "actor.h" #include "queue.h" @@ -113,14 +113,15 @@ typedef struct iscsi_login_context { struct iscsi_session; struct iscsi_conn; -typedef void (*send_pdu_begin_f)(int ctrl_fd, struct iscsi_session *session, - struct iscsi_conn *conn, int hdr_size, int data_size); -typedef int (*send_pdu_end_f)(int ctrl_fd, struct iscsi_session *session, - struct iscsi_conn *conn); -typedef int (*recv_pdu_begin_f)(int ctrl_fd, struct iscsi_conn *conn, - ulong_t recv_handle, ulong_t *pdu_handle, int *pdu_size); -typedef int (*recv_pdu_end_f)(int ctrl_fd, struct iscsi_conn *conn, - ulong_t pdu_handle); +typedef void (*send_pdu_begin_f) (uint64_t transport_handle, ulong_t dp_cnx, + int hdr_size, int data_size); +typedef int (*send_pdu_end_f) (uint64_t transport_handle, ulong_t dp_cnx, + int *retcode); +typedef int (*recv_pdu_begin_f) (uint64_t transport_handle, ulong_t dp_cnx, + ulong_t recv_handle, ulong_t *pdu_handle, + int *pdu_size); +typedef int (*recv_pdu_end_f) (uint64_t transport_handle, ulong_t dp_cnx, + ulong_t pdu_handle); typedef void (*send_pdu_timer_add_f)(struct iscsi_conn *conn, int timeout); typedef void (*send_pdu_timer_remove_f)(struct iscsi_conn *conn); @@ -146,6 +147,9 @@ typedef struct iscsi_conn { send_pdu_timer_add_f send_pdu_timer_add; send_pdu_timer_remove_f send_pdu_timer_remove; +#define RECVPOOL_MAX 32 + void* recvpool[RECVPOOL_MAX]; + /* login state machine */ int current_stage; int next_stage; @@ -185,12 +189,12 @@ typedef struct queue_task { struct ipcreq_login { iscsiadm_req_t req; iscsiadm_rsp_t rsp; - int ipc_fd; + int mgmt_ipc_fd; } login; struct ipcreq_logout { iscsiadm_req_t req; iscsiadm_rsp_t rsp; - int ipc_fd; + int mgmt_ipc_fd; } logout; /* iSCSI requests originated via CTL */ struct ctlreq_recv_pdu { @@ -316,13 +320,13 @@ extern int iscsi_login_rsp(iscsi_session_t *session, iscsi_login_context_t *c); #define IRRELEVANT_DATASEQUENCEINORDER 0x80 /* io.c */ -extern int iscsi_tcp_poll(iscsi_conn_t *conn); -extern int iscsi_tcp_connect(iscsi_conn_t *conn, int non_blocking); -extern int iscsi_connect(iscsi_conn_t *conn); -extern void iscsi_disconnect(iscsi_conn_t *conn); -extern int iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, +extern int iscsi_io_tcp_poll(iscsi_conn_t *conn); +extern int iscsi_io_tcp_connect(iscsi_conn_t *conn, int non_blocking); +extern int iscsi_io_connect(iscsi_conn_t *conn); +extern void iscsi_io_disconnect(iscsi_conn_t *conn); +extern int iscsi_io_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, int hdr_digest, char *data, int data_digest, int timeout); -extern int iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, +extern int iscsi_io_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, int hdr_digest, char *data, int max_data_length, int data_digest, int timeout); @@ -330,27 +334,7 @@ extern int iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, 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_rec(node_rec_t *rec); - -/* transport API Ioctl/IPC/NETLINK/etc */ -extern int ksession_create(int ctrl_fd, iscsi_session_t *session); -extern int ksession_destroy(int ctrl_fd, iscsi_session_t *session); -extern int ksession_cnx_create(int ctrl_fd, iscsi_session_t *session, - iscsi_conn_t *conn); -extern int ksession_cnx_destroy(int ctrl_fd, iscsi_conn_t *conn); -extern int ksession_cnx_bind(int ctrl_fd, iscsi_session_t *session, - iscsi_conn_t *conn); -extern void ksession_send_pdu_begin(int ctrl_fd, iscsi_session_t *session, - iscsi_conn_t *conn, int hdr_size, int data_size); -extern int ksession_send_pdu_end(int ctrl_fd, iscsi_session_t *session, - iscsi_conn_t *conn); -extern int ksession_set_param(int ctrl_fd, iscsi_conn_t *conn, - enum iscsi_param param, uint32_t value); -extern int ksession_stop_cnx(int ctrl_fd, iscsi_conn_t *conn, int flag); -extern int ksession_start_cnx(int ctrl_fd, iscsi_conn_t *conn); -extern int ksession_recv_pdu_begin(int ctrl_fd, iscsi_conn_t *conn, - ulong_t recv_handle, ulong_t *pdu_handle, int *pdu_size); -extern int ksession_recv_pdu_end(int ctrl_fd, iscsi_conn_t *conn, - ulong_t pdu_handle); -extern int ktrans_list(int ctrl_fd, struct iscsi_uevent *ev); +extern void* recvpool_get(iscsi_conn_t *conn, int ev_size); +extern void recvpool_put(iscsi_conn_t *conn, void *handle); #endif /* INITIATOR_H */ @@ -32,6 +32,7 @@ #include "iscsi_proto.h" #include "initiator.h" +#include "iscsi_ipc.h" #include "log.h" #define LOG_CONN_CLOSED(conn) \ @@ -63,7 +64,7 @@ set_non_blocking(int fd) } int -iscsi_tcp_connect(iscsi_conn_t *conn, int non_blocking) +iscsi_io_tcp_connect(iscsi_conn_t *conn, int non_blocking) { int rc, onearg; @@ -137,7 +138,7 @@ iscsi_tcp_connect(iscsi_conn_t *conn, int non_blocking) } int -iscsi_tcp_poll(iscsi_conn_t *conn) +iscsi_io_tcp_poll(iscsi_conn_t *conn) { int rc; struct pollfd pdesc; @@ -165,7 +166,7 @@ iscsi_tcp_poll(iscsi_conn_t *conn) } int -iscsi_connect(iscsi_conn_t *conn) +iscsi_io_connect(iscsi_conn_t *conn) { int rc, ret; struct sigaction action; @@ -186,7 +187,7 @@ iscsi_connect(iscsi_conn_t *conn) /* perform blocking TCP connect operation when no async request * associated. SendTargets Discovery know to work in such a mode. */ - rc = iscsi_tcp_connect(conn, 0); + rc = iscsi_io_tcp_connect(conn, 0); if (timedout) { log_debug(1, "socket %d connect timed out", conn->socket_fd); ret = 0; @@ -218,7 +219,7 @@ done: } void -iscsi_disconnect(iscsi_conn_t *conn) +iscsi_io_disconnect(iscsi_conn_t *conn) { if (conn->socket_fd >= 0) { log_debug(1, "disconnecting conn %p, fd %d", conn, @@ -244,7 +245,7 @@ iscsi_log_text(struct iscsi_hdr *pdu, char *data) } int -iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, +iscsi_io_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, int hdr_digest, char *data, int data_digest, int timeout) { int rc, ret = 0; @@ -338,7 +339,7 @@ iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, pad_bytes = 0; if (conn->kernel_io) { - conn->send_pdu_begin(session->ctrl_fd, session, conn, + conn->send_pdu_begin(session->transport_handle, conn->handle, end - header, ntoh24(hdr->dlength) + pad_bytes); conn->send_pdu_timer_add(conn, timeout); } @@ -347,7 +348,10 @@ iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, vec[0].iov_base = header; vec[0].iov_len = end - header; - rc = ctldev_writev(session->ctrl_fd, 0, vec, 1); + if (!conn->kernel_io) + rc = writev(session->ctrl_fd, vec, 1); + else + rc = ipc->writev(0, vec, 1); if (timedout) { log_error("socket %d write timed out", conn->socket_fd); @@ -372,7 +376,10 @@ iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, vec[1].iov_base = (void *) &pad; vec[1].iov_len = pad_bytes; - rc = ctldev_writev(session->ctrl_fd, 0, vec, 2); + if (!conn->kernel_io) + rc = writev(session->ctrl_fd, vec, 2); + else + rc = ipc->writev(0, vec, 2); if (timedout) { log_error("socket %d write timed out", conn->socket_fd); @@ -394,7 +401,8 @@ iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, } if (conn->kernel_io) { - if (conn->send_pdu_end(session->ctrl_fd, session, conn)) { + if (conn->send_pdu_end(session->transport_handle, conn->handle, + &rc)) { ret = 0; goto done; } @@ -412,7 +420,7 @@ iscsi_send_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, } int -iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, +iscsi_io_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, int hdr_digest, char *data, int max_data_length, int data_digest, int timeout) { @@ -447,7 +455,7 @@ iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, timedout = 0; alarm(timeout); } else { - if (conn->recv_pdu_begin(session->ctrl_fd, conn, + if (conn->recv_pdu_begin(session->ctrl_fd, conn->handle, conn->recv_handle, &pdu_handle, &pdu_size)) { failed = 1; goto done; @@ -456,8 +464,11 @@ iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, /* read a response header */ do { - rlen = ctldev_read(session->ctrl_fd, header, - sizeof (*hdr) - h_bytes); + if (!conn->kernel_io) + rlen = read(session->ctrl_fd, header, + sizeof (*hdr) - h_bytes); + else + rlen = ipc->read(header, sizeof (*hdr) - h_bytes); if (timedout) { log_error("socket %d header read timed out", conn->socket_fd); @@ -510,8 +521,11 @@ iscsi_recv_pdu(iscsi_conn_t *conn, struct iscsi_hdr *hdr, /* read the rest into our buffer */ d_bytes = 0; while (d_bytes < dlength) { - rlen = ctldev_read(session->ctrl_fd, data + d_bytes, - dlength - d_bytes); + if (!conn->kernel_io) + rlen = read(session->ctrl_fd, data + d_bytes, + dlength - d_bytes); + else + rlen = ipc->read(data + d_bytes, dlength - d_bytes); if (timedout) { log_error("socket %d data read timed out", conn->socket_fd); @@ -603,7 +617,8 @@ done: sigaction(SIGALRM, &old, NULL); } else { /* finalyze receive transaction */ - if (conn->recv_pdu_end(session->ctrl_fd, conn, pdu_handle)) { + if (conn->recv_pdu_end(session->ctrl_fd, (ulong_t)conn, + pdu_handle)) { failed = 1; } conn->send_pdu_timer_remove(conn); diff --git a/usr/ioctl.c b/usr/ioctl.c deleted file mode 100644 index 2a34fea..0000000 --- a/usr/ioctl.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - * iSCSI Ioctl and SysFS control - * - * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman - * maintained by open-iscsi@@googlegroups.com - * - * 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. - * - * See the file COPYING included with this distribution for more details. - */ - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#include <sys/types.h> -#include <sys/stat.h> - -#include "iscsi_u.h" -#include "iscsid.h" -#include "log.h" - -#define CTL_DEVICE "/dev/iscsictl" -#define SYSFS_ROOT "/sysfs/class/iscsi" - -static int ctrl_fd; - -int -ctldev_read(iscsi_conn_t *conn, char *data, int count) -{ - return read(ctrl_fd, data, count); -} - -int -ctldev_writev(iscsi_conn_t *conn, struct iovec *iovp, int count) -{ - return writev(ctrl_fd, iovp, count); -} - -int -ksession_create(iscsi_session_t *session) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_CREATE_SESSION; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.c_session.session_handle = (ulong_t)session; - ev.u.c_session.sid = session->id; - ev.u.c_session.initial_cmdsn = session->nrec.session.initial_cmdsn; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_CREATE_SESSION, &ev)) < 0) { - log_error("can't create session with id = %d (%d)", - session->id, errno); - return rc; - } - - session->handle = ev.r.handle; - log_debug(3, "created new iSCSI session, handle 0x%p", - (void*)session->handle); - - return 0; -} - -int -ksession_destroy(iscsi_session_t *session) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_DESTROY_SESSION; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.d_session.session_handle = session->handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_DESTROY_SESSION, &ev)) < 0) { - log_error("can't destroy session with id = %d (%d)", - session->id, errno); - return rc; - } - - log_warning("destroyed iSCSI session, handle 0x%p", - (void*)session->handle); - - return 0; -} - -int -ksession_cnx_create(iscsi_session_t *session, iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_CREATE_CNX; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.c_cnx.session_handle = session->handle; - ev.u.c_cnx.cnx_handle = (ulong_t)conn; - ev.u.c_cnx.socket_fd = conn->socket_fd; - ev.u.c_cnx.cid = conn->id; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_CREATE_CNX, &ev)) < 0) { - log_error("can't create cnx with id = %d (%d)", - conn->id, errno); - return rc; - } - - conn->handle = ev.r.handle; - log_debug(3, "created new iSCSI connection, handle 0x%p", - (void*)conn->handle); - return 0; -} - -int -ksession_cnx_destroy(iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_DESTROY_CNX; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.d_cnx.cnx_handle = conn->handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_DESTROY_CNX, &ev)) < 0) { - log_error("can't destroy cnx with id = %d (%d)", - conn->id, errno); - return rc; - } - - log_warning("destroyed iSCSI connection, handle 0x%p", - (void*)conn->handle); - return 0; -} - -int -ksession_cnx_bind(iscsi_session_t *session, iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_BIND_CNX; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.b_cnx.session_handle = session->handle; - ev.u.b_cnx.cnx_handle = conn->handle; - ev.u.b_cnx.is_leading = (conn->id == 0); - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_BIND_CNX, &ev)) < 0) { - log_error("can't bind a cnx with id = %d (%d), retcode %d", - conn->id, errno, ev.r.retcode); - return rc; - } - - log_debug(3, "binded iSCSI connection (handle 0x%p) to " - "session (handle 0x%p)", (void*)conn->handle, - (void*)session->handle); - return 0; -} - -int -ksession_send_pdu_begin(iscsi_session_t *session, iscsi_conn_t *conn, - int hdr_size, int data_size) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_SEND_PDU_BEGIN; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.sp_begin.cnx_handle = conn->handle; - ev.u.sp_begin.hdr_size = hdr_size; - ev.u.sp_begin.data_size = data_size; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_SEND_PDU_BEGIN, &ev)) < 0) { - log_error("can't initiate send PDU operation for cnx with " - "id = %d (%d), retcode %d", - conn->id, errno, ev.r.retcode); - return rc; - } - - log_debug(3, "send PDU began for hdr %d bytes and data %d bytes", - hdr_size, data_size); - return 0; -} - -int -ksession_send_pdu_end(iscsi_session_t *session, iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_SEND_PDU_END; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.sp_end.cnx_handle = conn->handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_SEND_PDU_END, &ev)) < 0) { - log_error("can't finish send PDU operation for cnx with " - "id = %d (%d), retcode %d", - conn->id, errno, ev.r.retcode); - return rc; - } - - log_debug(3, "send PDU finished for cnx (handle %p)", - (void*)conn->handle); - return 0; -} - -int -ksession_set_param(iscsi_conn_t *conn, iscsi_param_e param, uint32_t value) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_SET_PARAM; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.set_param.cnx_handle = (ulong_t)conn->handle; - ev.u.set_param.param = param; - ev.u.set_param.value = value; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_SET_PARAM, &ev)) < 0) { - log_error("can't set operational parameter %d for cnx with " - "id = %d (%d)", param, conn->id, errno); - return rc; - } - - log_debug(3, "set operational parameter %d to %u", - param, value); - - return 0; -} - -int -ksession_stop_cnx(iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_STOP_CNX; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.stop_cnx.cnx_handle = conn->handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_STOP_CNX, &ev)) < 0) { - log_error("can't stop connection 0x%p with " - "id = %d (%d)", (void*)conn->handle, - conn->id, errno); - return rc; - } - - log_debug(3, "connection 0x%p is stopped now", - (void*)conn->handle); - return 0; -} - -int -ksession_start_cnx(iscsi_conn_t *conn) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_START_CNX; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.start_cnx.cnx_handle = conn->handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_START_CNX, &ev)) < 0) { - log_error("can't start connection 0x%p with " - "id = %d (%d)", (void*)conn->handle, - conn->id, errno); - return rc; - } - - log_debug(3, "connection 0x%p is operational now", - (void*)conn->handle); - return 0; -} - -int -ksession_recv_pdu_begin(iscsi_conn_t *conn, ulong_t recv_handle, - ulong_t *pdu_handle, int *pdu_size) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_RECV_PDU_BEGIN; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.rp_begin.cpcnx_handle = (ulong_t)conn; - ev.u.rp_begin.recv_handle = recv_handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_RECV_PDU_BEGIN, &ev)) < 0) { - log_error("can't initiate recv PDU operation for cnx with " - "id = %d (%d)", conn->id, errno); - return rc; - } - - *pdu_handle = ev.r.rp_begin.pdu_handle; - *pdu_size = ev.r.rp_begin.pdu_size; - - log_debug(3, "recv PDU began, pdu handle 0x%p size %d", - (void*)*pdu_handle, *pdu_size); - return 0; -} - -int -ksession_recv_pdu_end(iscsi_conn_t *conn, ulong_t pdu_handle) -{ - int rc; - iscsi_uevent_t ev; - - memset(&ev, 0, sizeof(iscsi_uevent_t)); - - ev.type = ISCSI_UEVENT_RECV_PDU_END; - ev.provider_id = 0; /* FIXME: hardcoded */ - ev.u.rp_end.cpcnx_handle = (ulong_t)conn; - ev.u.rp_end.pdu_handle = pdu_handle; - - if ((rc = ioctl(ctrl_fd, ISCSI_UEVENT_RECV_PDU_END, &ev)) < 0) { - log_error("can't finish recv PDU operation for cnx with " - "id = %d (%d)", conn->id, errno); - return rc; - } - - log_debug(3, "recv PDU finished for pdu handle 0x%p", - (void*)pdu_handle); - return 0; -} - -int -ctldev_handle(int fd) -{ - int rc; - iscsi_uevent_t ev; - struct qelem *item; - iscsi_session_t *session = NULL; - iscsi_conn_t *conn = NULL; - - if ((rc = ioctl(fd, ISCSI_UEVENT_RECV_REQ, &ev)) < 0) { - log_error("can't fetch recv event information " - "(%d), retcode %d", errno, rc); - return rc; - } - - /* verify connection */ - item = provider[0].sessions.q_forw; - while (item != &provider[0].sessions) { - int i; - session = (iscsi_session_t *)item; - for (i=0; i<ISCSI_CNX_MAX; i++) { - if (&session->cnx[i] == (iscsi_conn_t*) - ev.r.recv_req.cnx_handle) { - conn = &session->cnx[i]; - break; - } - } - item = item->q_forw; - } - - if (ev.type == ISCSI_KEVENT_RECV_PDU) { - if (conn == NULL) { - log_error("could not verify connection 0x%p for " - "event RECV_PDU", conn); - return -ENXIO; - } - - /* produce an event, so session manager will handle */ - queue_produce(session->queue, EV_CNX_RECV_PDU, conn, - sizeof(ulong_t), (void*)&ev.r.recv_req.recv_handle); - actor_schedule(&session->mainloop); - - } else if (ev.type == ISCSI_KEVENT_CNX_ERROR) { - if (conn == NULL) { - log_error("could not verify connection 0x%p for " - "event CNX_ERR", conn); - return -ENXIO; - } - - /* produce an event, so session manager will handle */ - queue_produce(session->queue, EV_CNX_ERROR, conn, - sizeof(ulong_t), (void*)&ev.r.recv_req.recv_handle); - actor_schedule(&session->mainloop); - - } else { - log_error("unknown kernel event %d", ev.type); - } - - return 0; -} - -int ctldev_open(void) -{ - FILE *f = NULL; - char devname[256]; - char buf[256]; - int devn; - int ctlfd; - - f = fopen("/proc/devices", "r"); - if (!f) { - log_error("cannot open control path to the driver"); - return -1; - } - - devn = 0; - while (!feof(f)) { - if (!fgets(buf, sizeof (buf), f)) { - break; - } - if (sscanf(buf, "%d %s", &devn, devname) != 2) { - continue; - } - if (!strcmp(devname, "iscsictl")) { - break; - } - devn = 0; - } - - fclose(f); - if (!devn) { - log_error("cannot find iscsictl in /proc/devices - " - "make sure the module is loaded"); - return -1; - } - - unlink(CTL_DEVICE); - if (mknod(CTL_DEVICE, (S_IFCHR | 0600), (devn << 8))) { - log_error("cannot create %s %d", CTL_DEVICE, errno); - return -1; - } - - ctlfd = open(CTL_DEVICE, O_RDWR); - if (ctlfd < 0) { - log_error("cannot open %s %d", CTL_DEVICE, errno); - return -1; - } - - log_debug(1, CTL_DEVICE " is opened!"); - - return ctlfd; -} - -void -ctldev_close(int fd) -{ - close(fd); -} diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c index 9223be0..499ab19 100644 --- a/usr/iscsiadm.c +++ b/usr/iscsiadm.c @@ -35,9 +35,10 @@ #include "initiator.h" #include "iscsiadm.h" #include "log.h" -#include "ipc.h" +#include "mgmt_ipc.h" #include "idbm.h" +struct iscsi_ipc *ipc = NULL; /* dummy */ static char program_name[] = "iscsiadm"; char initiator_name[TARGET_NAME_MAXLEN]; @@ -220,19 +221,6 @@ iscsid_connect(void) return fd; } -int -ctldev_read(int ctrl_fd, char *data, int count) -{ - return read(ctrl_fd, data, count); -} - -int -ctldev_writev(int ctrl_fd, enum iscsi_uevent_e type, struct iovec *iovp, - int count) -{ - return writev(ctrl_fd, iovp, count); -} - static int iscsid_request(int fd, iscsiadm_req_t *req) { @@ -292,7 +280,7 @@ session_login(int rid, node_rec_t *rec) iscsiadm_rsp_t rsp; memset(&req, 0, sizeof(req)); - req.command = IPC_SESSION_LOGIN; + req.command = MGMT_IPC_SESSION_LOGIN; req.u.session.rid = rid; return do_iscsid(&req, &rsp); @@ -305,7 +293,7 @@ session_logout(int rid, node_rec_t *rec) iscsiadm_rsp_t rsp; memset(&req, 0, sizeof(req)); - req.command = IPC_SESSION_LOGOUT; + req.command = MGMT_IPC_SESSION_LOGOUT; req.u.session.rid = rid; return do_iscsid(&req, &rsp); @@ -323,7 +311,7 @@ session_activelist(idbm_t *db) iscsiadm_rsp_t rsp; memset(&req, 0, sizeof(req)); - req.command = IPC_SESSION_ACTIVELIST; + req.command = MGMT_IPC_SESSION_ACTIVELIST; rc = do_iscsid(&req, &rsp); if (rc) diff --git a/usr/iscsid.c b/usr/iscsid.c index bb717e9..6ed3fa5 100644 --- a/usr/iscsid.c +++ b/usr/iscsid.c @@ -32,7 +32,8 @@ #include "iscsid.h" #include "actor.h" -#include "ipc.h" +#include "mgmt_ipc.h" +#include "iscsi_ipc.h" #include "log.h" #define POLL_CTRL 0 @@ -45,7 +46,7 @@ struct iscsi_daemon_config *dconfig = &daemon_config; iscsi_provider_t provider[ISCSI_TRANSPORT_MAX]; static char program_name[] = "iscsid"; -int control_fd, ipc_fd; +int control_fd, mgmt_ipc_fd; static struct pollfd poll_array[POLL_MAX]; static struct option const long_options[] = { @@ -86,7 +87,7 @@ void event_loop(void) poll_array[POLL_CTRL].fd = control_fd; poll_array[POLL_CTRL].events = POLLIN; - poll_array[POLL_IPC].fd = ipc_fd; + poll_array[POLL_IPC].fd = mgmt_ipc_fd; poll_array[POLL_IPC].events = POLLIN; while (1) { @@ -108,10 +109,10 @@ void event_loop(void) log_debug(6, "detected poll event %d", res); if (poll_array[POLL_CTRL].revents) - ctldev_handle(control_fd); + ipc->ctldev_handle(); if (poll_array[POLL_IPC].revents) - ipc_handle(ipc_fd); + mgmt_ipc_handle(mgmt_ipc_fd); } } @@ -123,7 +124,7 @@ int trans_sync(void) int i, found = 0; struct iscsi_uevent ev; - if (ktrans_list(control_fd, &ev)) + if (ipc->trans_list(&ev)) return -1; for (i = 0; i < ISCSI_TRANSPORT_MAX; i++) { @@ -221,7 +222,7 @@ int main(int argc, char *argv[]) /* initialize logger */ log_init(program_name); - if ((ipc_fd = ipc_listen()) < 0) { + if ((mgmt_ipc_fd = mgmt_ipc_listen()) < 0) { exit(-1); } @@ -244,7 +245,7 @@ int main(int argc, char *argv[]) exit(0); } - if ((control_fd = ctldev_open()) < 0) { + if ((control_fd = ipc->ctldev_open()) < 0) { exit(-1); } @@ -263,7 +264,7 @@ int main(int argc, char *argv[]) dup2(0, 2); setsid(); } else { - if ((control_fd = ctldev_open()) < 0) { + if ((control_fd = ipc->ctldev_open()) < 0) { exit(-1); } } diff --git a/usr/iscsid.h b/usr/iscsid.h index b009a1d..8ce7202 100644 --- a/usr/iscsid.h +++ b/usr/iscsid.h @@ -36,13 +36,8 @@ typedef struct iscsi_pdu { unsigned int datasize; } iscsi_pdu_t; -/* ctldev: Ioctl/IPC/NETLINK/etc */ -extern int ctldev_open(void); -extern void ctldev_close(int fd); -extern int ctldev_handle(int fd); -extern int ctldev_writev(int fd, enum iscsi_uevent_e type, struct iovec *iov, - int count); -extern int ctldev_read(int fd, char *data, int count); +/* IPC API */ +extern struct iscsi_ipc *ipc; /* iscsid.c: daemon config */ struct iscsi_daemon_config { diff --git a/usr/login.c b/usr/login.c index 3b2f0a2..6adf419 100644 --- a/usr/login.c +++ b/usr/login.c @@ -1352,7 +1352,7 @@ iscsi_login_req(iscsi_session_t *session, iscsi_login_context_t *c) } /* send a PDU to the target */ - if (!iscsi_send_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, + if (!iscsi_io_send_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, c->data, ISCSI_DIGEST_NONE, c->timeout)) { /* * FIXME: caller might want us to distinguish I/O @@ -1383,7 +1383,7 @@ iscsi_login_rsp(iscsi_session_t *session, iscsi_login_context_t *c) iscsi_conn_t *conn = &session->cnx[c->cid]; /* read the target's response into the same buffer */ - if (!iscsi_recv_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, c->data, + if (!iscsi_io_recv_pdu(conn, &c->pdu, ISCSI_DIGEST_NONE, c->data, c->max_data_length, ISCSI_DIGEST_NONE, c->timeout)) { /* diff --git a/usr/ipc.c b/usr/mgmt_ipc.c index 93473d1..af84822 100644 --- a/usr/ipc.c +++ b/usr/mgmt_ipc.c @@ -2,7 +2,7 @@ * iSCSI Administrator Utility Socket Interface * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman - * maintained by open-iscsi@@googlegroups.com + * maintained by open-iscsi@googlegroups.com * * Originally based on: * (C) 2004 FUJITA Tomonori <tomof@acm.org> @@ -32,11 +32,11 @@ #include "iscsid.h" #include "idbm.h" -#include "ipc.h" +#include "mgmt_ipc.h" #include "log.h" int -ipc_listen(void) +mgmt_ipc_listen(void) { int fd, err; struct sockaddr_un addr; @@ -70,43 +70,43 @@ ipc_listen(void) } void -ipc_close(int fd) +mgmt_ipc_close(int fd) { } -static ipc_err_e -ipc_node_read(int rid, node_rec_t *rec) +static mgmt_ipc_err_e +mgmt_ipc_node_read(int rid, node_rec_t *rec) { idbm_t *db; db = idbm_init(CONFIG_FILE); if (!db) { - return IPC_ERR_IDBM_FAILURE; + return MGMT_IPC_ERR_IDBM_FAILURE; } if (idbm_node_read(db, rid, rec)) { log_error("node record [%06x] not found!", rid); - return IPC_ERR_NOT_FOUND; + return MGMT_IPC_ERR_NOT_FOUND; } idbm_terminate(db); return 0; } -static ipc_err_e -ipc_session_login(queue_task_t *qtask, int rid) +static mgmt_ipc_err_e +mgmt_ipc_session_login(queue_task_t *qtask, int rid) { - ipc_err_e rc; + mgmt_ipc_err_e rc; node_rec_t rec; - if ((rc = ipc_node_read(rid, &rec))) + if ((rc = mgmt_ipc_node_read(rid, &rec))) return rc; return session_login_task(&rec, qtask); } -static ipc_err_e -ipc_session_activelist(queue_task_t *qtask, iscsiadm_rsp_t *rsp) +static mgmt_ipc_err_e +mgmt_ipc_session_activelist(queue_task_t *qtask, iscsiadm_rsp_t *rsp) { iscsi_session_t *session; struct qelem *item; @@ -121,42 +121,42 @@ ipc_session_activelist(queue_task_t *qtask, iscsiadm_rsp_t *rsp) item = item->q_forw; } - return IPC_OK; + return MGMT_IPC_OK; } -static ipc_err_e -ipc_session_logout(queue_task_t *qtask, int rid) +static mgmt_ipc_err_e +mgmt_ipc_session_logout(queue_task_t *qtask, int rid) { - ipc_err_e rc; + mgmt_ipc_err_e rc; node_rec_t rec; iscsi_session_t *session; - if ((rc = ipc_node_read(rid, &rec))) + if ((rc = mgmt_ipc_node_read(rid, &rec))) return rc; if (!(session = session_find_by_rec(&rec))) { log_error("session with corresponding record [%06x] " "not found!", rid); - return IPC_ERR_NOT_FOUND; + return MGMT_IPC_ERR_NOT_FOUND; } return session_logout_task(session, qtask); } -static ipc_err_e -ipc_conn_add(queue_task_t *qtask, int rid, int cid) +static mgmt_ipc_err_e +mgmt_ipc_conn_add(queue_task_t *qtask, int rid, int cid) { - return IPC_ERR; + return MGMT_IPC_ERR; } -static ipc_err_e -ipc_conn_remove(queue_task_t *qtask, int rid, int cid) +static mgmt_ipc_err_e +mgmt_ipc_conn_remove(queue_task_t *qtask, int rid, int cid) { - return IPC_ERR; + return MGMT_IPC_ERR; } int -ipc_handle(int accept_fd) +mgmt_ipc_handle(int accept_fd) { struct sockaddr addr; struct ucred cred; @@ -178,12 +178,12 @@ ipc_handle(int accept_fd) len = sizeof(cred); if ((rc = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &len)) < 0) { - rsp.err = IPC_ERR_TCP_FAILURE; + rsp.err = MGMT_IPC_ERR_TCP_FAILURE; goto err; } if (cred.uid || cred.gid) { - rsp.err = IPC_ERR_TCP_FAILURE; + rsp.err = MGMT_IPC_ERR_TCP_FAILURE; rc = -EPERM; goto err; } @@ -199,29 +199,31 @@ ipc_handle(int accept_fd) qtask = calloc(1, sizeof(queue_task_t)); if (!qtask) { - rsp.err = IPC_ERR_NOMEM; + rsp.err = MGMT_IPC_ERR_NOMEM; rc = -ENOMEM; goto err; } memcpy(&qtask->u.login.req, &req, sizeof(iscsiadm_req_t)); - qtask->u.login.ipc_fd = fd; + qtask->u.login.mgmt_ipc_fd = fd; switch(req.command) { - case IPC_SESSION_LOGIN: - rsp.err = ipc_session_login(qtask, req.u.session.rid); + case MGMT_IPC_SESSION_LOGIN: + rsp.err = mgmt_ipc_session_login(qtask, req.u.session.rid); break; - case IPC_SESSION_LOGOUT: - rsp.err = ipc_session_logout(qtask, req.u.session.rid); + case MGMT_IPC_SESSION_LOGOUT: + rsp.err = mgmt_ipc_session_logout(qtask, req.u.session.rid); break; - case IPC_SESSION_ACTIVELIST: - rsp.err = ipc_session_activelist(qtask, &rsp); + case MGMT_IPC_SESSION_ACTIVELIST: + rsp.err = mgmt_ipc_session_activelist(qtask, &rsp); immrsp = 1; break; - case IPC_CONN_ADD: - rsp.err = ipc_conn_add(qtask, req.u.conn.rid, req.u.conn.cid); + case MGMT_IPC_CONN_ADD: + rsp.err = mgmt_ipc_conn_add(qtask, req.u.conn.rid, + req.u.conn.cid); break; - case IPC_CONN_REMOVE: - rsp.err = ipc_conn_remove(qtask,req.u.conn.rid,req.u.conn.cid); + case MGMT_IPC_CONN_REMOVE: + rsp.err = mgmt_ipc_conn_remove(qtask, req.u.conn.rid, + req.u.conn.cid); break; default: log_error("unknown request: %s(%d) %u", @@ -229,7 +231,7 @@ ipc_handle(int accept_fd) break; } - if (rsp.err == IPC_OK && !immrsp) + if (rsp.err == MGMT_IPC_OK && !immrsp) return 0; err: diff --git a/usr/ipc.h b/usr/mgmt_ipc.h index 19c4901..7c2f7da 100644 --- a/usr/ipc.h +++ b/usr/mgmt_ipc.h @@ -1,8 +1,8 @@ /* - * iSCSI Daemon/Admin IPC + * iSCSI Daemon/Admin Management IPC * * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman - * maintained by open-iscsi@@googlegroups.com + * maintained by open-iscsi@googlegroups.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -16,37 +16,37 @@ * * See the file COPYING included with this distribution for more details. */ -#ifndef IPC_H -#define IPC_H +#ifndef MGMT_IPC_H +#define MGMT_IPC_H #include "types.h" #define ISCSIADM_NAMESPACE "ISCSIADM_ABSTRACT_NAMESPACE" -typedef enum ipc_err { - IPC_OK = 0, - IPC_ERR = 1, - IPC_ERR_NOT_FOUND = 2, - IPC_ERR_NOMEM = 3, - IPC_ERR_TCP_FAILURE = 4, - IPC_ERR_LOGIN_FAILURE = 5, - IPC_ERR_IDBM_FAILURE = 6, - IPC_ERR_INVAL = 7, - IPC_ERR_TCP_TIMEOUT = 8, - IPC_ERR_INTERNAL = 9, - IPC_ERR_LOGOUT_FAILURE = 10, - IPC_ERR_PDU_TIMEOUT = 11, - IPC_ERR_TRANS_NOT_FOUND = 12, -} ipc_err_e; +typedef enum mgmt_ipc_err { + MGMT_IPC_OK = 0, + MGMT_IPC_ERR = 1, + MGMT_IPC_ERR_NOT_FOUND = 2, + MGMT_IPC_ERR_NOMEM = 3, + MGMT_IPC_ERR_TCP_FAILURE = 4, + MGMT_IPC_ERR_LOGIN_FAILURE = 5, + MGMT_IPC_ERR_IDBM_FAILURE = 6, + MGMT_IPC_ERR_INVAL = 7, + MGMT_IPC_ERR_TCP_TIMEOUT = 8, + MGMT_IPC_ERR_INTERNAL = 9, + MGMT_IPC_ERR_LOGOUT_FAILURE = 10, + MGMT_IPC_ERR_PDU_TIMEOUT = 11, + MGMT_IPC_ERR_TRANS_NOT_FOUND = 12, +} mgmt_ipc_err_e; typedef enum iscsiadm_cmd { - IPC_UNKNOWN = 0, - IPC_SESSION_LOGIN = 1, - IPC_SESSION_LOGOUT = 2, - IPC_SESSION_ACTIVELIST = 3, - IPC_SESSION_ACTIVESTAT = 4, - IPC_CONN_ADD = 5, - IPC_CONN_REMOVE = 6, + MGMT_IPC_UNKNOWN = 0, + MGMT_IPC_SESSION_LOGIN = 1, + MGMT_IPC_SESSION_LOGOUT = 2, + MGMT_IPC_SESSION_ACTIVELIST = 3, + MGMT_IPC_SESSION_ACTIVESTAT = 4, + MGMT_IPC_CONN_ADD = 5, + MGMT_IPC_CONN_REMOVE = 6, } iscsiadm_cmd_e; /* IPC Request */ @@ -68,20 +68,20 @@ typedef struct iscsiadm_req { /* IPC Response */ typedef struct iscsiadm_rsp { iscsiadm_cmd_e command; - ipc_err_e err; + mgmt_ipc_err_e err; union { struct msg_activelist { -#define IPC_ACTIVELIST_MAX 64 - int sids[IPC_ACTIVELIST_MAX]; - int rids[IPC_ACTIVELIST_MAX]; +#define MGMT_IPC_ACTIVELIST_MAX 64 + int sids[MGMT_IPC_ACTIVELIST_MAX]; + int rids[MGMT_IPC_ACTIVELIST_MAX]; int cnt; } activelist; } u; } iscsiadm_rsp_t; -int ipc_handle(int accept_fd); -int ipc_listen(void); -void ipc_close(int fd); +int mgmt_ipc_handle(int accept_fd); +int mgmt_ipc_listen(void); +void mgmt_ipc_close(int fd); -#endif /* IPC_H */ +#endif /* MGMT_IPC_H */ diff --git a/usr/netlink.c b/usr/netlink.c index 004fde7..0598240 100644 --- a/usr/netlink.c +++ b/usr/netlink.c @@ -31,7 +31,9 @@ #include "iscsi_ifev.h" #include "iscsid.h" #include "log.h" +#include "iscsi_ipc.h" +static int ctrl_fd; static struct sockaddr_nl src_addr, dest_addr; static void *xmitbuf = NULL; static int xmitlen = 0; @@ -41,6 +43,8 @@ static void *nlm_sendbuf; static void *nlm_recvbuf; static void *pdu_sendbuf; +static int ctldev_handle(void); + #define NLM_BUF_DEFAULT_MAX \ (NLMSG_SPACE(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH + \ sizeof(struct iscsi_hdr))) @@ -48,23 +52,27 @@ static void *pdu_sendbuf; #define PDU_SENDBUF_DEFAULT_MAX \ (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH + sizeof(struct iscsi_hdr)) -int -ctldev_read(int ctrl_fd, char *data, int count) +static int +kread(char *data, int count) { + log_debug(7, "in %s", __FUNCTION__); + memcpy(data, recvbuf + recvlen, count); recvlen += count; return count; } static int -nl_read(int ctrl_fd, struct nlmsghdr *nl, int flags) +nl_read(int ctrl_fd, char *data, int size, int flags) { int rc; struct iovec iov; struct msghdr msg; - iov.iov_base = nl; - iov.iov_len = sizeof(*nl); + log_debug(7, "in %s", __FUNCTION__); + + iov.iov_base = data; + iov.iov_len = size; memset(&msg, 0, sizeof(msg)); msg.msg_name= (void*)&src_addr; @@ -84,6 +92,8 @@ nlpayload_read(int ctrl_fd, char *data, int count, int flags) struct iovec iov; struct msghdr msg; + log_debug(7, "in %s", __FUNCTION__); + iov.iov_base = nlm_recvbuf; iov.iov_len = NLMSG_SPACE(count); memset(iov.iov_base, 0, iov.iov_len); @@ -126,9 +136,8 @@ nlpayload_read(int ctrl_fd, char *data, int count, int flags) return rc; } -int -ctldev_writev(int ctrl_fd, enum iscsi_uevent_e type, struct iovec *iovp, - int count) +static int +kwritev(enum iscsi_uevent_e type, struct iovec *iovp, int count) { int i, rc; struct nlmsghdr *nlh; @@ -136,6 +145,8 @@ ctldev_writev(int ctrl_fd, enum iscsi_uevent_e type, struct iovec *iovp, struct iovec iov; int datalen = 0; + log_debug(7, "in %s", __FUNCTION__); + for (i = 0; i < count; i++) { datalen += iovp[i].iov_len; } @@ -209,7 +220,7 @@ ctldev_writev(int ctrl_fd, enum iscsi_uevent_e type, struct iovec *iovp, } /* - * __ksession_call() should never block. Therefore + * __kipc_call() should never block. Therefore * Netlink's xmit logic is serialized. This means we do not allocate on * xmit path. Instead we reuse nlm_sendbuf buffer. * @@ -231,17 +242,19 @@ ctldev_writev(int ctrl_fd, enum iscsi_uevent_e type, struct iovec *iovp, * cleanup. (Dima) */ static int -__ksession_call(int ctrl_fd, void *iov_base, int iov_len) +__kipc_call(void *iov_base, int iov_len) { int rc; struct iovec iov; struct iscsi_uevent *ev = iov_base; enum iscsi_uevent_e type = ev->type; + log_debug(7, "in %s", __FUNCTION__); + iov.iov_base = iov_base; iov.iov_len = iov_len; - rc = ctldev_writev(ctrl_fd, type, &iov, 1); + rc = kwritev(type, &iov, 1); do { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, @@ -265,7 +278,7 @@ __ksession_call(int ctrl_fd, void *iov_base, int iov_len) * - CNX_ERROR * - RECV_PDU */ - ctldev_handle(ctrl_fd); + ctldev_handle(); } else { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), 0)) < 0) { @@ -278,149 +291,141 @@ __ksession_call(int ctrl_fd, void *iov_base, int iov_len) return rc; } -int -ksession_create(int ctrl_fd, iscsi_session_t *session) +static int +kcreate_session(uint64_t transport_handle, ulong_t cp_snx, + uint32_t initial_cmdsn, ulong_t *out_handle, int *out_sid) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_CREATE_SESSION; - ev.transport_handle = session->transport_handle; - ev.u.c_session.session_handle = (ulong_t)session; - ev.u.c_session.initial_cmdsn = session->nrec.session.initial_cmdsn; + ev.transport_handle = transport_handle; + ev.u.c_session.session_handle = cp_snx; + ev.u.c_session.initial_cmdsn = initial_cmdsn; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't create session with id = %d (%d)", - session->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } if (!ev.r.c_session_ret.handle || ev.r.c_session_ret.sid < 0) return -EIO; - session->handle = ev.r.c_session_ret.handle; - session->id = ev.r.c_session_ret.sid; - log_debug(3, "created new iSCSI session, handle 0x%p", - (void*)session->handle); + *out_handle = ev.r.c_session_ret.handle; + *out_sid = ev.r.c_session_ret.sid; return 0; } -int -ksession_destroy(int ctrl_fd, iscsi_session_t *session) +static int +kdestroy_session(uint64_t transport_handle, ulong_t dp_snx, int sid) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_DESTROY_SESSION; - ev.transport_handle = session->transport_handle; - ev.u.d_session.session_handle = session->handle; - ev.u.d_session.sid = session->id; + ev.transport_handle = transport_handle; + ev.u.d_session.session_handle = dp_snx; + ev.u.d_session.sid = sid; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't destroy session with id = %d (%d)", - session->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - log_warning("destroyed iSCSI session, handle 0x%p", - (void*)session->handle); - return 0; } -int -ksession_cnx_create(int ctrl_fd, iscsi_session_t *session, iscsi_conn_t *conn) +static int +kcreate_cnx(uint64_t transport_handle, ulong_t dp_snx, ulong_t cp_cnx, + uint32_t sid, uint32_t cid, ulong_t *out_handle) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_CREATE_CNX; - ev.transport_handle = session->transport_handle; - ev.u.c_cnx.session_handle = session->handle; - ev.u.c_cnx.cnx_handle = (ulong_t)conn; - ev.u.c_cnx.cid = conn->id; - ev.u.c_cnx.sid = session->id; - - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't create cnx with id = %d (%d)", - conn->id, errno); + ev.transport_handle = transport_handle; + ev.u.c_cnx.session_handle = dp_snx; + ev.u.c_cnx.cnx_handle = cp_cnx; + ev.u.c_cnx.cid = cid; + ev.u.c_cnx.sid = sid; + + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } if (!ev.r.handle) return -EIO; - conn->handle = ev.r.handle; - log_debug(3, "created new iSCSI connection, handle 0x%p", - (void*)conn->handle); + *out_handle = ev.r.handle; return 0; } -int -ksession_cnx_destroy(int ctrl_fd, iscsi_conn_t *conn) +static int +kdestroy_cnx(uint64_t transport_handle, ulong_t dp_cnx, int cid) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_DESTROY_CNX; - ev.transport_handle = conn->session->transport_handle; - ev.u.d_cnx.cnx_handle = conn->handle; - ev.u.d_cnx.cid = conn->id; + ev.transport_handle = transport_handle; + ev.u.d_cnx.cnx_handle = dp_cnx; + ev.u.d_cnx.cid = cid; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't destroy cnx with id = %d (%d)", - conn->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - log_warning("destroyed iSCSI connection, handle 0x%p", - (void*)conn->handle); return 0; } -int -ksession_cnx_bind(int ctrl_fd, iscsi_session_t *session, iscsi_conn_t *conn) +static int +kbind_cnx(uint64_t transport_handle, ulong_t dp_snx, ulong_t dp_cnx, + uint32_t transport_fd, int is_leading, int *retcode) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_BIND_CNX; - ev.transport_handle = session->transport_handle; - ev.u.b_cnx.session_handle = session->handle; - ev.u.b_cnx.cnx_handle = conn->handle; - ev.u.b_cnx.transport_fd = conn->socket_fd; - ev.u.b_cnx.is_leading = (conn->id == 0); - - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't bind a cnx with id = %d (%d)", - conn->id, errno); + ev.transport_handle = transport_handle; + ev.u.b_cnx.session_handle = dp_snx; + ev.u.b_cnx.cnx_handle = dp_cnx; + ev.u.b_cnx.transport_fd = transport_fd; + ev.u.b_cnx.is_leading = is_leading; + + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - if (!ev.r.retcode) { - log_debug(3, "bound iSCSI connection (handle 0x%p) to " - "session (handle 0x%p)", (void*)conn->handle, - (void*)session->handle); - } else { - log_error("can't bind a cnx with id = %d, retcode %d", - conn->id, ev.r.retcode); - } - return ev.r.retcode; + + *retcode = ev.r.retcode; + + return 0; } -void ksession_send_pdu_begin(int ctrl_fd, iscsi_session_t *session, - iscsi_conn_t *conn, int hdr_size, int data_size) +static void +ksend_pdu_begin(uint64_t transport_handle, ulong_t dp_cnx, + int hdr_size, int data_size) { struct iscsi_uevent *ev; + log_debug(7, "in %s", __FUNCTION__); + if (xmitbuf) { log_error("send's begin state machine bug?"); exit(-EIO); @@ -432,8 +437,8 @@ void ksession_send_pdu_begin(int ctrl_fd, iscsi_session_t *session, ev = xmitbuf; memset(ev, 0, sizeof(*ev)); ev->type = ISCSI_UEVENT_SEND_PDU; - ev->transport_handle = session->transport_handle; - ev->u.send_pdu.cnx_handle = conn->handle; + ev->transport_handle = transport_handle; + ev->u.send_pdu.cnx_handle = dp_cnx; ev->u.send_pdu.hdr_size = hdr_size; ev->u.send_pdu.data_size = data_size; @@ -441,19 +446,21 @@ void ksession_send_pdu_begin(int ctrl_fd, iscsi_session_t *session, hdr_size, data_size); } -int -ksession_send_pdu_end(int ctrl_fd, iscsi_session_t *session, iscsi_conn_t *conn) +static int +ksend_pdu_end(uint64_t transport_handle, ulong_t dp_cnx, int *retcode) { int rc; struct iscsi_uevent *ev; struct iovec iov; + log_debug(7, "in %s", __FUNCTION__); + if (!xmitbuf) { log_error("send's end state machine bug?"); exit(-EIO); } ev = xmitbuf; - if (ev->u.send_pdu.cnx_handle != conn->handle) { + if (ev->u.send_pdu.cnx_handle != dp_cnx) { log_error("send's end state machine corruption?"); exit(-EIO); } @@ -461,119 +468,104 @@ ksession_send_pdu_end(int ctrl_fd, iscsi_session_t *session, iscsi_conn_t *conn) iov.iov_base = xmitbuf; iov.iov_len = xmitlen; - if ((rc = __ksession_call(ctrl_fd, xmitbuf, xmitlen)) < 0) + if ((rc = __kipc_call(xmitbuf, xmitlen)) < 0) goto err; - if (ev->r.retcode) + if (ev->r.retcode) { + *retcode = ev->r.retcode; goto err; + } if (ev->type != ISCSI_UEVENT_SEND_PDU) { log_error("bad event: bug on send_pdu_end?"); exit(-EIO); } - log_debug(3, "send PDU finished for cnx (handle %p)", - (void*)conn->handle); + log_debug(3, "send PDU finished for cnx (handle %p)", (void*)dp_cnx); xmitbuf = NULL; return 0; err: - log_error("can't finish send PDU operation for cnx with " - "id = %d (%d), retcode %d", - conn->id, errno, ev->r.retcode); xmitbuf = NULL; xmitlen = 0; return rc; } -int -ksession_set_param(int ctrl_fd, iscsi_conn_t *conn, enum iscsi_param param, - uint32_t value) +static int +kset_param(uint64_t transport_handle, ulong_t dp_cnx, + enum iscsi_param param, uint32_t value, int *retcode) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_SET_PARAM; - ev.transport_handle = conn->session->transport_handle; - ev.u.set_param.cnx_handle = (ulong_t)conn->handle; + ev.transport_handle = transport_handle; + ev.u.set_param.cnx_handle = dp_cnx; ev.u.set_param.param = param; ev.u.set_param.value = value; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't set operational parameter %d for cnx with " - "id = %d (%d)", param, conn->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - if (!ev.r.retcode) { - log_debug(3, "set operational parameter %d to %u", - param, value); - } else { - log_error("can't set operational parameter %d for cnx with " - "id = %d, retcode %d", param, conn->id, ev.r.retcode); - } - return ev.r.retcode; + *retcode = ev.r.retcode; + + return 0; } -int -ksession_stop_cnx(int ctrl_fd, iscsi_conn_t *conn, int flag) +static int +kstop_cnx(uint64_t transport_handle, ulong_t dp_cnx, int flag) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_STOP_CNX; - ev.transport_handle = conn->session->transport_handle; - ev.u.stop_cnx.cnx_handle = conn->handle; + ev.transport_handle = transport_handle; + ev.u.stop_cnx.cnx_handle = dp_cnx; ev.u.stop_cnx.flag = flag; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't stop connection 0x%p with " - "id = %d (%d)", (void*)conn->handle, - conn->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - log_debug(3, "connection 0x%p is stopped now", - (void*)conn->handle); return 0; } -int -ksession_start_cnx(int ctrl_fd, iscsi_conn_t *conn) +static int +kstart_cnx(uint64_t transport_handle, ulong_t dp_cnx, int *retcode) { int rc; struct iscsi_uevent ev; + log_debug(7, "in %s", __FUNCTION__); + memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_START_CNX; - ev.transport_handle = conn->session->transport_handle; - ev.u.start_cnx.cnx_handle = conn->handle; + ev.transport_handle = transport_handle; + ev.u.start_cnx.cnx_handle = dp_cnx; - if ((rc = __ksession_call(ctrl_fd, &ev, sizeof(ev))) < 0) { - log_error("can't start connection 0x%p with " - "id = %d (%d)", (void*)conn->handle, - conn->id, errno); + if ((rc = __kipc_call(&ev, sizeof(ev))) < 0) { return rc; } - if (!ev.r.retcode) { - log_debug(3, "connection 0x%p is operational now", - (void*)conn->handle); - } else { - log_error("can't start connection 0x%p with " - "id = %d, retcode %d", (void*)conn->handle, - conn->id, ev.r.retcode); - } - return ev.r.retcode; + + *retcode = ev.r.retcode; + return 0; } -int -ksession_recv_pdu_begin(int ctrl_fd, iscsi_conn_t *conn, ulong_t recv_handle, - ulong_t *pdu_handle, int *pdu_size) +static int +krecv_pdu_begin(uint64_t transport_handle, ulong_t dp_cnx, + ulong_t recv_handle, ulong_t *pdu_handle, int *pdu_size) { + log_debug(7, "in %s", __FUNCTION__); + if (recvbuf) { log_error("recv's begin state machine bug?"); return -EIO; @@ -588,9 +580,11 @@ ksession_recv_pdu_begin(int ctrl_fd, iscsi_conn_t *conn, ulong_t recv_handle, return 0; } -int -ksession_recv_pdu_end(int ctrl_fd, iscsi_conn_t *conn, ulong_t pdu_handle) +static int +krecv_pdu_end(uint64_t transport_handle, ulong_t cp_cnx, ulong_t pdu_handle) { + log_debug(7, "in %s", __FUNCTION__); + if (!recvbuf) { log_error("recv's end state machine bug?"); return -EIO; @@ -599,30 +593,31 @@ ksession_recv_pdu_end(int ctrl_fd, iscsi_conn_t *conn, ulong_t pdu_handle) log_debug(3, "recv PDU finished for pdu handle 0x%p", (void*)pdu_handle); - free((void*)pdu_handle); + recvpool_put((void*)cp_cnx, (void*)pdu_handle); recvbuf = NULL; return 0; } -int -ktrans_list(int ctrl_fd, struct iscsi_uevent *ev) +static int +ktrans_list(struct iscsi_uevent *ev) { int rc; + log_debug(7, "in %s", __FUNCTION__); + memset(ev, 0, sizeof(struct iscsi_uevent)); ev->type = ISCSI_UEVENT_TRANS_LIST; - if ((rc = __ksession_call(ctrl_fd, ev, sizeof(*ev))) < 0) { - log_error("can't retreive transport list (%d)", errno); + if ((rc = __kipc_call(ev, sizeof(*ev))) < 0) { return rc; } return 0; } -int -ctldev_handle(int ctrl_fd) +static int +ctldev_handle() { int rc; struct iscsi_uevent *ev; @@ -630,30 +625,19 @@ ctldev_handle(int ctrl_fd) iscsi_session_t *session = NULL; iscsi_conn_t *conn = NULL; ulong_t recv_handle; - struct nlmsghdr nlh; + char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))]; + struct nlmsghdr *nlh; int ev_size; - if ((rc = nl_read(ctrl_fd, &nlh, MSG_PEEK)) < 0) { - log_error("can not read nlmsghdr, error %d", rc); - return rc; - } + log_debug(7, "in %s", __FUNCTION__); - ev_size = nlh.nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr)); - recv_handle = (ulong_t)calloc(1, ev_size); - if (!recv_handle) { - log_error("can not allocate memory for receive handle"); - return -ENOMEM; - } - - log_debug(6, "message real length is %d bytes, recv_handle %p", - nlh.nlmsg_len, (void*)recv_handle); - - if ((rc = nlpayload_read(ctrl_fd, (void*)recv_handle, - ev_size, 0)) < 0) { - log_error("can not read from NL socket, error %d", rc); + if ((rc = nl_read(ctrl_fd, nlm_ev, + NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) { + log_error("can not read nlm_ev, error %d", rc); return rc; } - ev = (struct iscsi_uevent *)recv_handle; + nlh = (struct nlmsghdr *)nlm_ev; + ev = (struct iscsi_uevent *)NLMSG_DATA(nlm_ev); /* verify connection */ item = provider[0].sessions.q_forw; @@ -661,8 +645,13 @@ ctldev_handle(int ctrl_fd) int i; session = (iscsi_session_t *)item; for (i=0; i<ISCSI_CNX_MAX; i++) { - if (&session->cnx[i] == (iscsi_conn_t*) - iscsi_ptr(ev->r.recv_req.cnx_handle) || + if (ev->type == ISCSI_KEVENT_RECV_PDU && + &session->cnx[i] == (iscsi_conn_t*) + iscsi_ptr(ev->r.recv_req.cnx_handle)) { + conn = &session->cnx[i]; + break; + } + if (ev->type == ISCSI_KEVENT_CNX_ERROR && &session->cnx[i] == (iscsi_conn_t*) iscsi_ptr(ev->r.cnxerror.cnx_handle)) { conn = &session->cnx[i]; @@ -671,32 +660,41 @@ ctldev_handle(int ctrl_fd) } item = item->q_forw; } + if (conn == NULL) { + log_error("could not verify connection 0x%p ", conn); + return -ENXIO; + } - if (ev->type == ISCSI_KEVENT_RECV_PDU) { - if (conn == NULL) { - log_error("could not verify connection 0x%p for " - "event RECV_PDU", conn); - return -ENXIO; - } + ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr)); + recv_handle = (ulong_t)recvpool_get(conn, ev_size); + if (!recv_handle) { + log_error("can not allocate memory for receive handle"); + return -ENOMEM; + } + + log_debug(6, "message real length is %d bytes, recv_handle %p", + nlh->nlmsg_len, (void*)recv_handle); + + if ((rc = nlpayload_read(ctrl_fd, (void*)recv_handle, + ev_size, 0)) < 0) { + recvpool_put(conn, (void*)recv_handle); + log_error("can not read from NL socket, error %d", rc); + return rc; + } + if (ev->type == ISCSI_KEVENT_RECV_PDU) { /* produce an event, so session manager will handle */ queue_produce(session->queue, EV_CNX_RECV_PDU, conn, sizeof(ulong_t), &recv_handle); actor_schedule(&session->mainloop); - } else if (ev->type == ISCSI_KEVENT_CNX_ERROR) { - if (conn == NULL) { - log_error("could not verify connection 0x%p for " - "event CNX_ERR", conn); - return -ENXIO; - } - /* produce an event, so session manager will handle */ queue_produce(session->queue, EV_CNX_ERROR, conn, sizeof(ulong_t), (void*)&ev->r.cnxerror.error); actor_schedule(&session->mainloop); - + recvpool_put(conn, (void*)recv_handle); } else { + recvpool_put(conn, (void*)recv_handle); log_error("unknown kernel event %d", ev->type); return -EEXIST; } @@ -704,9 +702,10 @@ ctldev_handle(int ctrl_fd) return 0; } -int ctldev_open(void) +static int +ctldev_open(void) { - int ctrl_fd; + log_debug(7, "in %s", __FUNCTION__); nlm_sendbuf = calloc(1, NLM_BUF_DEFAULT_MAX); if (!nlm_sendbuf) { @@ -754,11 +753,38 @@ int ctldev_open(void) return ctrl_fd; } -void -ctldev_close(int ctrl_fd) +static void +ctldev_close(void) { + log_debug(7, "in %s", __FUNCTION__); + free(pdu_sendbuf); free(nlm_recvbuf); free(nlm_sendbuf); close(ctrl_fd); } + +struct iscsi_ipc nl_ipc = { + .name = "Open-iSCSI Kernel IPC/NETLINK v.1", + .ctldev_bufmax = NLM_BUF_DEFAULT_MAX, + .ctldev_open = ctldev_open, + .ctldev_close = ctldev_close, + .ctldev_handle = ctldev_handle, + .trans_list = ktrans_list, + .create_session = kcreate_session, + .destroy_session = kdestroy_session, + .create_cnx = kcreate_cnx, + .destroy_cnx = kdestroy_cnx, + .bind_cnx = kbind_cnx, + .set_param = kset_param, + .get_param = NULL, + .start_cnx = kstart_cnx, + .stop_cnx = kstop_cnx, + .writev = kwritev, + .send_pdu_begin = ksend_pdu_begin, + .send_pdu_end = ksend_pdu_end, + .read = kread, + .recv_pdu_begin = krecv_pdu_begin, + .recv_pdu_end = krecv_pdu_end, +}; +struct iscsi_ipc *ipc = &nl_ipc; |