isns_util.c revision 1.1 1 1.1 agc /* $NetBSD: isns_util.c,v 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 /*
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.1 agc __RCSID("$NetBSD: isns_util.c,v 1.1 2011/01/16 01:22:50 agc 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.1 agc isns_new_config()
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