static int __ksession_call(int ctrl_fd, void *iov_base, int iov_len) { int rc; struct iovec iov; struct iscsi_uevent *ev = iov_base; iscsi_uevent_e type = ev->type; iov.iov_base = iov_base; iov.iov_len = iov_len; if ((rc = ctldev_writev(ctrl_fd, type, &iov, 1)) < 0) { return rc; } do { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), MSG_PEEK)) < 0) { return rc; } if (ev->type != type) { /* * receive and queue async. event which as of * today could be: * - CNX_ERROR * - RECV_PDU */ ctldev_handle(ctrl_fd); } else { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), 0)) < 0) { return rc; } break; } } while (ev->type != type); return rc; }
/* * __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. * * Transport must assure non-blocking operations for: * * - session_create() * - conn_create() * - conn_bind() * _ set_param() * - conn_start() * - conn_stop() * * Its OK to block for cleanup for short period of time in operatations for: * * - conn_destroy() * - session_destroy() * * FIXME: interface needs to be extended to allow longer blocking on * cleanup. (Dima) */ static int __kipc_call(struct iovec *iovp, int count) { int rc, iferr; struct iscsi_uevent *ev = iovp[1].iov_base; enum iscsi_uevent_e type = ev->type; log_debug(7, "in %s", __FUNCTION__); rc = kwritev(type, iovp, count); do { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), MSG_PEEK)) < 0) { return rc; } if (ev->type != type) { log_debug(1, "expecting event %d, got %d, handling...", type, ev->type); if (ev->type == ISCSI_KEVENT_IF_ERROR) { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), 0)) < 0) { return rc; } /* * iferror is u32, but the kernel returns * negative errno values for errors. */ iferr = ev->iferror; if (iferr == -ENOSYS) /* not fatal so let caller handle log */ log_debug(1, "Received iferror %d: %s.", iferr, strerror(-iferr)); else if (iferr < 0) log_error("Received iferror %d: %s.", iferr, strerror(-iferr)); else log_error("Received iferror %d.", iferr); return ev->iferror; } /* * receive and queue async. event which as of * today could be: * - CONN_ERROR * - RECV_PDU */ ctldev_handle(); } else if (ev->type == ISCSI_UEVENT_GET_STATS) { /* kget_stats() will read */ return 0; } else if (ev->type == ISCSI_UEVENT_GET_CHAP) { /* kget_chap() will read */ return 0; } else if (ev->type == ISCSI_UEVENT_GET_HOST_STATS) { /* kget_host_stats() will read */ return 0; } else { if ((rc = nlpayload_read(ctrl_fd, (void*)ev, sizeof(*ev), 0)) < 0) { return rc; } break; } } while (ev->type != type); return rc; }