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