isns_thread.c revision 1.1 1 1.1 agc /* $NetBSD: isns_thread.c,v 1.1 2011/01/16 01:22:50 agc 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 agc __RCSID("$NetBSD: isns_thread.c,v 1.1 2011/01/16 01:22:50 agc 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 agc if ((rbytes < 0) && (rbytes == sizeof(trans_id)))
156 1.1 agc isns_abort_trans(cfg_p, trans_id);
157 1.1 agc else
158 1.1 agc DBG("isns_kevent_pipe: "
159 1.1 agc "error reading trans id\n");
160 1.1 agc pipe_nbytes -= (int)rbytes;
161 1.1 agc break;
162 1.1 agc
163 1.1 agc case ISNS_CMD_STOP:
164 1.1 agc DBG("isns_kevent_pipe: ISNS_CMD_STOP\n");
165 1.1 agc force_isns_stop = 1;
166 1.1 agc pipe_nbytes = 0;
167 1.1 agc break;
168 1.1 agc
169 1.1 agc default:
170 1.1 agc DBG("isns_kevent_pipe: unknown command (cmd=%d)\n",
171 1.1 agc cmd_type);
172 1.1 agc break;
173 1.1 agc }
174 1.1 agc }
175 1.1 agc
176 1.1 agc return (force_isns_stop ? 1 : 0);
177 1.1 agc }
178 1.1 agc
179 1.1 agc /*
180 1.1 agc * isns_is_trans_complete()
181 1.1 agc */
182 1.1 agc static int
183 1.1 agc isns_is_trans_complete(struct isns_trans_s *trans_p)
184 1.1 agc {
185 1.1 agc struct isns_pdu_s *pdu_p;
186 1.1 agc uint16_t count;
187 1.1 agc
188 1.1 agc pdu_p = trans_p->pdu_rsp_list;
189 1.1 agc count = 0;
190 1.1 agc while (pdu_p->next != NULL) {
191 1.1 agc if (pdu_p->hdr.seq_id != count++) return 0;
192 1.1 agc pdu_p = pdu_p->next;
193 1.1 agc }
194 1.1 agc if ((pdu_p->hdr.seq_id != count) ||
195 1.1 agc !(pdu_p->hdr.flags & ISNS_FLAG_LAST_PDU))
196 1.1 agc return 0;
197 1.1 agc
198 1.1 agc return 1;
199 1.1 agc }
200 1.1 agc
201 1.1 agc /*
202 1.1 agc * isns_is_valid_resp()
203 1.1 agc */
204 1.1 agc static int
205 1.1 agc isns_is_valid_resp(struct isns_trans_s *trans_p, struct isns_pdu_s *pdu_p)
206 1.1 agc {
207 1.1 agc struct isns_pdu_s *curpdu_p;
208 1.1 agc
209 1.1 agc if (pdu_p->hdr.trans_id != trans_p->id)
210 1.1 agc return 0;
211 1.1 agc if (pdu_p->hdr.func_id != (trans_p->func_id | 0x8000))
212 1.1 agc return 0;
213 1.1 agc curpdu_p = trans_p->pdu_rsp_list;
214 1.1 agc while (curpdu_p != NULL) {
215 1.1 agc if (curpdu_p->hdr.seq_id == pdu_p->hdr.seq_id) return 0;
216 1.1 agc curpdu_p = curpdu_p->next;
217 1.1 agc }
218 1.1 agc
219 1.1 agc return 1;
220 1.1 agc }
221 1.1 agc
222 1.1 agc /*
223 1.1 agc * isns_process_in_pdu()
224 1.1 agc */
225 1.1 agc static void
226 1.1 agc isns_process_in_pdu(struct isns_config_s *cfg_p)
227 1.1 agc {
228 1.1 agc struct isns_task_s *curtask_p;
229 1.1 agc struct isns_trans_s *trans_p;
230 1.1 agc
231 1.1 agc DBG("isns_process_in_pdu: entered\n");
232 1.1 agc
233 1.1 agc if ((curtask_p = cfg_p->curtask_p) == NULL)
234 1.1 agc isns_free_pdu(cfg_p->pdu_in_p);
235 1.1 agc else if ((trans_p = curtask_p->var.send_pdu.trans_p) == NULL)
236 1.1 agc isns_free_pdu(cfg_p->pdu_in_p);
237 1.1 agc else if (!isns_is_valid_resp(trans_p, cfg_p->pdu_in_p))
238 1.1 agc isns_free_pdu(cfg_p->pdu_in_p);
239 1.1 agc else {
240 1.1 agc isns_add_pdu_response(trans_p, cfg_p->pdu_in_p);
241 1.1 agc
242 1.1 agc if (isns_is_trans_complete(trans_p)) {
243 1.1 agc isns_complete_trans(trans_p);
244 1.1 agc isns_end_task(curtask_p);
245 1.1 agc }
246 1.1 agc }
247 1.1 agc
248 1.1 agc cfg_p->pdu_in_p = NULL;
249 1.1 agc }
250 1.1 agc
251 1.1 agc /*
252 1.1 agc * isns_kevent_socket()
253 1.1 agc */
254 1.1 agc int
255 1.1 agc isns_kevent_socket(struct kevent *evt_p, struct isns_config_s *cfg_p)
256 1.1 agc {
257 1.1 agc struct iovec *iovp;
258 1.1 agc struct isns_buffer_s *curbuf_p, *newbuf_p;
259 1.1 agc struct isns_pdu_s *pdu_p;
260 1.1 agc int64_t bavail; /* bytes available in socket buffer */
261 1.1 agc uint32_t cur_len, buf_len, unread_len, rd_len, b_len;
262 1.1 agc ssize_t rv;
263 1.1 agc uint16_t payload_len;
264 1.1 agc int iovcnt, more, transport_evt;
265 1.1 agc
266 1.1 agc
267 1.1 agc DBG("isns_kevent_socket: entered\n");
268 1.1 agc
269 1.1 agc transport_evt = 0;
270 1.1 agc bavail = evt_p->data;
271 1.1 agc iovp = read_buf;
272 1.1 agc
273 1.1 agc more = (bavail > 0);
274 1.1 agc while (more) {
275 1.1 agc if (cfg_p->pdu_in_p == NULL) {
276 1.1 agc /*
277 1.1 agc * Try to form a valid pdu by starting with the hdr.
278 1.1 agc * If there isn't enough data in the socket buffer
279 1.1 agc * to form a full hdr, just return.
280 1.1 agc *
281 1.1 agc * Once we have read in our hdr, allocate all buffers
282 1.1 agc * needed.
283 1.1 agc */
284 1.1 agc
285 1.1 agc if (bavail < (int64_t)sizeof(struct isns_pdu_hdr_s))
286 1.1 agc return 0;
287 1.1 agc
288 1.1 agc /* Form a placeholder pdu */
289 1.1 agc pdu_p = isns_new_pdu(cfg_p, 0, 0, 0);
290 1.1 agc
291 1.1 agc /* Read the header into our placeholder pdu */
292 1.1 agc read_buf[0].iov_base = &(pdu_p->hdr);
293 1.1 agc read_buf[0].iov_len = sizeof(struct isns_pdu_hdr_s);
294 1.1 agc iovcnt = 1;
295 1.1 agc
296 1.1 agc iovp = read_buf;
297 1.1 agc rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
298 1.1 agc if ((rv == 0) || (rv == -1)) {
299 1.1 agc DBG("isns_kevent_socket: isns_socket_readv(1) "
300 1.1 agc "returned %d\n", rv);
301 1.1 agc transport_evt = 1;
302 1.1 agc break;
303 1.1 agc }
304 1.1 agc
305 1.1 agc bavail -= sizeof(struct isns_pdu_hdr_s);
306 1.1 agc /*
307 1.1 agc * ToDo: read until sizeof(struct isns_pdu_hdr_s) has
308 1.1 agc * been read in. This statement should be
309 1.1 agc *
310 1.1 agc * bavail -= rv;
311 1.1 agc */
312 1.1 agc
313 1.1 agc /* adjust byte order */
314 1.1 agc pdu_p->hdr.isnsp_version = isns_ntohs(pdu_p->hdr.
315 1.1 agc isnsp_version);
316 1.1 agc pdu_p->hdr.func_id = isns_ntohs(pdu_p->hdr.func_id);
317 1.1 agc pdu_p->hdr.payload_len = isns_ntohs(pdu_p->hdr.
318 1.1 agc payload_len);
319 1.1 agc pdu_p->hdr.flags = isns_ntohs(pdu_p->hdr.flags);
320 1.1 agc pdu_p->hdr.trans_id = isns_ntohs(pdu_p->hdr.trans_id);
321 1.1 agc pdu_p->hdr.seq_id = isns_ntohs(pdu_p->hdr.seq_id);
322 1.1 agc pdu_p->byteorder_host = 1;
323 1.1 agc
324 1.1 agc /* Try to sense early whether we might have garbage */
325 1.1 agc if (pdu_p->hdr.isnsp_version != ISNSP_VERSION) {
326 1.1 agc DBG("isns_kevent_socket: pdu_p->hdr."
327 1.1 agc "isnsp_version != ISNSP_VERSION\n");
328 1.1 agc isns_free_pdu(pdu_p);
329 1.1 agc
330 1.1 agc transport_evt = 1;
331 1.1 agc break;
332 1.1 agc }
333 1.1 agc
334 1.1 agc /* Allocate all the necessary payload buffers */
335 1.1 agc payload_len = pdu_p->hdr.payload_len;
336 1.1 agc curbuf_p = pdu_p->payload_p;
337 1.1 agc buf_len = 0;
338 1.1 agc while (buf_len + curbuf_p->alloc_len < payload_len) {
339 1.1 agc buf_len += curbuf_p->alloc_len;
340 1.1 agc newbuf_p = isns_new_buffer(0);
341 1.1 agc curbuf_p->next = newbuf_p;
342 1.1 agc curbuf_p = newbuf_p;
343 1.1 agc }
344 1.1 agc curbuf_p->next = NULL;
345 1.1 agc
346 1.1 agc /* Hold on to our placeholder pdu */
347 1.1 agc cfg_p->pdu_in_p = pdu_p;
348 1.1 agc more = (bavail > 0) ? 1 : 0;
349 1.1 agc } else if (bavail > 0) {
350 1.1 agc /*
351 1.1 agc * Fill in the pdu payload data.
352 1.1 agc *
353 1.1 agc * If we can fill it all in now
354 1.1 agc * -AND- it corresponds to the active transaction
355 1.1 agc * then add the pdu to the transaction's
356 1.1 agc * pdu_rsp_list
357 1.1 agc * -AND- it does not correspond to the active
358 1.1 agc * transaction (or there is no active
359 1.1 agc * transaction) then drop it on the floor.
360 1.1 agc * We may not be able to fill it all in now.
361 1.1 agc * -EITHER WAY- fill in as much payload data now
362 1.1 agc * as we can.
363 1.1 agc */
364 1.1 agc
365 1.1 agc /* Refer to our placeholder pdu */
366 1.1 agc pdu_p = cfg_p->pdu_in_p;
367 1.1 agc
368 1.1 agc /* How much payload data has been filled in? */
369 1.1 agc cur_len = 0;
370 1.1 agc curbuf_p = pdu_p->payload_p;
371 1.1 agc while (curbuf_p->cur_len == curbuf_p->alloc_len) {
372 1.1 agc cur_len += curbuf_p->cur_len;
373 1.1 agc curbuf_p = curbuf_p->next;
374 1.1 agc }
375 1.1 agc cur_len += curbuf_p->cur_len;
376 1.1 agc
377 1.1 agc /* How much payload data is left to be filled in? */
378 1.1 agc unread_len = pdu_p->hdr.payload_len - cur_len;
379 1.1 agc
380 1.1 agc /* Read as much remaining payload data as possible */
381 1.1 agc iovcnt = 0;
382 1.1 agc while (curbuf_p->next != NULL) {
383 1.1 agc read_buf[iovcnt].iov_base = isns_buffer_data(
384 1.1 agc curbuf_p, curbuf_p->cur_len);
385 1.1 agc read_buf[iovcnt].iov_len = curbuf_p->alloc_len -
386 1.1 agc curbuf_p->cur_len;
387 1.1 agc iovcnt++;
388 1.1 agc
389 1.1 agc curbuf_p = curbuf_p->next;
390 1.1 agc }
391 1.1 agc read_buf[iovcnt].iov_base = isns_buffer_data(curbuf_p,
392 1.1 agc curbuf_p->cur_len);
393 1.1 agc read_buf[iovcnt].iov_len = unread_len;
394 1.1 agc iovcnt++;
395 1.1 agc
396 1.1 agc rv = isns_socket_readv(cfg_p->sd, iovp, iovcnt);
397 1.1 agc if ((rv == 0) || (rv == -1)) {
398 1.1 agc DBG("isns_kevent_socket: isns_socket_readv(2) "
399 1.1 agc "returned %d\n",rv);
400 1.1 agc isns_free_pdu(cfg_p->pdu_in_p);
401 1.1 agc cfg_p->pdu_in_p = NULL;
402 1.1 agc
403 1.1 agc transport_evt = 1;
404 1.1 agc break;
405 1.1 agc }
406 1.1 agc
407 1.1 agc /* Update cur_len in buffers that newly have data */
408 1.1 agc curbuf_p = pdu_p->payload_p;
409 1.1 agc while (curbuf_p->cur_len == curbuf_p->alloc_len)
410 1.1 agc curbuf_p = curbuf_p->next;
411 1.1 agc
412 1.1 agc rd_len = (uint32_t)rv;
413 1.1 agc do {
414 1.1 agc b_len = curbuf_p->alloc_len - curbuf_p->cur_len;
415 1.1 agc if (rd_len > b_len) {
416 1.1 agc curbuf_p->cur_len = curbuf_p->alloc_len;
417 1.1 agc rd_len -= b_len;
418 1.1 agc } else {
419 1.1 agc curbuf_p->cur_len += rd_len;
420 1.1 agc break;
421 1.1 agc }
422 1.1 agc
423 1.1 agc curbuf_p = curbuf_p->next;
424 1.1 agc } while (curbuf_p != NULL);
425 1.1 agc
426 1.1 agc bavail -= rv;
427 1.1 agc
428 1.1 agc if (rv == (int)unread_len)
429 1.1 agc isns_process_in_pdu(cfg_p);
430 1.1 agc
431 1.1 agc more = (bavail > (int64_t)sizeof(struct isns_pdu_hdr_s)) ? 1 : 0;
432 1.1 agc }
433 1.1 agc }
434 1.1 agc
435 1.1 agc transport_evt |= (evt_p->flags & EV_EOF);
436 1.1 agc if (transport_evt) {
437 1.1 agc DBG("isns_kevent_socket: processing transport event\n");
438 1.1 agc
439 1.1 agc isns_socket_close(cfg_p->sd);
440 1.1 agc cfg_p->sd_connected = 0;
441 1.1 agc
442 1.1 agc if (cfg_p->curtask_p != NULL)
443 1.1 agc isns_process_connection_loss(cfg_p);
444 1.1 agc
445 1.1 agc if (cfg_p->pdu_in_p != NULL) {
446 1.1 agc isns_free_pdu(cfg_p->pdu_in_p);
447 1.1 agc cfg_p->pdu_in_p = NULL;
448 1.1 agc }
449 1.1 agc }
450 1.1 agc
451 1.1 agc return 0;
452 1.1 agc }
453 1.1 agc
454 1.1 agc /* ARGSUSED */
455 1.1 agc /*
456 1.1 agc * isns_kevent_timer_recon()
457 1.1 agc */
458 1.1 agc int
459 1.1 agc isns_kevent_timer_recon(struct kevent *evt_p, struct isns_config_s *cfg_p)
460 1.1 agc {
461 1.1 agc int rv;
462 1.1 agc
463 1.1 agc
464 1.1 agc DBG("isns_kevent_timer_recon: entered\n");
465 1.1 agc
466 1.1 agc rv = isns_socket_create(&(cfg_p->sd), cfg_p->ai_p->ai_family,
467 1.1 agc cfg_p->ai_p->ai_socktype);
468 1.1 agc if (rv != 0)
469 1.1 agc return 0;
470 1.1 agc
471 1.1 agc rv = isns_socket_connect(cfg_p->sd, cfg_p->ai_p->ai_addr,
472 1.1 agc cfg_p->ai_p->ai_addrlen);
473 1.1 agc if (rv == 0) {
474 1.1 agc /* Remove ISNS_EVT_TIMER_RECON from kqueue */
475 1.1 agc rv = isns_change_kevent_list(cfg_p,
476 1.1 agc (uintptr_t)ISNS_EVT_TIMER_RECON, EVFILT_TIMER, EV_DELETE,
477 1.1 agc (int64_t)0, (intptr_t)0);
478 1.1 agc if (rv == -1)
479 1.1 agc DBG("isns_kevent_timer_recon: error on "
480 1.1 agc "isns_change_kevent_list(1)\n");
481 1.1 agc
482 1.1 agc cfg_p->sd_connected = 1;
483 1.1 agc
484 1.1 agc /* Add cfg_p->sd to kqueue */
485 1.1 agc rv = isns_change_kevent_list(cfg_p, (uintptr_t)cfg_p->sd,
486 1.1 agc EVFILT_READ, EV_ADD | EV_CLEAR, (int64_t)0,
487 1.1 agc (intptr_t)isns_kevent_socket);
488 1.1 agc if (rv == -1)
489 1.1 agc DBG("isns_kevent_timer_recon: error on "
490 1.1 agc "isns_change_kevent_list(2)\n");
491 1.1 agc
492 1.1 agc isns_end_task(cfg_p->curtask_p);
493 1.1 agc }
494 1.1 agc
495 1.1 agc return 0;
496 1.1 agc }
497 1.1 agc
498 1.1 agc
499 1.1 agc /* ARGSUSED */
500 1.1 agc /*
501 1.1 agc * isns_kevent_timer_refresh
502 1.1 agc */
503 1.1 agc int
504 1.1 agc isns_kevent_timer_refresh(struct kevent* evt_p, struct isns_config_s *cfg_p)
505 1.1 agc {
506 1.1 agc struct isns_refresh_s *ref_p;
507 1.1 agc ISNS_TRANS trans;
508 1.1 agc uint32_t status;
509 1.1 agc int rval;
510 1.1 agc
511 1.1 agc DBG("isns_kevent_timer_refresh: entered\n");
512 1.1 agc
513 1.1 agc /* If refresh info pointer NULL, or no name assigned, just return. */
514 1.1 agc ref_p = cfg_p->refresh_p;
515 1.1 agc if ((ref_p == NULL) || (ref_p->node[0] == '\0'))
516 1.1 agc return 0;
517 1.1 agc
518 1.1 agc if (ref_p->trans_p != NULL) {
519 1.1 agc /* If the previous refresh trans is not complete, return. */
520 1.1 agc rval = isns_get_pdu_response_status(ref_p->trans_p, &status);
521 1.1 agc if (rval == EPERM) {
522 1.1 agc DBG("isns_kevent_timer_refresh: "
523 1.1 agc "prev refresh trans not complete\n");
524 1.1 agc return 0;
525 1.1 agc }
526 1.1 agc /* Free previous refresh trans. */
527 1.1 agc isns_free_trans(ref_p->trans_p);
528 1.1 agc ref_p->trans_p = NULL;
529 1.1 agc }
530 1.1 agc
531 1.1 agc /* Build new refresh transaction and send it. */
532 1.1 agc trans = isns_new_trans((ISNS_HANDLE)cfg_p, isnsp_DevAttrQry, 0);
533 1.1 agc if (trans == ISNS_INVALID_TRANS) {
534 1.1 agc DBG("isns_kevent_timer_refresh: error on isns_new_trans()\n");
535 1.1 agc return 0;
536 1.1 agc }
537 1.1 agc
538 1.1 agc ref_p->trans_p = (struct isns_trans_s *)trans;
539 1.1 agc /* First we add our source attribute */
540 1.1 agc isns_add_string(trans, isnst_iSCSIName, ref_p->node);
541 1.1 agc /* Now add our message attribute */
542 1.1 agc isns_add_string(trans, isnst_iSCSIName, ref_p->node);
543 1.1 agc isns_add_tlv(trans, isnst_Delimiter, 0, NULL);
544 1.1 agc /* and finally the operating attributes */
545 1.1 agc isns_add_tlv(trans, isnst_EID, 0, NULL);
546 1.1 agc isns_send_trans(trans, NULL, NULL);
547 1.1 agc
548 1.1 agc return 0;
549 1.1 agc }
550