Updated for libhail's anet. Not yet committed, waiting for more time to pass. Makefile.am | 2 configure.ac | 1 iscsiutil.h | 52 +------------ target.c | 53 ++++++++++---- target.h | 3 util.c | 223 ++--------------------------------------------------------- 6 files changed, 57 insertions(+), 277 deletions(-) diff --git a/Makefile.am b/Makefile.am index d559165..d99ab0c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,7 +9,7 @@ sbin_PROGRAMS = itd itd_SOURCES = \ elist.h scsi_cmd_codes.h iscsiutil.h iscsi.h parameters.h target.h \ main.c iscsi.c target.c util.c parameters.c -itd_LDADD = @GLIB_LIBS@ @CRYPTO_LIBS@ @EVENT_LIBS@ +itd_LDADD = @GLIB_LIBS@ @CRYPTO_LIBS@ @EVENT_LIBS@ @HAIL_LIBS@ EXTRA_DIST = autogen.sh diff --git a/configure.ac b/configure.ac index 7cbbe3f..e2f6731 100644 --- a/configure.ac +++ b/configure.ac @@ -71,6 +71,7 @@ dnl autoconf output generation dnl -------------------------- AM_PATH_GLIB_2_0(2.0.0) +PKG_CHECK_MODULES(HAIL, libhail) AC_SUBST(CRYPTO_LIBS) AC_SUBST(EVENT_LIBS) diff --git a/iscsiutil.h b/iscsiutil.h index 5e5f5bf..2430c48 100644 --- a/iscsiutil.h +++ b/iscsiutil.h @@ -82,8 +82,8 @@ #endif #include <string.h> -#include <event.h> #include "elist.h" +#include <anet.h> /* * Debugging Levels @@ -138,11 +138,11 @@ extern void iscsi_print_buffer(uint8_t *, const size_t); */ struct target_session; -struct tcp_write_state; +struct atcp_wr_state; extern const char *sopstr(uint8_t op); extern int fsetflags(const char *prefix, int fd, int or_flags); -extern int iscsi_writev(struct tcp_write_state *st, +extern int iscsi_writev(struct atcp_wr_state *wst, void *header, unsigned header_len, const void *data, unsigned data_len); @@ -241,53 +241,11 @@ typedef struct name { \ extern size_t strlcpy(char *, const char *, size_t); #endif -enum { - TCP_MAX_WR_IOV = 512, /* arbitrary, pick better one */ - TCP_MAX_WR_CNT = 10000,/* arbitrary, pick better one */ -}; - -struct tcp_write_state { - int fd; - struct list_head write_q; - struct list_head write_compl_q; - size_t write_cnt; /* water level */ - size_t write_cnt_max; - bool writing; - struct event write_ev; - - void *priv; /* useable by any app */ - - /* stats */ - unsigned long opt_write; -}; - -struct tcp_write { - const void *buf; /* write buffer pointer */ - int togo; /* write buffer remainder */ - - int length; /* length for accounting */ - - /* callback */ - bool (*cb)(struct tcp_write_state *, void *, bool); - void *cb_data; /* data passed to cb */ - - struct list_head node; -}; - -extern int tcp_writeq(struct tcp_write_state *st, const void *buf, unsigned int buflen, - bool (*cb)(struct tcp_write_state *, void *, bool), - void *cb_data); -extern bool tcp_wr_cb_free(struct tcp_write_state *st, void *cb_data, bool done); -extern void tcp_write_init(struct tcp_write_state *st, int fd); -extern void tcp_write_exit(struct tcp_write_state *st); -extern bool tcp_write_start(struct tcp_write_state *st); -extern bool tcp_write_run_compl(struct tcp_write_state *st); - -extern void send_padding(struct tcp_write_state *st, unsigned int len_out); +extern void send_padding(struct atcp_wr_state *wst, unsigned int len_out); extern void *header_get(void); extern void header_put(void *mem); -extern bool hdr_cb_free(struct tcp_write_state *st, void *cb_data, bool done); +extern bool hdr_cb_free(struct atcp_wr_state *, void *, bool); extern void hdrs_free_all(void); static inline int padding_bytes(unsigned int len_out) diff --git a/target.c b/target.c index 7ef7d72..be6a88b 100644 --- a/target.c +++ b/target.c @@ -613,9 +613,9 @@ static int task_command_t(struct target_session *sess, const uint8_t *header) goto err_out_hdr; } - tcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, + atcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, hdr_cb_free, rsp_header); - tcp_write_start(&sess->wst); + atcp_write_start(&sess->wst); return 0; @@ -839,18 +839,18 @@ static int text_command_t(struct target_session *sess, const uint8_t *header) goto err_out_hdr; } - tcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, + atcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, hdr_cb_free, rsp_header); if (len_out) { - tcp_writeq(&sess->wst, text_out, len_out, - tcp_wr_cb_free, text_out); + atcp_writeq(&sess->wst, text_out, len_out, + atcp_cb_free, text_out); text_out = NULL; send_padding(&sess->wst, len_out); } - tcp_write_start(&sess->wst); + atcp_write_start(&sess->wst); free(text_in); free(text_out); @@ -1228,9 +1228,9 @@ static int logout_command_t(struct target_session *sess, const uint8_t *header) return -1; } - tcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, + atcp_writeq(&sess->wst, rsp_header, ISCSI_HEADER_LEN, hdr_cb_free, rsp_header); - tcp_write_start(&sess->wst); + atcp_write_start(&sess->wst); iscsi_trace(TRACE_ISCSI_DEBUG, __FILE__, __LINE__, "sent logout response OK\n"); @@ -1494,9 +1494,9 @@ static int send_r2t(struct target_session *sess) sess->xfer.r2t.tag, sess->xfer.r2t.transfer_tag, sess->xfer.r2t.length, sess->xfer.r2t.offset); - tcp_writeq(&sess->wst, header, ISCSI_HEADER_LEN, + atcp_writeq(&sess->wst, header, ISCSI_HEADER_LEN, hdr_cb_free, header); - tcp_write_start(&sess->wst); + atcp_write_start(&sess->wst); sess->xfer.r2t_flag = 1; sess->xfer.r2t.R2TSN += 1; @@ -1761,7 +1761,7 @@ int target_sess_cleanup(struct target_session *sess) event_del(&sess->ev); - tcp_write_exit(&sess->wst); + atcp_wr_exit(&sess->wst); /* Terminate connection */ if (sess->fd >= 0) @@ -1965,7 +1965,7 @@ restart: break; } - tcp_write_run_compl(&sess->wst); + atcp_write_run_compl(&sess->wst); return; err_out: @@ -1982,6 +1982,32 @@ static void target_tcp_evt(int fd, short events, void *userdata) target_read_evt(sess); } +static int target_sess_le_wset(void *ev_info, int fd, atcp_ev_func cb, void *cb_data) +{ + struct event *ev = ev_info; + + event_set(ev, fd, EV_WRITE | EV_PERSIST, cb, cb_data); + return 0; +} + +static int target_sess_le_add(void *ev_info, const struct timeval *tv) +{ + struct event *ev = ev_info; + return event_add(ev, tv); +} + +static int target_sess_le_del(void *ev_info) +{ + struct event *ev = ev_info; + return event_del(ev); +} + +static const struct atcp_wr_ops libevent_wr_ops = { + .ev_wset = target_sess_le_wset, + .ev_add = target_sess_le_add, + .ev_del = target_sess_le_del, +}; + int target_accept(struct globals *gp, struct server_socket *sock) { struct target_session *sess; @@ -2013,7 +2039,8 @@ int target_accept(struct globals *gp, struct server_socket *sock) sess->globals = gp; - tcp_write_init(&sess->wst, sess->fd); + atcp_wr_init(&sess->wst, &libevent_wr_ops, &sess->write_ev, sess); + atcp_wr_set_fd(&sess->wst, sess->fd); event_set(&sess->ev, sess->fd, EV_READ | EV_PERSIST, target_tcp_evt, sess); diff --git a/target.h b/target.h index ddedb0a..e764730 100644 --- a/target.h +++ b/target.h @@ -219,8 +219,9 @@ struct target_session { int fd; struct sockaddr addr; struct event ev; + struct event write_ev; - struct tcp_write_state wst; + struct atcp_wr_state wst; struct session_xfer xfer; diff --git a/util.c b/util.c index c3e4455..eb41f84 100644 --- a/util.c +++ b/util.c @@ -307,7 +307,7 @@ void header_put(void *mem) g_trash_stack_push(&free_headers, mem); } -bool hdr_cb_free(struct tcp_write_state *st, void *cb_data, bool done) +bool hdr_cb_free(struct atcp_wr_state *wst, void *cb_data, bool done) { header_put(cb_data); return false; @@ -326,7 +326,7 @@ void hdrs_free_all(void) } } -void send_padding(struct tcp_write_state *st, unsigned int len_out) +void send_padding(struct atcp_wr_state *st, unsigned int len_out) { int pad_len; static const char pad_buf[4] = { 0, 0, 0, 0 }; @@ -335,7 +335,7 @@ void send_padding(struct tcp_write_state *st, unsigned int len_out) if (!pad_len) return; - tcp_writeq(st, pad_buf, pad_len, NULL, NULL); + atcp_writeq(st, pad_buf, pad_len, NULL, NULL); } /* @@ -348,7 +348,7 @@ void send_padding(struct tcp_write_state *st, unsigned int len_out) * data, else send as two separate messages. */ -int iscsi_writev(struct tcp_write_state *st, +int iscsi_writev(struct atcp_wr_state *st, void *header, unsigned header_len, const void *data, unsigned data_len) { @@ -356,7 +356,7 @@ int iscsi_writev(struct tcp_write_state *st, "NET: writing %u header bytes, %u data bytes\n", header_len, data_len); - tcp_writeq(st, header, header_len, hdr_cb_free, header); + atcp_writeq(st, header, header_len, hdr_cb_free, header); if (data && data_len > 0) { void *mem; @@ -364,13 +364,13 @@ int iscsi_writev(struct tcp_write_state *st, mem = g_memdup(data, data_len); if (!mem) return -1; - tcp_writeq(st, mem, data_len, - tcp_wr_cb_free, mem); + atcp_writeq(st, mem, data_len, + atcp_cb_free, mem); } send_padding(st, data_len); - tcp_write_start(st); + atcp_write_start(st); return header_len + data_len; } @@ -712,213 +712,6 @@ int fsetflags(const char *prefix, int fd, int or_flags) return rc; } -static void tcp_write_complete(struct tcp_write_state *st, struct tcp_write *tmp) -{ - list_del(&tmp->node); - list_add_tail(&tmp->node, &st->write_compl_q); -} - -bool tcp_wr_cb_free(struct tcp_write_state *st, void *cb_data, bool done) -{ - free(cb_data); - return false; -} - -static bool tcp_write_free(struct tcp_write_state *st, struct tcp_write *tmp, - bool done) -{ - bool rcb = false; - - st->write_cnt -= tmp->length; - list_del_init(&tmp->node); - if (tmp->cb) - rcb = tmp->cb(st, tmp->cb_data, done); - free(tmp); - - return rcb; -} - -static void tcp_write_free_all(struct tcp_write_state *st) -{ - struct tcp_write *wr, *tmp; - - list_for_each_entry_safe(wr, tmp, &st->write_compl_q, node) { - tcp_write_free(st, wr, true); - } - list_for_each_entry_safe(wr, tmp, &st->write_q, node) { - tcp_write_free(st, wr, false); - } -} - -bool tcp_write_run_compl(struct tcp_write_state *st) -{ - struct tcp_write *wr; - bool do_loop; - - do_loop = false; - while (!list_empty(&st->write_compl_q)) { - wr = list_entry(st->write_compl_q.next, struct tcp_write, - node); - do_loop |= tcp_write_free(st, wr, true); - } - return do_loop; -} - -static bool tcp_writable(struct tcp_write_state *st) -{ - int n_iov; - struct tcp_write *tmp; - ssize_t rc; - struct iovec iov[TCP_MAX_WR_IOV]; - - /* accumulate pending writes into iovec */ - n_iov = 0; - list_for_each_entry(tmp, &st->write_q, node) { - if (n_iov == TCP_MAX_WR_IOV) - break; - /* bleh, struct iovec should declare iov_base const */ - iov[n_iov].iov_base = (void *) tmp->buf; - iov[n_iov].iov_len = tmp->togo; - n_iov++; - } - - /* execute non-blocking write */ -do_write: - rc = writev(st->fd, iov, n_iov); - if (rc < 0) { - if (errno == EINTR) - goto do_write; - if (errno != EAGAIN) - goto err_out; - return true; - } - - /* iterate through write queue, issuing completions based on - * amount of data written - */ - while (rc > 0) { - int sz; - - /* get pointer to first record on list */ - tmp = list_entry(st->write_q.next, struct tcp_write, node); - - /* mark data consumed by decreasing tmp->len */ - sz = (tmp->togo < rc) ? tmp->togo : rc; - tmp->togo -= sz; - tmp->buf += sz; - rc -= sz; - - /* if tmp->len reaches zero, write is complete, - * so schedule it for clean up (cannot call callback - * right away or an endless recursion will result) - */ - if (tmp->togo == 0) - tcp_write_complete(st, tmp); - } - - /* if we emptied the queue, clear write notification */ - if (list_empty(&st->write_q)) { - st->writing = false; - if (event_del(&st->write_ev) < 0) - goto err_out; - } - - return true; - -err_out: - tcp_write_free_all(st); - return false; -} - -bool tcp_write_start(struct tcp_write_state *st) -{ - if (list_empty(&st->write_q)) - return true; /* loop, not poll */ - - /* if write-poll already active, nothing further to do */ - if (st->writing) - return false; /* poll wait */ - - /* attempt optimistic write, in hopes of avoiding poll, - * or at least refill the write buffers so as to not - * get -immediately- called again by the kernel - */ - tcp_writable(st); - if (list_empty(&st->write_q)) { - st->opt_write++; - return true; /* loop, not poll */ - } - - if (event_add(&st->write_ev, NULL) < 0) - return true; /* loop, not poll */ - - st->writing = true; - - return false; /* poll wait */ -} - -int tcp_writeq(struct tcp_write_state *st, const void *buf, unsigned int buflen, - bool (*cb)(struct tcp_write_state *, void *, bool), - void *cb_data) -{ - struct tcp_write *wr; - - if (!buf || !buflen) - return -EINVAL; - - wr = calloc(1, sizeof(struct tcp_write)); - if (!wr) - return -ENOMEM; - - wr->buf = buf; - wr->togo = buflen; - wr->length = buflen; - wr->cb = cb; - wr->cb_data = cb_data; - list_add_tail(&wr->node, &st->write_q); - st->write_cnt += buflen; - if (st->write_cnt > st->write_cnt_max) - st->write_cnt_max = st->write_cnt; - - return 0; -} - -size_t tcp_wqueued(struct tcp_write_state *st) -{ - return st->write_cnt; -} - -static void tcp_wr_evt(int fd, short events, void *userdata) -{ - struct tcp_write_state *st = userdata; - - tcp_writable(st); - tcp_write_run_compl(st); -} - -void tcp_write_init(struct tcp_write_state *st, int fd) -{ - memset(st, 0, sizeof(*st)); - - st->fd = fd; - - INIT_LIST_HEAD(&st->write_q); - INIT_LIST_HEAD(&st->write_compl_q); - - st->write_cnt_max = TCP_MAX_WR_CNT; - - event_set(&st->write_ev, fd, EV_WRITE | EV_PERSIST, - tcp_wr_evt, st); -} - -void tcp_write_exit(struct tcp_write_state *st) -{ - if (st->writing) - event_del(&st->write_ev); - - tcp_write_free_all(st); -} - /* * CRC32C chksum, * as copied from Linux kernel's crypto/crc32c.c -- To unsubscribe from this list: send the line "unsubscribe hail-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html