1 1.2 dholland /* $NetBSD: isns_thread.c,v 1.2 2019/07/03 18:40:33 dholland 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.2 dholland __RCSID("$NetBSD: isns_thread.c,v 1.2 2019/07/03 18:40:33 dholland 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.2 dholland if (rbytes < 0) 156 1.1 agc DBG("isns_kevent_pipe: " 157 1.1 agc "error reading trans id\n"); 158 1.2 dholland else if (rbytes != sizeof(trans_id)) 159 1.2 dholland DBG("isns_kevent_pipe: " 160 1.2 dholland "short read reading trans id\n"); 161 1.2 dholland else { 162 1.2 dholland isns_abort_trans(cfg_p, trans_id); 163 1.2 dholland pipe_nbytes -= (int)rbytes; 164 1.2 dholland } 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