xref: /netbsd-src/lib/libisns/isns_task.c (revision dc2ecebec96795469eed09503b4155a9974a9910)
1*dc2ecebeSagc /*	$NetBSD: isns_task.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $	*/
2*dc2ecebeSagc 
3*dc2ecebeSagc /*-
4*dc2ecebeSagc  * Copyright (c) 2004,2009 The NetBSD Foundation, Inc.
5*dc2ecebeSagc  * All rights reserved.
6*dc2ecebeSagc  *
7*dc2ecebeSagc  * This code is derived from software contributed to The NetBSD Foundation
8*dc2ecebeSagc  * by Wasabi Systems, Inc.
9*dc2ecebeSagc  *
10*dc2ecebeSagc  * Redistribution and use in source and binary forms, with or without
11*dc2ecebeSagc  * modification, are permitted provided that the following conditions
12*dc2ecebeSagc  * are met:
13*dc2ecebeSagc  * 1. Redistributions of source code must retain the above copyright
14*dc2ecebeSagc  *    notice, this list of conditions and the following disclaimer.
15*dc2ecebeSagc  * 2. Redistributions in binary form must reproduce the above copyright
16*dc2ecebeSagc  *    notice, this list of conditions and the following disclaimer in the
17*dc2ecebeSagc  *    documentation and/or other materials provided with the distribution.
18*dc2ecebeSagc  *
19*dc2ecebeSagc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*dc2ecebeSagc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*dc2ecebeSagc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*dc2ecebeSagc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*dc2ecebeSagc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*dc2ecebeSagc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*dc2ecebeSagc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*dc2ecebeSagc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*dc2ecebeSagc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*dc2ecebeSagc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*dc2ecebeSagc  * POSSIBILITY OF SUCH DAMAGE.
30*dc2ecebeSagc  */
31*dc2ecebeSagc 
32*dc2ecebeSagc #include <sys/cdefs.h>
33*dc2ecebeSagc __RCSID("$NetBSD: isns_task.c,v 1.1.1.1 2011/01/16 01:22:50 agc Exp $");
34*dc2ecebeSagc 
35*dc2ecebeSagc /*
36*dc2ecebeSagc  * isns_task.c
37*dc2ecebeSagc  */
38*dc2ecebeSagc 
39*dc2ecebeSagc #include <sys/types.h>
40*dc2ecebeSagc #include <sys/socket.h>
41*dc2ecebeSagc #include <netinet/in.h>
42*dc2ecebeSagc 
43*dc2ecebeSagc #include "isns.h"
44*dc2ecebeSagc #include "isns_config.h"
45*dc2ecebeSagc 
46*dc2ecebeSagc static struct iovec write_buf[2 + (ISNS_MAX_PDU_PAYLOAD / ISNS_BUF_SIZE) +
47*dc2ecebeSagc     ((ISNS_MAX_PDU_PAYLOAD % ISNS_BUF_SIZE) != 0)];
48*dc2ecebeSagc 
49*dc2ecebeSagc static isns_task_handler isns_task_discover_server;
50*dc2ecebeSagc static isns_task_handler isns_task_reconnect_server;
51*dc2ecebeSagc static isns_task_handler isns_task_send_pdu;
52*dc2ecebeSagc static isns_task_handler isns_task_init_socket_io;
53*dc2ecebeSagc static isns_task_handler isns_task_init_refresh;
54*dc2ecebeSagc 
55*dc2ecebeSagc 
56*dc2ecebeSagc void
isns_run_task(struct isns_task_s * task_p)57*dc2ecebeSagc isns_run_task(struct isns_task_s *task_p)
58*dc2ecebeSagc {
59*dc2ecebeSagc 	static isns_task_handler *task_dispatch_table[ISNS_NUM_TASKS] = {
60*dc2ecebeSagc 		isns_task_discover_server,
61*dc2ecebeSagc 		isns_task_reconnect_server,
62*dc2ecebeSagc 		isns_task_send_pdu,
63*dc2ecebeSagc 		isns_task_init_socket_io,
64*dc2ecebeSagc 		isns_task_init_refresh
65*dc2ecebeSagc 	};
66*dc2ecebeSagc 
67*dc2ecebeSagc 	DBG("isns_run_task: task_type=%d\n", task_p->task_type);
68*dc2ecebeSagc 
69*dc2ecebeSagc 	if (task_p->task_type < ARRAY_ELEMS(task_dispatch_table))
70*dc2ecebeSagc 		task_dispatch_table[task_p->task_type](task_p);
71*dc2ecebeSagc 	else
72*dc2ecebeSagc 		DBG("isns_run_task: unknown task type=%d\n", task_p->task_type);
73*dc2ecebeSagc }
74*dc2ecebeSagc 
75*dc2ecebeSagc 
76*dc2ecebeSagc int
isns_wait_task(struct isns_task_s * task_p,const struct timespec * timeout_p)77*dc2ecebeSagc isns_wait_task(struct isns_task_s *task_p, const struct timespec *timeout_p)
78*dc2ecebeSagc {
79*dc2ecebeSagc 	struct timeval tv_now;
80*dc2ecebeSagc 	struct timespec ts_abstime;
81*dc2ecebeSagc 	int rval;
82*dc2ecebeSagc 
83*dc2ecebeSagc 	DBG("isns_wait_task: waitable=%d\n", task_p->waitable);
84*dc2ecebeSagc 
85*dc2ecebeSagc 	if (!task_p->waitable)
86*dc2ecebeSagc 		return EPERM;
87*dc2ecebeSagc 
88*dc2ecebeSagc 	pthread_mutex_lock(&task_p->wait_mutex);
89*dc2ecebeSagc 
90*dc2ecebeSagc 	if (timeout_p == NULL) {
91*dc2ecebeSagc 		rval = pthread_cond_wait(&task_p->wait_condvar,
92*dc2ecebeSagc 		    &task_p->wait_mutex);
93*dc2ecebeSagc 	} else {
94*dc2ecebeSagc 		gettimeofday(&tv_now, NULL);
95*dc2ecebeSagc 		TIMEVAL_TO_TIMESPEC(&tv_now, &ts_abstime);
96*dc2ecebeSagc 		timespecadd(&ts_abstime, timeout_p, &ts_abstime);
97*dc2ecebeSagc 
98*dc2ecebeSagc 		rval = pthread_cond_timedwait(&task_p->wait_condvar,
99*dc2ecebeSagc 		    &task_p->wait_mutex, &ts_abstime);
100*dc2ecebeSagc 	}
101*dc2ecebeSagc 
102*dc2ecebeSagc 	pthread_mutex_unlock(&task_p->wait_mutex);
103*dc2ecebeSagc 
104*dc2ecebeSagc 	isns_free_task(task_p);
105*dc2ecebeSagc 
106*dc2ecebeSagc 	DBG("isns_wait_task: wait done (rval=%d)\n", rval);
107*dc2ecebeSagc 
108*dc2ecebeSagc 	return rval;
109*dc2ecebeSagc }
110*dc2ecebeSagc 
111*dc2ecebeSagc 
112*dc2ecebeSagc void
isns_end_task(struct isns_task_s * task_p)113*dc2ecebeSagc isns_end_task(struct isns_task_s *task_p)
114*dc2ecebeSagc {
115*dc2ecebeSagc 	DBG("isns_end_task: %p\n", task_p);
116*dc2ecebeSagc 	if (task_p == task_p->cfg_p->curtask_p)
117*dc2ecebeSagc 		task_p->cfg_p->curtask_p = NULL;
118*dc2ecebeSagc 
119*dc2ecebeSagc 	if (task_p->waitable)
120*dc2ecebeSagc 		pthread_cond_signal(&task_p->wait_condvar);
121*dc2ecebeSagc 
122*dc2ecebeSagc 	isns_free_task(task_p);
123*dc2ecebeSagc }
124*dc2ecebeSagc 
125*dc2ecebeSagc 
126*dc2ecebeSagc static void
isns_task_discover_server(struct isns_task_s * task_p)127*dc2ecebeSagc isns_task_discover_server(struct isns_task_s *task_p)
128*dc2ecebeSagc {
129*dc2ecebeSagc 	/* discover server here */
130*dc2ecebeSagc 	DBG("isns_task_discover_server: entered\n");
131*dc2ecebeSagc 
132*dc2ecebeSagc 	isns_end_task(task_p);
133*dc2ecebeSagc }
134*dc2ecebeSagc 
135*dc2ecebeSagc 
136*dc2ecebeSagc /*
137*dc2ecebeSagc  * isns_task_reconnect_server()
138*dc2ecebeSagc  */
139*dc2ecebeSagc static void
isns_task_reconnect_server(struct isns_task_s * task_p)140*dc2ecebeSagc isns_task_reconnect_server(struct isns_task_s *task_p)
141*dc2ecebeSagc {
142*dc2ecebeSagc 	struct addrinfo *ai_p;
143*dc2ecebeSagc 	int rv;
144*dc2ecebeSagc 
145*dc2ecebeSagc 
146*dc2ecebeSagc 	DBG("isns_task_reconnect_server: entered\n");
147*dc2ecebeSagc 
148*dc2ecebeSagc 	ai_p = task_p->var.reconnect_server.ai_p;
149*dc2ecebeSagc 
150*dc2ecebeSagc 	rv = isns_socket_create(&(task_p->cfg_p->sd), ai_p->ai_family,
151*dc2ecebeSagc 	    ai_p->ai_socktype);
152*dc2ecebeSagc 	if (rv != 0)
153*dc2ecebeSagc 		return;
154*dc2ecebeSagc 
155*dc2ecebeSagc 	rv = isns_socket_connect(task_p->cfg_p->sd, ai_p->ai_addr,
156*dc2ecebeSagc 	    ai_p->ai_addrlen);
157*dc2ecebeSagc 	if (rv != 0) {
158*dc2ecebeSagc 		/* Add ISNS_EVT_TIMER_RECON to kqueue */
159*dc2ecebeSagc 		rv = isns_change_kevent_list(task_p->cfg_p,
160*dc2ecebeSagc 		    (uintptr_t)ISNS_EVT_TIMER_RECON, EVFILT_TIMER, EV_ADD,
161*dc2ecebeSagc 		    (int64_t)ISNS_EVT_TIMER_RECON_PERIOD_MS,
162*dc2ecebeSagc 		    (intptr_t)isns_kevent_timer_recon);
163*dc2ecebeSagc 		if (rv == -1)
164*dc2ecebeSagc 			DBG("isns_task_reconnect_server: error on "
165*dc2ecebeSagc 			    "isns_change_kevent_list(1)\n");
166*dc2ecebeSagc 	} else {
167*dc2ecebeSagc 		task_p->cfg_p->sd_connected = 1;
168*dc2ecebeSagc 
169*dc2ecebeSagc 		/* Add cfg_p->sd to kqueue */
170*dc2ecebeSagc 		rv = isns_change_kevent_list(task_p->cfg_p,
171*dc2ecebeSagc 		    (uintptr_t)(task_p->cfg_p->sd), EVFILT_READ,
172*dc2ecebeSagc 		    EV_ADD | EV_CLEAR, (int64_t)0,
173*dc2ecebeSagc 		    (intptr_t)isns_kevent_socket);
174*dc2ecebeSagc 		if (rv == -1)
175*dc2ecebeSagc 			DBG("isns_task_reconnect_server: error on "
176*dc2ecebeSagc 			    "isns_change_kevent_lists(2)\n");
177*dc2ecebeSagc 
178*dc2ecebeSagc 		isns_end_task(task_p);
179*dc2ecebeSagc 	}
180*dc2ecebeSagc }
181*dc2ecebeSagc 
182*dc2ecebeSagc /*
183*dc2ecebeSagc  * isns_task_send_pdu()
184*dc2ecebeSagc  *
185*dc2ecebeSagc  * We send all of the pdu's associated with transaction task_p->trans_p here.
186*dc2ecebeSagc  *
187*dc2ecebeSagc  * Assumptions:
188*dc2ecebeSagc  *	(1) task_p->trans_p->pdu_req_list is an ordered (seq_id) list of
189*dc2ecebeSagc  *	    related (trans_id), appropriately sized pdus to be sent. The first
190*dc2ecebeSagc  *	    pdu has flag ISNS_FLAG_FIRST_PDU set and the last pdu has flag
191*dc2ecebeSagc  *	    ISNS_FLAG_LAST_PDU set.
192*dc2ecebeSagc  */
193*dc2ecebeSagc static void
isns_task_send_pdu(struct isns_task_s * task_p)194*dc2ecebeSagc isns_task_send_pdu(struct isns_task_s *task_p)
195*dc2ecebeSagc {
196*dc2ecebeSagc 	struct iovec *iovp;
197*dc2ecebeSagc 	struct isns_config_s *cfg_p;
198*dc2ecebeSagc 	struct isns_pdu_s *pdu_p; /* points to first pdu in pdu_req_list */
199*dc2ecebeSagc 	struct isns_buffer_s *buf_p;
200*dc2ecebeSagc 	ssize_t bytes_written;
201*dc2ecebeSagc 	ssize_t count;
202*dc2ecebeSagc 	size_t bytes_to_write;
203*dc2ecebeSagc 	int iovcnt, cur_iovec;
204*dc2ecebeSagc 	char *ptr;
205*dc2ecebeSagc 
206*dc2ecebeSagc 
207*dc2ecebeSagc 	DBG("isns_task_send_pdu: entered\n");
208*dc2ecebeSagc 
209*dc2ecebeSagc 	cfg_p = task_p->cfg_p;
210*dc2ecebeSagc 	pdu_p = task_p->var.send_pdu.pdu_p;
211*dc2ecebeSagc 
212*dc2ecebeSagc 	while (pdu_p != NULL) {
213*dc2ecebeSagc 		/* adjust byte order if necessary */
214*dc2ecebeSagc 		if (pdu_p->byteorder_host) {
215*dc2ecebeSagc 			pdu_p->hdr.isnsp_version = isns_htons(pdu_p->hdr.
216*dc2ecebeSagc 			    isnsp_version);
217*dc2ecebeSagc 			pdu_p->hdr.func_id = isns_htons(pdu_p->hdr.func_id);
218*dc2ecebeSagc 			pdu_p->hdr.payload_len = isns_htons(pdu_p->hdr.
219*dc2ecebeSagc 			    payload_len);
220*dc2ecebeSagc 			pdu_p->hdr.flags = isns_htons(pdu_p->hdr.flags);
221*dc2ecebeSagc 			pdu_p->hdr.trans_id = isns_htons(pdu_p->hdr.trans_id);
222*dc2ecebeSagc 			pdu_p->hdr.seq_id = isns_htons(pdu_p->hdr.seq_id);
223*dc2ecebeSagc 
224*dc2ecebeSagc 			pdu_p->byteorder_host = 0;
225*dc2ecebeSagc 		}
226*dc2ecebeSagc 		DUMP_PDU(pdu_p);
227*dc2ecebeSagc 
228*dc2ecebeSagc 		/* send PDU via socket here */
229*dc2ecebeSagc 		write_buf[0].iov_base = &(pdu_p->hdr);
230*dc2ecebeSagc 		write_buf[0].iov_len = sizeof(pdu_p->hdr);
231*dc2ecebeSagc 		bytes_to_write = write_buf[0].iov_len;
232*dc2ecebeSagc 		iovcnt = 1;
233*dc2ecebeSagc 
234*dc2ecebeSagc 		buf_p = pdu_p->payload_p;
235*dc2ecebeSagc 		while (buf_p != NULL) {
236*dc2ecebeSagc 			write_buf[iovcnt].iov_base = isns_buffer_data(buf_p,0);
237*dc2ecebeSagc 			write_buf[iovcnt].iov_len = buf_p->cur_len;
238*dc2ecebeSagc 			bytes_to_write += write_buf[iovcnt].iov_len;
239*dc2ecebeSagc 			iovcnt++;
240*dc2ecebeSagc 			buf_p = buf_p->next;
241*dc2ecebeSagc 		}
242*dc2ecebeSagc 
243*dc2ecebeSagc 		/* iovcnt and bytes_to_write are initialized */
244*dc2ecebeSagc 		cur_iovec = 0;
245*dc2ecebeSagc 		buf_p = ((struct isns_buffer_s *)(void *)pdu_p) - 1;
246*dc2ecebeSagc 		do {
247*dc2ecebeSagc 			iovp = &(write_buf[cur_iovec]);
248*dc2ecebeSagc 			bytes_written = isns_socket_writev(cfg_p->sd, iovp,
249*dc2ecebeSagc 			    iovcnt);
250*dc2ecebeSagc 			if (bytes_written == -1) {
251*dc2ecebeSagc 				DBG("isns_task_send_pdu: error on "
252*dc2ecebeSagc 			    	"isns_socket_writev\n");
253*dc2ecebeSagc 				isns_socket_close(cfg_p->sd);
254*dc2ecebeSagc 				cfg_p->sd_connected = 0;
255*dc2ecebeSagc 
256*dc2ecebeSagc 				isns_process_connection_loss(cfg_p);
257*dc2ecebeSagc 
258*dc2ecebeSagc 				if (cfg_p->pdu_in_p != NULL) {
259*dc2ecebeSagc 					isns_free_pdu(cfg_p->pdu_in_p);
260*dc2ecebeSagc 					cfg_p->pdu_in_p = NULL;
261*dc2ecebeSagc 				}
262*dc2ecebeSagc 
263*dc2ecebeSagc 				break;
264*dc2ecebeSagc 			}
265*dc2ecebeSagc 
266*dc2ecebeSagc 			if (bytes_written < (ssize_t)bytes_to_write) {
267*dc2ecebeSagc 				count = bytes_written;
268*dc2ecebeSagc 				while (buf_p != NULL) { /* -OR- while (1) */
269*dc2ecebeSagc 					if ((unsigned)count >= write_buf[
270*dc2ecebeSagc 					    cur_iovec].iov_len) {
271*dc2ecebeSagc 						count -= write_buf[cur_iovec].
272*dc2ecebeSagc 						    iov_len;
273*dc2ecebeSagc 						if (cur_iovec == 0)
274*dc2ecebeSagc 							buf_p = pdu_p->
275*dc2ecebeSagc 							    payload_p;
276*dc2ecebeSagc 						else
277*dc2ecebeSagc 							buf_p = buf_p->next;
278*dc2ecebeSagc 						cur_iovec++;
279*dc2ecebeSagc 						iovcnt--;
280*dc2ecebeSagc 
281*dc2ecebeSagc 						if (count == 0) {
282*dc2ecebeSagc 							/* Do another write */
283*dc2ecebeSagc 							break;
284*dc2ecebeSagc 						} else {
285*dc2ecebeSagc 							/* Look at new iovec */
286*dc2ecebeSagc 							continue;
287*dc2ecebeSagc 						}
288*dc2ecebeSagc 					} else {
289*dc2ecebeSagc 						write_buf[cur_iovec].iov_len -=
290*dc2ecebeSagc 						    count;
291*dc2ecebeSagc 
292*dc2ecebeSagc 						ptr = (char *) write_buf[cur_iovec].iov_base;
293*dc2ecebeSagc 						ptr += count;
294*dc2ecebeSagc 						write_buf[cur_iovec].iov_base = ptr;
295*dc2ecebeSagc 
296*dc2ecebeSagc 						/* Do another write */
297*dc2ecebeSagc 						break;
298*dc2ecebeSagc 					}
299*dc2ecebeSagc 				}
300*dc2ecebeSagc 			}
301*dc2ecebeSagc 
302*dc2ecebeSagc 			bytes_to_write -= bytes_written;
303*dc2ecebeSagc 		} while (bytes_to_write);
304*dc2ecebeSagc 
305*dc2ecebeSagc 		pdu_p = pdu_p->next;
306*dc2ecebeSagc 	}
307*dc2ecebeSagc 
308*dc2ecebeSagc 	if (!task_p->waitable) {
309*dc2ecebeSagc 		isns_complete_trans(task_p->var.send_pdu.trans_p);
310*dc2ecebeSagc 		isns_end_task(task_p);
311*dc2ecebeSagc 	}
312*dc2ecebeSagc }
313*dc2ecebeSagc 
314*dc2ecebeSagc /*
315*dc2ecebeSagc  * isns_task_init_socket_io()
316*dc2ecebeSagc  */
317*dc2ecebeSagc static void
isns_task_init_socket_io(struct isns_task_s * task_p)318*dc2ecebeSagc isns_task_init_socket_io(struct isns_task_s *task_p)
319*dc2ecebeSagc {
320*dc2ecebeSagc 	struct isns_config_s *cfg_p;
321*dc2ecebeSagc 	int rv;
322*dc2ecebeSagc 
323*dc2ecebeSagc 
324*dc2ecebeSagc 	DBG("isns_task_init_socket_io: entered\n");
325*dc2ecebeSagc 
326*dc2ecebeSagc 	cfg_p = task_p->cfg_p;
327*dc2ecebeSagc 
328*dc2ecebeSagc 	if (cfg_p->sd_connected) {
329*dc2ecebeSagc 		isns_socket_close(cfg_p->sd);
330*dc2ecebeSagc 		cfg_p->sd_connected = 0;
331*dc2ecebeSagc 
332*dc2ecebeSagc 		/* We may have received part of an unsolicited/duplicate pdu */
333*dc2ecebeSagc 		if (cfg_p->pdu_in_p != NULL) {
334*dc2ecebeSagc 			isns_free_pdu(cfg_p->pdu_in_p);
335*dc2ecebeSagc 			cfg_p->pdu_in_p = NULL;
336*dc2ecebeSagc 		}
337*dc2ecebeSagc 	}
338*dc2ecebeSagc 
339*dc2ecebeSagc 	/* May have an allocated 'struct addrinfo', whether connected or not */
340*dc2ecebeSagc 	if (cfg_p->ai_p != NULL) {
341*dc2ecebeSagc 		isns_free(cfg_p->ai_p);
342*dc2ecebeSagc 		cfg_p->ai_p = NULL;
343*dc2ecebeSagc 	}
344*dc2ecebeSagc 
345*dc2ecebeSagc 	cfg_p->sd = task_p->var.init_socket_io.sd;
346*dc2ecebeSagc 	cfg_p->ai_p = task_p->var.init_socket_io.ai_p;
347*dc2ecebeSagc 
348*dc2ecebeSagc 	cfg_p->sd_connected = 1;
349*dc2ecebeSagc 
350*dc2ecebeSagc 	/* Add cfg_p->sd to kqueue */
351*dc2ecebeSagc 	rv = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->sd,
352*dc2ecebeSagc 	    EVFILT_READ, EV_ADD | EV_CLEAR, (int64_t)0,
353*dc2ecebeSagc 	    (intptr_t)isns_kevent_socket);
354*dc2ecebeSagc 	if (rv == -1)
355*dc2ecebeSagc 		DBG("isns_task_init_socket_io: error on "
356*dc2ecebeSagc 		    "isns_change_kevent_list\n");
357*dc2ecebeSagc 
358*dc2ecebeSagc 	isns_end_task(task_p);
359*dc2ecebeSagc }
360*dc2ecebeSagc 
361*dc2ecebeSagc 
362*dc2ecebeSagc /*
363*dc2ecebeSagc  * isns_task_init_refresh(struct isns_task_s *task_p)
364*dc2ecebeSagc  */
365*dc2ecebeSagc static void
isns_task_init_refresh(struct isns_task_s * task_p)366*dc2ecebeSagc isns_task_init_refresh(struct isns_task_s *task_p)
367*dc2ecebeSagc {
368*dc2ecebeSagc 	struct isns_config_s *cfg_p;
369*dc2ecebeSagc 	int rval;
370*dc2ecebeSagc 
371*dc2ecebeSagc 	DBG("isns_task_init_refresh: entered\n");
372*dc2ecebeSagc 
373*dc2ecebeSagc 	/* Free any previous refresh info. */
374*dc2ecebeSagc 	cfg_p = task_p->cfg_p;
375*dc2ecebeSagc 	if (cfg_p->refresh_p != NULL) {
376*dc2ecebeSagc 		if (cfg_p->refresh_p->trans_p != NULL)
377*dc2ecebeSagc 			isns_free_trans(cfg_p->refresh_p->trans_p);
378*dc2ecebeSagc 		isns_free(cfg_p->refresh_p);
379*dc2ecebeSagc 	}
380*dc2ecebeSagc 
381*dc2ecebeSagc 	/* Assign new refresh info into config struct. */
382*dc2ecebeSagc 	cfg_p->refresh_p = task_p->var.init_refresh.ref_p;
383*dc2ecebeSagc 	cfg_p->refresh_p->trans_p = NULL;
384*dc2ecebeSagc 
385*dc2ecebeSagc 	/* Setup (or change) kevent timer for reg refresh. */
386*dc2ecebeSagc 	rval = isns_change_kevent_list(cfg_p,
387*dc2ecebeSagc 	    (uintptr_t)ISNS_EVT_TIMER_REFRESH, EVFILT_TIMER,
388*dc2ecebeSagc 	    EV_ADD | EV_ENABLE, (int64_t)cfg_p->refresh_p->interval * 1000,
389*dc2ecebeSagc 	    (intptr_t)isns_kevent_timer_refresh);
390*dc2ecebeSagc 	if (rval == -1) {
391*dc2ecebeSagc 		DBG("isns_task_init_refresh: "
392*dc2ecebeSagc 		    "error on isns_change_kevent_list()\n");
393*dc2ecebeSagc 	}
394*dc2ecebeSagc 
395*dc2ecebeSagc 	isns_end_task(task_p);
396*dc2ecebeSagc }
397*dc2ecebeSagc 
398*dc2ecebeSagc 
399*dc2ecebeSagc struct isns_task_s *
isns_new_task(struct isns_config_s * cfg_p,uint8_t task_type,int waitable)400*dc2ecebeSagc isns_new_task(struct isns_config_s *cfg_p, uint8_t task_type, int waitable)
401*dc2ecebeSagc {
402*dc2ecebeSagc 	struct isns_buffer_s *buf_p;
403*dc2ecebeSagc 	struct isns_task_s *task_p;
404*dc2ecebeSagc 	pthread_mutexattr_t mutexattr;
405*dc2ecebeSagc 	pthread_condattr_t condattr;
406*dc2ecebeSagc 
407*dc2ecebeSagc 	task_p = NULL;
408*dc2ecebeSagc 	buf_p = isns_new_buffer((int)sizeof(struct isns_task_s));
409*dc2ecebeSagc 	if (buf_p) {
410*dc2ecebeSagc 		task_p = (struct isns_task_s *)isns_buffer_data(buf_p, 0);
411*dc2ecebeSagc 		task_p->cfg_p = cfg_p;
412*dc2ecebeSagc 		task_p->task_type = task_type;
413*dc2ecebeSagc 		task_p->waitable = waitable;
414*dc2ecebeSagc 
415*dc2ecebeSagc 		if (waitable) {
416*dc2ecebeSagc 			pthread_mutexattr_init(&mutexattr);
417*dc2ecebeSagc 			pthread_mutexattr_settype(&mutexattr,
418*dc2ecebeSagc 			    ISNS_MUTEX_TYPE_NORMAL);
419*dc2ecebeSagc 			pthread_mutex_init(&task_p->wait_mutex, &mutexattr);
420*dc2ecebeSagc 
421*dc2ecebeSagc 			pthread_condattr_init(&condattr);
422*dc2ecebeSagc 			pthread_cond_init(&task_p->wait_condvar, &condattr);
423*dc2ecebeSagc 			task_p->wait_ref_count = 2;
424*dc2ecebeSagc 		}
425*dc2ecebeSagc 	}
426*dc2ecebeSagc 
427*dc2ecebeSagc 	DBG("isns_new_task: %p, waitable=%d\n", task_p, waitable);
428*dc2ecebeSagc 
429*dc2ecebeSagc 	return task_p;
430*dc2ecebeSagc }
431*dc2ecebeSagc 
432*dc2ecebeSagc 
433*dc2ecebeSagc void
isns_free_task(struct isns_task_s * task_p)434*dc2ecebeSagc isns_free_task(struct isns_task_s *task_p)
435*dc2ecebeSagc {
436*dc2ecebeSagc 	struct isns_buffer_s *buf_p;
437*dc2ecebeSagc 	int ref_count;
438*dc2ecebeSagc 
439*dc2ecebeSagc 	DBG("isns_free_task: %p\n", task_p);
440*dc2ecebeSagc 	if (task_p->waitable) {
441*dc2ecebeSagc 		pthread_mutex_lock(&task_p->wait_mutex);
442*dc2ecebeSagc 		ref_count = --task_p->wait_ref_count;
443*dc2ecebeSagc 		pthread_mutex_unlock(&task_p->wait_mutex);
444*dc2ecebeSagc 
445*dc2ecebeSagc 		if (ref_count > 0) {
446*dc2ecebeSagc 			DBG("isns_free_task: ref_count > 0, no free done\n");
447*dc2ecebeSagc 			return;
448*dc2ecebeSagc 		}
449*dc2ecebeSagc 
450*dc2ecebeSagc 		pthread_mutex_destroy(&task_p->wait_mutex);
451*dc2ecebeSagc 		pthread_cond_destroy(&task_p->wait_condvar);
452*dc2ecebeSagc 	}
453*dc2ecebeSagc 	buf_p = ((struct isns_buffer_s *)(void *)(task_p))-1;
454*dc2ecebeSagc 	isns_free_buffer(buf_p);
455*dc2ecebeSagc }
456*dc2ecebeSagc 
457*dc2ecebeSagc 
458*dc2ecebeSagc void
isns_taskq_insert_head(struct isns_config_s * cfg_p,struct isns_task_s * task_p)459*dc2ecebeSagc isns_taskq_insert_head(struct isns_config_s *cfg_p,
460*dc2ecebeSagc     struct isns_task_s *task_p)
461*dc2ecebeSagc {
462*dc2ecebeSagc 	pthread_mutex_lock(&cfg_p->taskq_mutex);
463*dc2ecebeSagc 	SIMPLEQ_INSERT_HEAD(&cfg_p->taskq_head, task_p, taskq_entry);
464*dc2ecebeSagc 	pthread_mutex_unlock(&cfg_p->taskq_mutex);
465*dc2ecebeSagc 
466*dc2ecebeSagc 	DBG("isns_taskq_insert_head: %p\n", task_p);
467*dc2ecebeSagc }
468*dc2ecebeSagc 
469*dc2ecebeSagc 
470*dc2ecebeSagc void
isns_taskq_insert_tail(struct isns_config_s * cfg_p,struct isns_task_s * task_p)471*dc2ecebeSagc isns_taskq_insert_tail(struct isns_config_s *cfg_p,
472*dc2ecebeSagc     struct isns_task_s *task_p)
473*dc2ecebeSagc {
474*dc2ecebeSagc 	pthread_mutex_lock(&cfg_p->taskq_mutex);
475*dc2ecebeSagc 	SIMPLEQ_INSERT_TAIL(&cfg_p->taskq_head, task_p, taskq_entry);
476*dc2ecebeSagc 	pthread_mutex_unlock(&cfg_p->taskq_mutex);
477*dc2ecebeSagc 
478*dc2ecebeSagc 	DBG("isns_taskq_insert_tail: %p\n", task_p);
479*dc2ecebeSagc }
480*dc2ecebeSagc 
481*dc2ecebeSagc 
482*dc2ecebeSagc struct isns_task_s *
isns_taskq_remove(struct isns_config_s * cfg_p)483*dc2ecebeSagc isns_taskq_remove(struct isns_config_s *cfg_p)
484*dc2ecebeSagc {
485*dc2ecebeSagc 	struct isns_task_s *task_p = NULL;
486*dc2ecebeSagc 
487*dc2ecebeSagc 	pthread_mutex_lock(&cfg_p->taskq_mutex);
488*dc2ecebeSagc 	if ((task_p = SIMPLEQ_FIRST(&cfg_p->taskq_head)) != NULL)
489*dc2ecebeSagc 		SIMPLEQ_REMOVE_HEAD(&cfg_p->taskq_head, taskq_entry);
490*dc2ecebeSagc 	pthread_mutex_unlock(&cfg_p->taskq_mutex);
491*dc2ecebeSagc 
492*dc2ecebeSagc 	DBG("isns_taskq_remove: %p\n", task_p);
493*dc2ecebeSagc 
494*dc2ecebeSagc 	return task_p;
495*dc2ecebeSagc }
496*dc2ecebeSagc 
497*dc2ecebeSagc 
498*dc2ecebeSagc struct isns_task_s *
isns_taskq_remove_trans(struct isns_config_s * cfg_p,uint16_t trans_id)499*dc2ecebeSagc isns_taskq_remove_trans(struct isns_config_s *cfg_p, uint16_t trans_id)
500*dc2ecebeSagc {
501*dc2ecebeSagc 	struct isns_task_s *task_p;
502*dc2ecebeSagc 	int trans_found;
503*dc2ecebeSagc 
504*dc2ecebeSagc 	trans_found = 0;
505*dc2ecebeSagc 	pthread_mutex_lock(&cfg_p->taskq_mutex);
506*dc2ecebeSagc 	SIMPLEQ_FOREACH(task_p, &cfg_p->taskq_head, taskq_entry) {
507*dc2ecebeSagc 		if ((task_p->task_type == ISNS_TASK_SEND_PDU)
508*dc2ecebeSagc 		    && (task_p->var.send_pdu.trans_p->id == trans_id)) {
509*dc2ecebeSagc 			trans_found = 1;
510*dc2ecebeSagc 			break;
511*dc2ecebeSagc 		}
512*dc2ecebeSagc 	}
513*dc2ecebeSagc 	if (trans_found) {
514*dc2ecebeSagc 		SIMPLEQ_REMOVE(&cfg_p->taskq_head, task_p, isns_task_s,
515*dc2ecebeSagc 		    taskq_entry);
516*dc2ecebeSagc 	}
517*dc2ecebeSagc 	pthread_mutex_unlock(&cfg_p->taskq_mutex);
518*dc2ecebeSagc 
519*dc2ecebeSagc 	return (trans_found ? task_p : NULL);
520*dc2ecebeSagc }
521