Home | History | Annotate | Line # | Download | only in libisns
isns_util.c revision 1.1.1.1.6.1
      1  1.1.1.1.6.1  yamt /*	$NetBSD: isns_util.c,v 1.1.1.1.6.1 2012/04/17 00:05:28 yamt 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.1.1.6.1  yamt __RCSID("$NetBSD: isns_util.c,v 1.1.1.1.6.1 2012/04/17 00:05:28 yamt 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.1.1.6.1  yamt 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