1 /* $NetBSD: isns_util.c,v 1.2 2012/03/21 05:33:27 matt Exp $ */ 2 3 /*- 4 * Copyright (c) 2004,2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * isns_util.c 34 */ 35 36 #include <sys/cdefs.h> 37 __RCSID("$NetBSD: isns_util.c,v 1.2 2012/03/21 05:33:27 matt Exp $"); 38 39 40 #include <sys/types.h> 41 42 #include <pthread.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "isns.h" 47 #include "isns_config.h" 48 49 #define ISNS_MAX_DISCONNECTS_PER_TRANS 3 50 51 int 52 isns_issue_cmd(struct isns_config_s *cfg_p, uint8_t cmd_type) 53 { 54 return (int)write(cfg_p->pipe_fds[1], &cmd_type, 1); 55 } 56 57 58 int 59 isns_issue_cmd_with_data(struct isns_config_s *cfg_p, uint8_t cmd_type, 60 uint8_t *data_p, int data_len) 61 { 62 struct iovec iov[2]; 63 64 iov[0].iov_base = &cmd_type; 65 iov[0].iov_len = 1; 66 iov[1].iov_base = data_p; 67 iov[1].iov_len = data_len; 68 69 return (int)isns_file_writev(cfg_p->pipe_fds[1], iov, 2); 70 } 71 72 73 int 74 isns_change_kevent_list(struct isns_config_s *cfg_p, 75 uintptr_t ident, uint32_t filter, uint32_t flags, int64_t data, intptr_t udata) 76 { 77 struct kevent evt; 78 79 EV_SET(&evt, ident, filter, flags, 0, data, udata); 80 return kevent(cfg_p->kq, &evt, 1, NULL, 0, NULL); 81 } 82 83 84 struct isns_config_s * 85 isns_new_config(void) 86 { 87 struct isns_config_s *cfg_p; 88 pthread_mutexattr_t mutexattr; 89 90 cfg_p = (struct isns_config_s *) 91 isns_malloc(sizeof(struct isns_config_s)); 92 if (cfg_p == NULL) { 93 DBG("isns_new_config: error on isns_malloc() [1]\n"); 94 return NULL; 95 } 96 cfg_p->kq = -1; 97 cfg_p->pipe_fds[0] = -1; 98 cfg_p->pipe_fds[1] = -1; 99 cfg_p->curtask_p = NULL; 100 cfg_p->sd_connected = 0; 101 cfg_p->ai_p = NULL; 102 cfg_p->pdu_in_p = NULL; 103 104 cfg_p->refresh_p = NULL; 105 106 pthread_mutexattr_init(&mutexattr); 107 pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL); 108 if (pthread_mutex_init(&cfg_p->taskq_mutex, &mutexattr) != 0) { 109 DBG("isns_new_config: error on pthread_mutex_init() [1]\n"); 110 isns_free(cfg_p); 111 return NULL; 112 } 113 114 pthread_mutexattr_init(&mutexattr); 115 pthread_mutexattr_settype(&mutexattr, ISNS_MUTEX_TYPE_NORMAL); 116 if (pthread_mutex_init(&cfg_p->trans_mutex, &mutexattr) != 0) { 117 DBG("isns_new_config: error on pthread_mutex_init() [2]\n"); 118 pthread_mutex_destroy(&cfg_p->taskq_mutex); 119 isns_free(cfg_p); 120 return NULL; 121 } 122 123 SIMPLEQ_INIT(&cfg_p->taskq_head); 124 125 cfg_p->control_thread_p = (pthread_t *)isns_malloc(sizeof(pthread_t)); 126 if (cfg_p->control_thread_p == NULL) { 127 DBG("isns_new_config: error on isns_malloc() [1]\n"); 128 isns_destroy_config(cfg_p); 129 return NULL; 130 } 131 132 return cfg_p; 133 } 134 135 136 void 137 isns_destroy_config(struct isns_config_s *cfg_p) 138 { 139 struct isns_task_s *task_p; 140 141 if (cfg_p != NULL) { 142 if (cfg_p->kq != -1) 143 close(cfg_p->kq); 144 if (cfg_p->pipe_fds[0] != -1) 145 close(cfg_p->pipe_fds[0]); 146 if (cfg_p->pipe_fds[1] != -1) 147 close(cfg_p->pipe_fds[1]); 148 if (cfg_p->control_thread_p != NULL) 149 isns_free(cfg_p->control_thread_p); 150 if (cfg_p->refresh_p != NULL) { 151 if (cfg_p->refresh_p->trans_p != NULL) 152 isns_free_trans(cfg_p->refresh_p->trans_p); 153 isns_free(cfg_p->refresh_p); 154 } 155 /* Free the current task, if necessary. */ 156 if ((task_p = cfg_p->curtask_p) != NULL) { 157 if (task_p->task_type == ISNS_TASK_SEND_PDU) 158 isns_complete_trans(task_p->var.send_pdu.trans_p); 159 isns_free_task(task_p); 160 } 161 /* Empty the task queue of any pending tasks and free them. */ 162 while ((task_p = isns_taskq_remove(cfg_p)) != NULL) { 163 if (task_p->task_type == ISNS_TASK_SEND_PDU) 164 isns_complete_trans(task_p->var.send_pdu.trans_p); 165 isns_free_task(task_p); 166 } 167 pthread_mutex_destroy(&cfg_p->taskq_mutex); 168 pthread_mutex_destroy(&cfg_p->trans_mutex); 169 if (cfg_p->ai_p != NULL) { 170 if (cfg_p->ai_p->ai_canonname != NULL) 171 isns_free(cfg_p->ai_p->ai_canonname); 172 if (cfg_p->ai_p->ai_addr != NULL) 173 isns_free(cfg_p->ai_p->ai_addr); 174 isns_free(cfg_p->ai_p); 175 } 176 isns_free(cfg_p); 177 } 178 } 179 180 181 /* 182 * isns_thread_create() 183 */ 184 int 185 isns_thread_create(struct isns_config_s *cfg_p) 186 { 187 char namebuf[ISNS_THREAD_MAX_NAMELEN]; 188 int error; 189 pthread_attr_t attr; 190 191 DBG("isns_thread_create: entered\n"); 192 193 strcpy(namebuf, "isns_control"); 194 error = pthread_attr_init(&attr); 195 if (error != 0) { 196 DBG("isns_thread_create: error on pthread_threadattr_init\n"); 197 return error; 198 } 199 200 error = pthread_attr_setname_np(&attr, namebuf, NULL); 201 if (error != 0) { 202 DBG("isns_thread_create: " 203 "error on pthread_threadattr_setname\n"); 204 pthread_attr_destroy(&attr); 205 return error; 206 } 207 208 error = pthread_create(cfg_p->control_thread_p, 209 &attr, isns_control_thread, cfg_p); 210 pthread_attr_destroy(&attr); 211 212 if (error != 0) { 213 DBG("isns_thread_create: error on pthread_thread_create\n"); 214 return error; 215 } 216 217 return error; 218 } 219 220 221 /* 222 * isns_thread_destroy() 223 */ 224 void 225 isns_thread_destroy(struct isns_config_s *cfg_p) 226 { 227 int error; 228 void *rv; 229 230 DBG("isns_thread_destroy: entered\n"); 231 232 if ((cfg_p == NULL) || (cfg_p->control_thread_p == NULL)) 233 return; 234 235 DBG("isns_thread_destroy: about to wait (join) on thread\n"); 236 error = pthread_join(*cfg_p->control_thread_p, &rv); 237 if (error) { 238 DBG("isns_thread_destroy: error on pthread_thread_join\n"); 239 return; 240 } 241 242 DBG("isns_thread_destroy: done waiting on thread\n"); 243 } 244 245 /* 246 * 247 */ 248 void 249 isns_process_connection_loss(struct isns_config_s *cfg_p) 250 { 251 struct isns_trans_s *trans_p; 252 struct isns_pdu_s *pdu_p, *free_pdu_p; 253 254 255 DBG("isns_process_connection_loss: entered\n"); 256 257 if (cfg_p->curtask_p != NULL) { 258 trans_p = cfg_p->curtask_p->var.send_pdu.trans_p; 259 260 if (trans_p->disconnect_cnt == ISNS_MAX_DISCONNECTS_PER_TRANS) { 261 isns_complete_trans(trans_p); 262 isns_end_task(cfg_p->curtask_p); 263 264 if (cfg_p->pdu_in_p != NULL) { 265 isns_free_pdu(cfg_p->pdu_in_p); 266 cfg_p->pdu_in_p = NULL; 267 } 268 } else { 269 trans_p->disconnect_cnt++; 270 271 if (trans_p->pdu_rsp_list != NULL) { 272 pdu_p = trans_p->pdu_rsp_list; 273 while (pdu_p != NULL) { 274 free_pdu_p = pdu_p; 275 pdu_p = pdu_p->next; 276 isns_free_pdu(free_pdu_p); 277 } 278 } 279 280 isns_taskq_insert_head(cfg_p, cfg_p->curtask_p); 281 cfg_p->curtask_p = NULL; 282 283 isns_issue_cmd(cfg_p, ISNS_CMD_PROCESS_TASKQ); 284 } 285 } 286 } 287