Home | History | Annotate | Line # | Download | only in libisns
      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