Home | History | Annotate | Line # | Download | only in libisns
isns_thread.c revision 1.1.1.1.46.1
      1  1.1.1.1.46.1  martin /*	$NetBSD: isns_thread.c,v 1.1.1.1.46.1 2020/04/13 08:03:13 martin Exp $	*/
      2           1.1     agc 
      3           1.1     agc /*-
      4           1.1     agc  * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
      5           1.1     agc  * All rights reserved.
      6           1.1     agc  *
      7           1.1     agc  * This code is derived from software contributed to The NetBSD Foundation
      8           1.1     agc  * by Wasabi Systems, Inc.
      9           1.1     agc  *
     10           1.1     agc  * Redistribution and use in source and binary forms, with or without
     11           1.1     agc  * modification, are permitted provided that the following conditions
     12           1.1     agc  * are met:
     13           1.1     agc  * 1. Redistributions of source code must retain the above copyright
     14           1.1     agc  *    notice, this list of conditions and the following disclaimer.
     15           1.1     agc  * 2. Redistributions in binary form must reproduce the above copyright
     16           1.1     agc  *    notice, this list of conditions and the following disclaimer in the
     17           1.1     agc  *    documentation and/or other materials provided with the distribution.
     18           1.1     agc  *
     19           1.1     agc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20           1.1     agc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21           1.1     agc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22           1.1     agc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23           1.1     agc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24           1.1     agc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25           1.1     agc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26           1.1     agc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27           1.1     agc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28           1.1     agc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29           1.1     agc  * POSSIBILITY OF SUCH DAMAGE.
     30           1.1     agc  */
     31           1.1     agc 
     32           1.1     agc #include <sys/cdefs.h>
     33  1.1.1.1.46.1  martin __RCSID("$NetBSD: isns_thread.c,v 1.1.1.1.46.1 2020/04/13 08:03:13 martin Exp $");
     34           1.1     agc 
     35           1.1     agc 
     36           1.1     agc /*
     37           1.1     agc  * isns_thread.c
     38           1.1     agc  */
     39           1.1     agc 
     40           1.1     agc #include <sys/types.h>
     41           1.1     agc 
     42           1.1     agc #include <unistd.h>
     43           1.1     agc 
     44           1.1     agc #include "isns.h"
     45           1.1     agc #include "isns_config.h"
     46           1.1     agc #include "isns_defs.h"
     47           1.1     agc 
     48           1.1     agc static struct iovec read_buf[2 + (ISNS_MAX_PDU_PAYLOAD / ISNS_BUF_SIZE) +
     49           1.1     agc     ((ISNS_MAX_PDU_PAYLOAD % ISNS_BUF_SIZE) != 0)];
     50           1.1     agc 
     51           1.1     agc static struct isns_task_s *isns_get_next_task(struct isns_config_s *);
     52           1.1     agc 
     53           1.1     agc /*
     54           1.1     agc  * isns_control_thread()
     55           1.1     agc  */
     56           1.1     agc void *
     57           1.1     agc isns_control_thread(void *arg)
     58           1.1     agc {
     59           1.1     agc 	struct isns_config_s *cfg_p = (struct isns_config_s *)arg;
     60           1.1     agc 	struct kevent evt_chgs[5], *evt_p;
     61           1.1     agc 
     62           1.1     agc 	int n, nevents;
     63           1.1     agc 	isns_kevent_handler *evt_handler_p;
     64           1.1     agc 	int run_thread;
     65           1.1     agc 
     66           1.1     agc 	run_thread = 1;
     67           1.1     agc 
     68           1.1     agc 	while (run_thread) {
     69           1.1     agc 		/* if no task outstanding, check queue here and send PDU */
     70           1.1     agc 		while ((cfg_p->curtask_p == NULL)
     71           1.1     agc 		    && ((cfg_p->curtask_p = isns_get_next_task(cfg_p)) != NULL))
     72           1.1     agc 			isns_run_task(cfg_p->curtask_p);
     73           1.1     agc 
     74           1.1     agc 		nevents = kevent(cfg_p->kq, NULL, 0, evt_chgs,
     75           1.1     agc 		    ARRAY_ELEMS(evt_chgs), NULL);
     76           1.1     agc 
     77           1.1     agc 		DBG("isns_control_thread: kevent() nevents=%d\n", nevents);
     78           1.1     agc 
     79           1.1     agc 		for (n = 0, evt_p = evt_chgs; n < nevents; n++, evt_p++) {
     80           1.1     agc 			DBG("event[%d] - data=%d\n", n, (int)evt_p->data);
     81           1.1     agc 			evt_handler_p = (void *)evt_p->udata;
     82           1.1     agc 			run_thread = (evt_handler_p(evt_p, cfg_p) == 0);
     83           1.1     agc 		}
     84           1.1     agc 	}
     85           1.1     agc 
     86           1.1     agc 	return 0;
     87           1.1     agc }
     88           1.1     agc 
     89           1.1     agc /*
     90           1.1     agc  * isns_get_next_task()
     91           1.1     agc  */
     92           1.1     agc static struct isns_task_s *
     93           1.1     agc isns_get_next_task(struct isns_config_s *cfg_p)
     94           1.1     agc {
     95           1.1     agc 	struct isns_task_s *task_p = NULL;
     96           1.1     agc 
     97           1.1     agc 
     98           1.1     agc 	DBG("isns_get_next_task: entered\n");
     99           1.1     agc 
    100           1.1     agc 	task_p = isns_taskq_remove(cfg_p);
    101           1.1     agc 
    102           1.1     agc 	if (cfg_p->sd_connected)
    103           1.1     agc 		return task_p;
    104           1.1     agc 	else {
    105           1.1     agc 		if (task_p == NULL)
    106           1.1     agc 			return NULL;
    107           1.1     agc 		else {
    108           1.1     agc 			if (task_p->task_type != ISNS_TASK_INIT_SOCKET_IO) {
    109           1.1     agc 				isns_taskq_insert_head(cfg_p, task_p);
    110           1.1     agc 
    111           1.1     agc 				task_p = isns_new_task(cfg_p,
    112           1.1     agc 				    ISNS_TASK_RECONNECT_SERVER, 0);
    113           1.1     agc 				task_p->var.reconnect_server.ai_p = cfg_p->ai_p;
    114           1.1     agc 			}
    115           1.1     agc 
    116           1.1     agc 			return task_p;
    117           1.1     agc 		}
    118           1.1     agc 	}
    119           1.1     agc }
    120           1.1     agc 
    121           1.1     agc /*
    122           1.1     agc  * isns_kevent_pipe()
    123           1.1     agc  */
    124           1.1     agc int
    125           1.1     agc isns_kevent_pipe(struct kevent* evt_p, struct isns_config_s *cfg_p)
    126           1.1     agc {
    127           1.1     agc 	uint8_t cmd_type;
    128           1.1     agc 	int force_isns_stop;
    129           1.1     agc 	uint16_t trans_id;
    130           1.1     agc 	ssize_t rbytes;
    131           1.1     agc 	int pipe_nbytes;
    132           1.1     agc 
    133           1.1     agc 	force_isns_stop = 0;
    134           1.1     agc 	pipe_nbytes = (int)evt_p->data;
    135           1.1     agc 
    136           1.1     agc 	while (pipe_nbytes > 0) {
    137           1.1     agc 		rbytes = read(cfg_p->pipe_fds[0], &cmd_type,
    138           1.1     agc 		    sizeof(cmd_type));
    139           1.1     agc 		if (rbytes < 0) {
    140           1.1     agc 			DBG("isns_kevent_pipe: error on wepe_sys_read\n");
    141           1.1     agc 			/*?? should we break here? */
    142           1.1     agc 			continue;
    143           1.1     agc 		}
    144           1.1     agc 
    145           1.1     agc 		pipe_nbytes -= (int)rbytes;
    146           1.1     agc 		switch (cmd_type) {
    147           1.1     agc 		case ISNS_CMD_PROCESS_TASKQ:
    148           1.1     agc 			DBG("isns_kevent_pipe: ISNS_CMD_PROCESS_TASKQ\n");
    149           1.1     agc 			break;
    150           1.1     agc 
    151           1.1     agc 		case ISNS_CMD_ABORT_TRANS:
    152           1.1     agc 			DBG("isns_kevent_pipe: ISNS_CMD_ABORT_TRANS\n");
    153           1.1     agc 			rbytes = read(cfg_p->pipe_fds[0], &trans_id,
    154           1.1     agc 			    sizeof(trans_id));
    155  1.1.1.1.46.1  martin 			if (rbytes < 0)
    156           1.1     agc 				DBG("isns_kevent_pipe: "
    157           1.1     agc 				    "error reading trans id\n");
    158  1.1.1.1.46.1  martin 			else if (rbytes != sizeof(trans_id))
    159  1.1.1.1.46.1  martin 				DBG("isns_kevent_pipe: "
    160  1.1.1.1.46.1  martin 				    "short read reading trans id\n");
    161  1.1.1.1.46.1  martin 			else {
    162  1.1.1.1.46.1  martin 				isns_abort_trans(cfg_p, trans_id);
    163  1.1.1.1.46.1  martin 				pipe_nbytes -= (int)rbytes;
    164  1.1.1.1.46.1  martin 			}
    165           1.1     agc 			break;
    166           1.1     agc 
    167           1.1     agc 		case ISNS_CMD_STOP:
    168           1.1     agc 			DBG("isns_kevent_pipe: ISNS_CMD_STOP\n");
    169           1.1     agc 			force_isns_stop = 1;
    170           1.1     agc 			pipe_nbytes = 0;
    171           1.1     agc 			break;
    172           1.1     agc 
    173           1.1     agc 		default:
    174           1.1     agc 			DBG("isns_kevent_pipe: unknown command (cmd=%d)\n",
    175           1.1     agc 			    cmd_type);
    176           1.1     agc 			break;
    177           1.1     agc 		}
    178           1.1     agc 	}
    179           1.1     agc 
    180           1.1     agc 	return (force_isns_stop ? 1 : 0);
    181           1.1     agc }
    182           1.1     agc 
    183           1.1     agc /*
    184           1.1     agc  * isns_is_trans_complete()
    185           1.1     agc  */
    186           1.1     agc static int
    187           1.1     agc isns_is_trans_complete(struct isns_trans_s *trans_p)
    188           1.1     agc {
    189           1.1     agc 	struct isns_pdu_s *pdu_p;
    190           1.1     agc 	uint16_t count;
    191           1.1     agc 
    192           1.1     agc 	pdu_p = trans_p->pdu_rsp_list;
    193           1.1     agc 	count = 0;
    194           1.1     agc 	while (pdu_p->next != NULL) {
    195           1.1     agc 		if (pdu_p->hdr.seq_id != count++) return 0;
    196           1.1     agc 		pdu_p = pdu_p->next;
    197           1.1     agc 	}
    198           1.1     agc 	if ((pdu_p->hdr.seq_id != count) ||
    199           1.1     agc 	    !(pdu_p->hdr.flags & ISNS_FLAG_LAST_PDU))
    200           1.1     agc 		return 0;
    201           1.1     agc 
    202           1.1     agc 	return 1;
    203           1.1     agc }
    204           1.1     agc 
    205           1.1     agc /*
    206           1.1     agc  * isns_is_valid_resp()
    207           1.1     agc  */
    208           1.1     agc static int
    209           1.1     agc isns_is_valid_resp(struct isns_trans_s *trans_p, struct isns_pdu_s *pdu_p)
    210           1.1     agc {
    211           1.1     agc 	struct isns_pdu_s *curpdu_p;
    212           1.1     agc 
    213           1.1     agc 	if (pdu_p->hdr.trans_id != trans_p->id)
    214           1.1     agc 		return 0;
    215           1.1     agc 	if (pdu_p->hdr.func_id != (trans_p->func_id | 0x8000))
    216           1.1     agc 		return 0;
    217           1.1     agc 	curpdu_p = trans_p->pdu_rsp_list;
    218           1.1     agc 	while (curpdu_p != NULL) {
    219           1.1     agc 		if (curpdu_p->hdr.seq_id == pdu_p->hdr.seq_id) return 0;
    220           1.1     agc 		curpdu_p = curpdu_p->next;
    221           1.1     agc 	}
    222           1.1     agc 
    223           1.1     agc 	return 1;
    224           1.1     agc }
    225           1.1     agc 
    226           1.1     agc /*
    227           1.1     agc  * isns_process_in_pdu()
    228           1.1     agc  */
    229           1.1     agc static void
    230           1.1     agc isns_process_in_pdu(struct isns_config_s *cfg_p)
    231           1.1     agc {
    232           1.1     agc 	struct isns_task_s *curtask_p;
    233           1.1     agc 	struct isns_trans_s *trans_p;
    234           1.1     agc 
    235           1.1     agc 	DBG("isns_process_in_pdu: entered\n");
    236           1.1     agc 
    237           1.1     agc 	if ((curtask_p = cfg_p->curtask_p) == NULL)
    238           1.1     agc 		isns_free_pdu(cfg_p->pdu_in_p);
    239           1.1     agc 	else if ((trans_p = curtask_p->var.send_pdu.trans_p) == NULL)
    240           1.1     agc 		isns_free_pdu(cfg_p->pdu_in_p);
    241           1.1     agc 	else if (!isns_is_valid_resp(trans_p, cfg_p->pdu_in_p))
    242           1.1     agc 		isns_free_pdu(cfg_p->pdu_in_p);
    243           1.1     agc 	else {
    244           1.1     agc 		isns_add_pdu_response(trans_p, cfg_p->pdu_in_p);
    245           1.1     agc 
    246           1.1     agc 		if (isns_is_trans_complete(trans_p)) {
    247           1.1     agc 			isns_complete_trans(trans_p);
    248           1.1     agc 			isns_end_task(curtask_p);
    249           1.1     agc 		}
    250           1.1     agc 	}
    251           1.1     agc 
    252           1.1     agc 	cfg_p->pdu_in_p = NULL;
    253           1.1     agc }
    254           1.1     agc 
    255           1.1     agc /*
    256           1.1     agc  * isns_kevent_socket()
    257           1.1     agc  */
    258           1.1     agc int
    259           1.1     agc isns_kevent_socket(struct kevent *evt_p, struct isns_config_s *cfg_p)
    260           1.1     agc {
    261           1.1     agc 	struct iovec *iovp;
    262           1.1     agc 	struct isns_buffer_s *curbuf_p, *newbuf_p;
    263           1.1     agc 	struct isns_pdu_s *pdu_p;
    264           1.1     agc 	int64_t bavail; /* bytes available in socket buffer */
    265           1.1     agc 	uint32_t cur_len, buf_len, unread_len, rd_len, b_len;
    266           1.1     agc 	ssize_t rv;
    267           1.1     agc 	uint16_t payload_len;
    268           1.1     agc 	int iovcnt, more, transport_evt;
    269           1.1     agc 
    270           1.1     agc 
    271           1.1     agc 	DBG("isns_kevent_socket: entered\n");
    272           1.1     agc 
    273           1.1     agc 	transport_evt = 0;
    274           1.1     agc 	bavail = evt_p->data;
    275           1.1     agc 	iovp = read_buf;
    276           1.1     agc 
    277           1.1     agc 	more = (bavail > 0);
    278           1.1     agc 	while (more) {
    279           1.1     agc 		if (cfg_p->pdu_in_p == NULL) {
    280           1.1     agc 			/*
    281           1.1     agc  	 		 * Try to form a valid pdu by starting with the hdr.
    282           1.1     agc 			 * If there isn't enough data in the socket buffer
    283           1.1     agc 			 * to form a full hdr, just return.
    284           1.1     agc  	 		 *
    285           1.1     agc  	 		 * Once we have read in our hdr, allocate all buffers
    286           1.1     agc 			 * needed.
    287           1.1     agc  	 		 */
    288           1.1     agc 
    289           1.1     agc 			if (bavail < (int64_t)sizeof(struct isns_pdu_hdr_s))
    290           1.1     agc 				return 0;
    291           1.1     agc 
    292           1.1     agc 			/* Form a placeholder pdu */
    293           1.1     agc 			pdu_p = isns_new_pdu(cfg_p, 0, 0, 0);
    294           1.1     agc 
    295           1.1     agc 			/* Read the header into our placeholder pdu */
    296           1.1     agc 			read_buf[0].iov_base = &(pdu_p->hdr);
    297           1.1     agc 			read_buf[0].iov_len = sizeof(struct isns_pdu_hdr_s);
    298           1.1     agc 			iovcnt = 1;
    299           1.1     agc 
    300           1.1     agc 			iovp = read_buf;
    301           1.1     agc 			rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
    302           1.1     agc 			if ((rv == 0) || (rv == -1)) {
    303           1.1     agc 				DBG("isns_kevent_socket: isns_socket_readv(1) "
    304           1.1     agc 				    "returned %d\n", rv);
    305           1.1     agc 				transport_evt = 1;
    306           1.1     agc 				break;
    307           1.1     agc 			}
    308           1.1     agc 
    309           1.1     agc 			bavail -= sizeof(struct isns_pdu_hdr_s);
    310           1.1     agc 			/*
    311           1.1     agc 			 * ToDo: read until sizeof(struct isns_pdu_hdr_s) has
    312           1.1     agc 			 *       been read in. This statement should be
    313           1.1     agc 			 *
    314           1.1     agc 			 *       bavail -= rv;
    315           1.1     agc 			 */
    316           1.1     agc 
    317           1.1     agc 			/* adjust byte order */
    318           1.1     agc 			pdu_p->hdr.isnsp_version = isns_ntohs(pdu_p->hdr.
    319           1.1     agc 			    isnsp_version);
    320           1.1     agc 			pdu_p->hdr.func_id = isns_ntohs(pdu_p->hdr.func_id);
    321           1.1     agc 			pdu_p->hdr.payload_len = isns_ntohs(pdu_p->hdr.
    322           1.1     agc 			    payload_len);
    323           1.1     agc 			pdu_p->hdr.flags = isns_ntohs(pdu_p->hdr.flags);
    324           1.1     agc 			pdu_p->hdr.trans_id = isns_ntohs(pdu_p->hdr.trans_id);
    325           1.1     agc 			pdu_p->hdr.seq_id = isns_ntohs(pdu_p->hdr.seq_id);
    326           1.1     agc 			pdu_p->byteorder_host = 1;
    327           1.1     agc 
    328           1.1     agc 			/* Try to sense early whether we might have garbage */
    329           1.1     agc 			if (pdu_p->hdr.isnsp_version != ISNSP_VERSION) {
    330           1.1     agc 				DBG("isns_kevent_socket: pdu_p->hdr."
    331           1.1     agc 				    "isnsp_version != ISNSP_VERSION\n");
    332           1.1     agc 				isns_free_pdu(pdu_p);
    333           1.1     agc 
    334           1.1     agc 				transport_evt = 1;
    335           1.1     agc 				break;
    336           1.1     agc 			}
    337           1.1     agc 
    338           1.1     agc 			/* Allocate all the necessary payload buffers */
    339           1.1     agc 			payload_len = pdu_p->hdr.payload_len;
    340           1.1     agc 			curbuf_p = pdu_p->payload_p;
    341           1.1     agc 			buf_len = 0;
    342           1.1     agc 			while (buf_len + curbuf_p->alloc_len < payload_len) {
    343           1.1     agc 				buf_len += curbuf_p->alloc_len;
    344           1.1     agc 				newbuf_p = isns_new_buffer(0);
    345           1.1     agc 				curbuf_p->next = newbuf_p;
    346           1.1     agc 				curbuf_p = newbuf_p;
    347           1.1     agc 			}
    348           1.1     agc 			curbuf_p->next = NULL;
    349           1.1     agc 
    350           1.1     agc 			/* Hold on to our placeholder pdu */
    351           1.1     agc 			cfg_p->pdu_in_p = pdu_p;
    352           1.1     agc 			more = (bavail > 0) ? 1 : 0;
    353           1.1     agc 		} else if (bavail > 0) {
    354           1.1     agc 			/*
    355           1.1     agc  	 		 * Fill in the pdu payload data.
    356           1.1     agc 			 *
    357           1.1     agc  	 		 * If we can fill it all in now
    358           1.1     agc 	 		 *     -AND- it corresponds to the active transaction
    359           1.1     agc 			 *           then add the pdu to the transaction's
    360           1.1     agc 			 *           pdu_rsp_list
    361           1.1     agc 	 		 *     -AND- it does not correspond to the active
    362           1.1     agc 			 *           transaction (or there is no active
    363           1.1     agc 			 *           transaction) then drop it on the floor.
    364           1.1     agc 			 * We may not be able to fill it all in now.
    365           1.1     agc 	 		 *     -EITHER WAY- fill in as much payload data now
    366           1.1     agc 			 *                  as we can.
    367           1.1     agc  	 		 */
    368           1.1     agc 
    369           1.1     agc 			/* Refer to our placeholder pdu */
    370           1.1     agc 			pdu_p = cfg_p->pdu_in_p;
    371           1.1     agc 
    372           1.1     agc 			/* How much payload data has been filled in? */
    373           1.1     agc 			cur_len = 0;
    374           1.1     agc 			curbuf_p = pdu_p->payload_p;
    375           1.1     agc 			while (curbuf_p->cur_len == curbuf_p->alloc_len) {
    376           1.1     agc 				cur_len += curbuf_p->cur_len;
    377           1.1     agc 				curbuf_p = curbuf_p->next;
    378           1.1     agc 			}
    379           1.1     agc 			cur_len += curbuf_p->cur_len;
    380           1.1     agc 
    381           1.1     agc 			/* How much payload data is left to be filled in? */
    382           1.1     agc 			unread_len = pdu_p->hdr.payload_len - cur_len;
    383           1.1     agc 
    384           1.1     agc 			/* Read as much remaining payload data as possible */
    385           1.1     agc 			iovcnt = 0;
    386           1.1     agc 			while (curbuf_p->next != NULL) {
    387           1.1     agc 				read_buf[iovcnt].iov_base = isns_buffer_data(
    388           1.1     agc 			    	    curbuf_p, curbuf_p->cur_len);
    389           1.1     agc 				read_buf[iovcnt].iov_len = curbuf_p->alloc_len -
    390           1.1     agc 			    	    curbuf_p->cur_len;
    391           1.1     agc 				iovcnt++;
    392           1.1     agc 
    393           1.1     agc 				curbuf_p = curbuf_p->next;
    394           1.1     agc 			}
    395           1.1     agc 			read_buf[iovcnt].iov_base = isns_buffer_data(curbuf_p,
    396           1.1     agc 		    	    curbuf_p->cur_len);
    397           1.1     agc 			read_buf[iovcnt].iov_len = unread_len;
    398           1.1     agc 			iovcnt++;
    399           1.1     agc 
    400           1.1     agc 			rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
    401           1.1     agc 			if ((rv == 0) || (rv == -1)) {
    402           1.1     agc 				DBG("isns_kevent_socket: isns_socket_readv(2) "
    403           1.1     agc 			    	    "returned %d\n",rv);
    404           1.1     agc 				isns_free_pdu(cfg_p->pdu_in_p);
    405           1.1     agc 				cfg_p->pdu_in_p = NULL;
    406           1.1     agc 
    407           1.1     agc 				transport_evt = 1;
    408           1.1     agc 				break;
    409           1.1     agc 			}
    410           1.1     agc 
    411           1.1     agc 			/* Update cur_len in buffers that newly have data */
    412           1.1     agc 			curbuf_p = pdu_p->payload_p;
    413           1.1     agc 			while (curbuf_p->cur_len == curbuf_p->alloc_len)
    414           1.1     agc 				curbuf_p = curbuf_p->next;
    415           1.1     agc 
    416           1.1     agc 			rd_len = (uint32_t)rv;
    417           1.1     agc 			do {
    418           1.1     agc 				b_len = curbuf_p->alloc_len - curbuf_p->cur_len;
    419           1.1     agc 				if (rd_len > b_len) {
    420           1.1     agc 					curbuf_p->cur_len = curbuf_p->alloc_len;
    421           1.1     agc 					rd_len -= b_len;
    422           1.1     agc 				} else {
    423           1.1     agc 					curbuf_p->cur_len += rd_len;
    424           1.1     agc 					break;
    425           1.1     agc 				}
    426           1.1     agc 
    427           1.1     agc 				curbuf_p = curbuf_p->next;
    428           1.1     agc 			} while (curbuf_p != NULL);
    429           1.1     agc 
    430           1.1     agc 			bavail -= rv;
    431           1.1     agc 
    432           1.1     agc 			if (rv == (int)unread_len)
    433           1.1     agc 				isns_process_in_pdu(cfg_p);
    434           1.1     agc 
    435           1.1     agc 			more = (bavail > (int64_t)sizeof(struct isns_pdu_hdr_s)) ? 1 : 0;
    436           1.1     agc 		}
    437           1.1     agc 	}
    438           1.1     agc 
    439           1.1     agc 	transport_evt |= (evt_p->flags & EV_EOF);
    440           1.1     agc 	if (transport_evt) {
    441           1.1     agc 		DBG("isns_kevent_socket: processing transport event\n");
    442           1.1     agc 
    443           1.1     agc 		isns_socket_close(cfg_p->sd);
    444           1.1     agc 		cfg_p->sd_connected = 0;
    445           1.1     agc 
    446           1.1     agc 		if (cfg_p->curtask_p != NULL)
    447           1.1     agc 			isns_process_connection_loss(cfg_p);
    448           1.1     agc 
    449           1.1     agc 		if (cfg_p->pdu_in_p != NULL) {
    450           1.1     agc 			isns_free_pdu(cfg_p->pdu_in_p);
    451           1.1     agc 			cfg_p->pdu_in_p = NULL;
    452           1.1     agc 		}
    453           1.1     agc 	}
    454           1.1     agc 
    455           1.1     agc 	return 0;
    456           1.1     agc }
    457           1.1     agc 
    458           1.1     agc /* ARGSUSED */
    459           1.1     agc /*
    460           1.1     agc  * isns_kevent_timer_recon()
    461           1.1     agc  */
    462           1.1     agc int
    463           1.1     agc isns_kevent_timer_recon(struct kevent *evt_p, struct isns_config_s *cfg_p)
    464           1.1     agc {
    465           1.1     agc 	int rv;
    466           1.1     agc 
    467           1.1     agc 
    468           1.1     agc 	DBG("isns_kevent_timer_recon: entered\n");
    469           1.1     agc 
    470           1.1     agc 	rv = isns_socket_create(&(cfg_p->sd), cfg_p->ai_p->ai_family,
    471           1.1     agc 		cfg_p->ai_p->ai_socktype);
    472           1.1     agc 	if (rv != 0)
    473           1.1     agc 		return 0;
    474           1.1     agc 
    475           1.1     agc 	rv = isns_socket_connect(cfg_p->sd, cfg_p->ai_p->ai_addr,
    476           1.1     agc 	    cfg_p->ai_p->ai_addrlen);
    477           1.1     agc 	if (rv == 0) {
    478           1.1     agc 		/* Remove ISNS_EVT_TIMER_RECON from kqueue */
    479           1.1     agc 		rv = isns_change_kevent_list(cfg_p,
    480           1.1     agc 		    (uintptr_t)ISNS_EVT_TIMER_RECON, EVFILT_TIMER, EV_DELETE,
    481           1.1     agc 		    (int64_t)0, (intptr_t)0);
    482           1.1     agc 		if (rv == -1)
    483           1.1     agc 			DBG("isns_kevent_timer_recon: error on "
    484           1.1     agc 			    "isns_change_kevent_list(1)\n");
    485           1.1     agc 
    486           1.1     agc 		cfg_p->sd_connected = 1;
    487           1.1     agc 
    488           1.1     agc 		/* Add cfg_p->sd to kqueue */
    489           1.1     agc 		rv = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->sd,
    490           1.1     agc 		    EVFILT_READ, EV_ADD | EV_CLEAR, (int64_t)0,
    491           1.1     agc 		    (intptr_t)isns_kevent_socket);
    492           1.1     agc 		if (rv == -1)
    493           1.1     agc 			DBG("isns_kevent_timer_recon: error on "
    494           1.1     agc 			    "isns_change_kevent_list(2)\n");
    495           1.1     agc 
    496           1.1     agc 		isns_end_task(cfg_p->curtask_p);
    497           1.1     agc 	}
    498           1.1     agc 
    499           1.1     agc 	return 0;
    500           1.1     agc }
    501           1.1     agc 
    502           1.1     agc 
    503           1.1     agc /* ARGSUSED */
    504           1.1     agc /*
    505           1.1     agc  * isns_kevent_timer_refresh
    506           1.1     agc  */
    507           1.1     agc int
    508           1.1     agc isns_kevent_timer_refresh(struct kevent* evt_p, struct isns_config_s *cfg_p)
    509           1.1     agc {
    510           1.1     agc 	struct isns_refresh_s *ref_p;
    511           1.1     agc 	ISNS_TRANS trans;
    512           1.1     agc 	uint32_t status;
    513           1.1     agc 	int rval;
    514           1.1     agc 
    515           1.1     agc 	DBG("isns_kevent_timer_refresh: entered\n");
    516           1.1     agc 
    517           1.1     agc 	/* If refresh info pointer NULL, or no name assigned, just return. */
    518           1.1     agc 	ref_p = cfg_p->refresh_p;
    519           1.1     agc 	if ((ref_p == NULL) || (ref_p->node[0] == '\0'))
    520           1.1     agc 	    	return 0;
    521           1.1     agc 
    522           1.1     agc 	if (ref_p->trans_p != NULL) {
    523           1.1     agc 		/* If the previous refresh trans is not complete, return. */
    524           1.1     agc 		rval = isns_get_pdu_response_status(ref_p->trans_p, &status);
    525           1.1     agc 		if (rval == EPERM) {
    526           1.1     agc 			DBG("isns_kevent_timer_refresh: "
    527           1.1     agc 			    "prev refresh trans not complete\n");
    528           1.1     agc 			return 0;
    529           1.1     agc 		}
    530           1.1     agc 		/* Free previous refresh trans. */
    531           1.1     agc 		isns_free_trans(ref_p->trans_p);
    532           1.1     agc 		ref_p->trans_p = NULL;
    533           1.1     agc 	}
    534           1.1     agc 
    535           1.1     agc 	/* Build new refresh transaction and send it. */
    536           1.1     agc 	trans = isns_new_trans((ISNS_HANDLE)cfg_p, isnsp_DevAttrQry, 0);
    537           1.1     agc 	if (trans == ISNS_INVALID_TRANS) {
    538           1.1     agc 		DBG("isns_kevent_timer_refresh: error on isns_new_trans()\n");
    539           1.1     agc 		return 0;
    540           1.1     agc 	}
    541           1.1     agc 
    542           1.1     agc 	ref_p->trans_p = (struct isns_trans_s *)trans;
    543           1.1     agc 	/* First we add our source attribute */
    544           1.1     agc 	isns_add_string(trans, isnst_iSCSIName, ref_p->node);
    545           1.1     agc 	/* Now add our message attribute */
    546           1.1     agc 	isns_add_string(trans, isnst_iSCSIName, ref_p->node);
    547           1.1     agc 	isns_add_tlv(trans, isnst_Delimiter, 0, NULL);
    548           1.1     agc 	/* and finally the operating attributes */
    549           1.1     agc 	isns_add_tlv(trans, isnst_EID, 0, NULL);
    550           1.1     agc 	isns_send_trans(trans, NULL, NULL);
    551           1.1     agc 
    552           1.1     agc 	return 0;
    553           1.1     agc }
    554