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