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