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