1 1.2 matt /* $NetBSD: isns_util.c,v 1.2 2012/03/21 05:33:27 matt 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 /* 33 1.1 agc * isns_util.c 34 1.1 agc */ 35 1.1 agc 36 1.1 agc #include <sys/cdefs.h> 37 1.2 matt __RCSID("$NetBSD: isns_util.c,v 1.2 2012/03/21 05:33:27 matt Exp $"); 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 <pthread.h> 43 1.1 agc #include <string.h> 44 1.1 agc #include <unistd.h> 45 1.1 agc 46 1.1 agc #include "isns.h" 47 1.1 agc #include "isns_config.h" 48 1.1 agc 49 1.1 agc #define ISNS_MAX_DISCONNECTS_PER_TRANS 3 50 1.1 agc 51 1.1 agc int 52 1.1 agc isns_issue_cmd(struct isns_config_s *cfg_p, uint8_t cmd_type) 53 1.1 agc { 54 1.1 agc return (int)write(cfg_p->pipe_fds[1], &cmd_type, 1); 55 1.1 agc } 56 1.1 agc 57 1.1 agc 58 1.1 agc int 59 1.1 agc isns_issue_cmd_with_data(struct isns_config_s *cfg_p, uint8_t cmd_type, 60 1.1 agc uint8_t *data_p, int data_len) 61 1.1 agc { 62 1.1 agc struct iovec iov[2]; 63 1.1 agc 64 1.1 agc iov[0].iov_base = &cmd_type; 65 1.1 agc iov[0].iov_len = 1; 66 1.1 agc iov[1].iov_base = data_p; 67 1.1 agc iov[1].iov_len = data_len; 68 1.1 agc 69 1.1 agc return (int)isns_file_writev(cfg_p->pipe_fds[1], iov, 2); 70 1.1 agc } 71 1.1 agc 72 1.1 agc 73 1.1 agc int 74 1.1 agc isns_change_kevent_list(struct isns_config_s *cfg_p, 75 1.1 agc uintptr_t ident, uint32_t filter, uint32_t flags, int64_t data, intptr_t udata) 76 1.1 agc { 77 1.1 agc struct kevent evt; 78 1.1 agc 79 1.1 agc EV_SET(&evt, ident, filter, flags, 0, data, udata); 80 1.1 agc return kevent(cfg_p->kq, &evt, 1, NULL, 0, NULL); 81 1.1 agc } 82 1.1 agc 83 1.1 agc 84 1.1 agc struct isns_config_s * 85 1.2 matt isns_new_config(void) 86 1.1 agc { 87 1.1 agc struct isns_config_s *cfg_p; 88 1.1 agc pthread_mutexattr_t mutexattr; 89 1.1 agc 90 1.1 agc cfg_p = (struct isns_config_s *) 91 1.1 agc isns_malloc(sizeof(struct isns_config_s)); 92 1.1 agc if (cfg_p == NULL) { 93 1.1 agc DBG("isns_new_config: error on isns_malloc() [1]\n"); 94 1.1 agc return NULL; 95 1.1 agc } 96 1.1 agc cfg_p->kq = -1; 97 1.1 agc cfg_p->pipe_fds[0] = -1; 98 1.1 agc cfg_p->pipe_fds[1] = -1; 99 1.1 agc cfg_p->curtask_p = NULL; 100 1.1 agc cfg_p->sd_connected = 0; 101 1.1 agc cfg_p->ai_p = NULL; 102 1.1 agc cfg_p->pdu_in_p = NULL; 103 1.1 agc 104 1.1 agc cfg_p->refresh_p = NULL; 105 1.1 agc 106 1.1 agc pthread_mutexattr_init(&mutexattr); 107 1.1 agc pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL); 108 1.1 agc if (pthread_mutex_init(&cfg_p->taskq_mutex, &mutexattr) != 0) { 109 1.1 agc DBG("isns_new_config: error on pthread_mutex_init() [1]\n"); 110 1.1 agc isns_free(cfg_p); 111 1.1 agc return NULL; 112 1.1 agc } 113 1.1 agc 114 1.1 agc pthread_mutexattr_init(&mutexattr); 115 1.1 agc pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL); 116 1.1 agc if (pthread_mutex_init(&cfg_p->trans_mutex, &mutexattr) != 0) { 117 1.1 agc DBG("isns_new_config: error on pthread_mutex_init() [2]\n"); 118 1.1 agc pthread_mutex_destroy(&cfg_p->taskq_mutex); 119 1.1 agc isns_free(cfg_p); 120 1.1 agc return NULL; 121 1.1 agc } 122 1.1 agc 123 1.1 agc SIMPLEQ_INIT(&cfg_p->taskq_head); 124 1.1 agc 125 1.1 agc cfg_p->control_thread_p = (pthread_t *)isns_malloc(sizeof(pthread_t)); 126 1.1 agc if (cfg_p->control_thread_p == NULL) { 127 1.1 agc DBG("isns_new_config: error on isns_malloc() [1]\n"); 128 1.1 agc isns_destroy_config(cfg_p); 129 1.1 agc return NULL; 130 1.1 agc } 131 1.1 agc 132 1.1 agc return cfg_p; 133 1.1 agc } 134 1.1 agc 135 1.1 agc 136 1.1 agc void 137 1.1 agc isns_destroy_config(struct isns_config_s *cfg_p) 138 1.1 agc { 139 1.1 agc struct isns_task_s *task_p; 140 1.1 agc 141 1.1 agc if (cfg_p != NULL) { 142 1.1 agc if (cfg_p->kq != -1) 143 1.1 agc close(cfg_p->kq); 144 1.1 agc if (cfg_p->pipe_fds[0] != -1) 145 1.1 agc close(cfg_p->pipe_fds[0]); 146 1.1 agc if (cfg_p->pipe_fds[1] != -1) 147 1.1 agc close(cfg_p->pipe_fds[1]); 148 1.1 agc if (cfg_p->control_thread_p != NULL) 149 1.1 agc isns_free(cfg_p->control_thread_p); 150 1.1 agc if (cfg_p->refresh_p != NULL) { 151 1.1 agc if (cfg_p->refresh_p->trans_p != NULL) 152 1.1 agc isns_free_trans(cfg_p->refresh_p->trans_p); 153 1.1 agc isns_free(cfg_p->refresh_p); 154 1.1 agc } 155 1.1 agc /* Free the current task, if necessary. */ 156 1.1 agc if ((task_p = cfg_p->curtask_p) != NULL) { 157 1.1 agc if (task_p->task_type == ISNS_TASK_SEND_PDU) 158 1.1 agc isns_complete_trans(task_p->var.send_pdu.trans_p); 159 1.1 agc isns_free_task(task_p); 160 1.1 agc } 161 1.1 agc /* Empty the task queue of any pending tasks and free them. */ 162 1.1 agc while ((task_p = isns_taskq_remove(cfg_p)) != NULL) { 163 1.1 agc if (task_p->task_type == ISNS_TASK_SEND_PDU) 164 1.1 agc isns_complete_trans(task_p->var.send_pdu.trans_p); 165 1.1 agc isns_free_task(task_p); 166 1.1 agc } 167 1.1 agc pthread_mutex_destroy(&cfg_p->taskq_mutex); 168 1.1 agc pthread_mutex_destroy(&cfg_p->trans_mutex); 169 1.1 agc if (cfg_p->ai_p != NULL) { 170 1.1 agc if (cfg_p->ai_p->ai_canonname != NULL) 171 1.1 agc isns_free(cfg_p->ai_p->ai_canonname); 172 1.1 agc if (cfg_p->ai_p->ai_addr != NULL) 173 1.1 agc isns_free(cfg_p->ai_p->ai_addr); 174 1.1 agc isns_free(cfg_p->ai_p); 175 1.1 agc } 176 1.1 agc isns_free(cfg_p); 177 1.1 agc } 178 1.1 agc } 179 1.1 agc 180 1.1 agc 181 1.1 agc /* 182 1.1 agc * isns_thread_create() 183 1.1 agc */ 184 1.1 agc int 185 1.1 agc isns_thread_create(struct isns_config_s *cfg_p) 186 1.1 agc { 187 1.1 agc char namebuf[ISNS_THREAD_MAX_NAMELEN]; 188 1.1 agc int error; 189 1.1 agc pthread_attr_t attr; 190 1.1 agc 191 1.1 agc DBG("isns_thread_create: entered\n"); 192 1.1 agc 193 1.1 agc strcpy(namebuf, "isns_control"); 194 1.1 agc error = pthread_attr_init(&attr); 195 1.1 agc if (error != 0) { 196 1.1 agc DBG("isns_thread_create: error on pthread_threadattr_init\n"); 197 1.1 agc return error; 198 1.1 agc } 199 1.1 agc 200 1.1 agc error = pthread_attr_setname_np(&attr, namebuf, NULL); 201 1.1 agc if (error != 0) { 202 1.1 agc DBG("isns_thread_create: " 203 1.1 agc "error on pthread_threadattr_setname\n"); 204 1.1 agc pthread_attr_destroy(&attr); 205 1.1 agc return error; 206 1.1 agc } 207 1.1 agc 208 1.1 agc error = pthread_create(cfg_p->control_thread_p, 209 1.1 agc &attr, isns_control_thread, cfg_p); 210 1.1 agc pthread_attr_destroy(&attr); 211 1.1 agc 212 1.1 agc if (error != 0) { 213 1.1 agc DBG("isns_thread_create: error on pthread_thread_create\n"); 214 1.1 agc return error; 215 1.1 agc } 216 1.1 agc 217 1.1 agc return error; 218 1.1 agc } 219 1.1 agc 220 1.1 agc 221 1.1 agc /* 222 1.1 agc * isns_thread_destroy() 223 1.1 agc */ 224 1.1 agc void 225 1.1 agc isns_thread_destroy(struct isns_config_s *cfg_p) 226 1.1 agc { 227 1.1 agc int error; 228 1.1 agc void *rv; 229 1.1 agc 230 1.1 agc DBG("isns_thread_destroy: entered\n"); 231 1.1 agc 232 1.1 agc if ((cfg_p == NULL) || (cfg_p->control_thread_p == NULL)) 233 1.1 agc return; 234 1.1 agc 235 1.1 agc DBG("isns_thread_destroy: about to wait (join) on thread\n"); 236 1.1 agc error = pthread_join(*cfg_p->control_thread_p, &rv); 237 1.1 agc if (error) { 238 1.1 agc DBG("isns_thread_destroy: error on pthread_thread_join\n"); 239 1.1 agc return; 240 1.1 agc } 241 1.1 agc 242 1.1 agc DBG("isns_thread_destroy: done waiting on thread\n"); 243 1.1 agc } 244 1.1 agc 245 1.1 agc /* 246 1.1 agc * 247 1.1 agc */ 248 1.1 agc void 249 1.1 agc isns_process_connection_loss(struct isns_config_s *cfg_p) 250 1.1 agc { 251 1.1 agc struct isns_trans_s *trans_p; 252 1.1 agc struct isns_pdu_s *pdu_p, *free_pdu_p; 253 1.1 agc 254 1.1 agc 255 1.1 agc DBG("isns_process_connection_loss: entered\n"); 256 1.1 agc 257 1.1 agc if (cfg_p->curtask_p != NULL) { 258 1.1 agc trans_p = cfg_p->curtask_p->var.send_pdu.trans_p; 259 1.1 agc 260 1.1 agc if (trans_p->disconnect_cnt == ISNS_MAX_DISCONNECTS_PER_TRANS) { 261 1.1 agc isns_complete_trans(trans_p); 262 1.1 agc isns_end_task(cfg_p->curtask_p); 263 1.1 agc 264 1.1 agc if (cfg_p->pdu_in_p != NULL) { 265 1.1 agc isns_free_pdu(cfg_p->pdu_in_p); 266 1.1 agc cfg_p->pdu_in_p = NULL; 267 1.1 agc } 268 1.1 agc } else { 269 1.1 agc trans_p->disconnect_cnt++; 270 1.1 agc 271 1.1 agc if (trans_p->pdu_rsp_list != NULL) { 272 1.1 agc pdu_p = trans_p->pdu_rsp_list; 273 1.1 agc while (pdu_p != NULL) { 274 1.1 agc free_pdu_p = pdu_p; 275 1.1 agc pdu_p = pdu_p->next; 276 1.1 agc isns_free_pdu(free_pdu_p); 277 1.1 agc } 278 1.1 agc } 279 1.1 agc 280 1.1 agc isns_taskq_insert_head(cfg_p, cfg_p->curtask_p); 281 1.1 agc cfg_p->curtask_p = NULL; 282 1.1 agc 283 1.1 agc isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ); 284 1.1 agc } 285 1.1 agc } 286 1.1 agc } 287