Annotation of embedaddon/istgt/src/istgt.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2008-2011 Daisuke Aoyama <aoyama@peach.ne.jp>.
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 15: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 17: * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
! 18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 19: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 20: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 21: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 22: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 23: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 24: * SUCH DAMAGE.
! 25: *
! 26: */
! 27:
! 28: #ifdef HAVE_CONFIG_H
! 29: #include "config.h"
! 30: #endif
! 31:
! 32: #include <inttypes.h>
! 33: #include <stdint.h>
! 34:
! 35: #include <errno.h>
! 36: #include <stdarg.h>
! 37: #include <stdio.h>
! 38: #include <stdlib.h>
! 39: #include <string.h>
! 40: #include <poll.h>
! 41: #include <pthread.h>
! 42: #ifdef HAVE_PTHREAD_NP_H
! 43: #include <pthread_np.h>
! 44: #endif
! 45: #include <fcntl.h>
! 46: #include <unistd.h>
! 47: #include <signal.h>
! 48:
! 49: #include <sys/types.h>
! 50: #include <sys/socket.h>
! 51: #include <netinet/in.h>
! 52:
! 53: #include "istgt.h"
! 54: #include "istgt_ver.h"
! 55: #include "istgt_log.h"
! 56: #include "istgt_conf.h"
! 57: #include "istgt_sock.h"
! 58: #include "istgt_misc.h"
! 59: #include "istgt_crc32c.h"
! 60: #include "istgt_iscsi.h"
! 61: #include "istgt_lu.h"
! 62: #include "istgt_proto.h"
! 63:
! 64: #ifdef ISTGT_USE_KQUEUE
! 65: #include <sys/types.h>
! 66: #include <sys/event.h>
! 67: #include <sys/time.h>
! 68: #endif
! 69:
! 70: #define POLLWAIT 3000
! 71: #define PORTNUMLEN 32
! 72:
! 73: ISTGT g_istgt;
! 74:
! 75: #if 0
! 76: void
! 77: fatal(const char *msg, ...)
! 78: {
! 79: va_list ap;
! 80: va_start(ap, msg);
! 81: vfprintf(stderr, msg, ap);
! 82: va_end(ap);
! 83: exit(EXIT_FAILURE);
! 84: }
! 85: #endif
! 86:
! 87: static int
! 88: istgt_parse_portal(const char *portal, char **host, char **port)
! 89: {
! 90: const char *p;
! 91: int n;
! 92:
! 93: if (portal == NULL) {
! 94: ISTGT_ERRLOG("portal error\n");
! 95: return -1;
! 96: }
! 97:
! 98: if (portal[0] == '[') {
! 99: /* IPv6 */
! 100: p = strchr(portal + 1, ']');
! 101: if (p == NULL) {
! 102: ISTGT_ERRLOG("portal error\n");
! 103: return -1;
! 104: }
! 105: #if 0
! 106: n = p - (portal + 1);
! 107: *host = xmalloc(n + 1);
! 108: memcpy(*host, portal + 1, n);
! 109: (*host)[n] = '\0';
! 110: p++;
! 111: #else
! 112: p++;
! 113: n = p - portal;
! 114: *host = xmalloc(n + 1);
! 115: memcpy(*host, portal, n);
! 116: (*host)[n] = '\0';
! 117: #endif
! 118: if (p[0] == '\0') {
! 119: *port = xmalloc(PORTNUMLEN);
! 120: snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
! 121: } else {
! 122: if (p[0] != ':') {
! 123: ISTGT_ERRLOG("portal error\n");
! 124: xfree(*host);
! 125: return -1;
! 126: }
! 127: *port = xstrdup(p + 1);
! 128: }
! 129: } else {
! 130: /* IPv4 */
! 131: p = strchr(portal, ':');
! 132: if (p == NULL) {
! 133: p = portal + strlen(portal);
! 134: }
! 135: n = p - portal;
! 136: *host = xmalloc(n + 1);
! 137: memcpy(*host, portal, n);
! 138: (*host)[n] = '\0';
! 139: if (p[0] == '\0') {
! 140: *port = xmalloc(PORTNUMLEN);
! 141: snprintf(*port, PORTNUMLEN, "%d", DEFAULT_PORT);
! 142: } else {
! 143: if (p[0] != ':') {
! 144: ISTGT_ERRLOG("portal error\n");
! 145: xfree(*host);
! 146: return -1;
! 147: }
! 148: *port = xstrdup(p + 1);
! 149: }
! 150: }
! 151: return 0;
! 152: }
! 153:
! 154: static int
! 155: istgt_add_portal(ISTGT_Ptr istgt, CF_SECTION *sp, int idx1)
! 156: {
! 157: char *label, *portal, *host, *port;
! 158: int idx;
! 159: int rc;
! 160:
! 161: label = istgt_get_nmval(sp, "Portal", idx1, 0);
! 162: portal = istgt_get_nmval(sp, "Portal", idx1, 1);
! 163: if (label == NULL || portal == NULL) {
! 164: ISTGT_ERRLOG("portal error\n");
! 165: return -1;
! 166: }
! 167:
! 168: rc = istgt_parse_portal(portal, &host, &port);
! 169: if (rc < 0) {
! 170: ISTGT_ERRLOG("parse portal error\n");
! 171: return -1;
! 172: }
! 173:
! 174: idx = istgt->nportal;
! 175: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 176: "Index=%d, Host=%s, Port=%s, Tag=%d\n",
! 177: idx, host, port, sp->num);
! 178: if (idx < MAX_PORTAL) {
! 179: istgt->portal[idx].label = xstrdup(label);
! 180: istgt->portal[idx].host = host;
! 181: istgt->portal[idx].port = port;
! 182: istgt->portal[idx].idx = idx;
! 183: istgt->portal[idx].tag = sp->num;
! 184: istgt->portal[idx].sock = -1;
! 185: idx++;
! 186: istgt->nportal = idx;
! 187: } else {
! 188: ISTGT_ERRLOG("nportal(%d) >= MAX_PORTAL\n", idx);
! 189: xfree(host);
! 190: xfree(port);
! 191: return -1;
! 192: }
! 193: return 0;
! 194: }
! 195:
! 196: static int
! 197: istgt_build_portal_array(ISTGT_Ptr istgt)
! 198: {
! 199: CF_SECTION *sp;
! 200: const char *val;
! 201: int rc;
! 202: int i;
! 203:
! 204: sp = istgt->config->section;
! 205: while (sp != NULL) {
! 206: if (sp->type == ST_PORTALGROUP) {
! 207: if (sp->num == 0) {
! 208: ISTGT_ERRLOG("Group 0 is invalid\n");
! 209: return -1;
! 210: }
! 211: if (sp->num > ISTGT_PG_TAG_MAX) {
! 212: ISTGT_ERRLOG("tag %d is invalid\n", sp->num);
! 213: return -1;
! 214: }
! 215:
! 216: val = istgt_get_val(sp, "Comment");
! 217: if (val != NULL) {
! 218: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 219: "Comment %s\n", val);
! 220: }
! 221: for (i = 0; ; i++) {
! 222: val = istgt_get_nval(sp, "Portal", i);
! 223: if (val == NULL)
! 224: break;
! 225: rc = istgt_add_portal(istgt, sp, i);
! 226: if (rc < 0) {
! 227: ISTGT_ERRLOG("add_portal() failed\n");
! 228: return -1;
! 229: }
! 230: }
! 231: }
! 232: sp = sp->next;
! 233: }
! 234: return 0;
! 235: }
! 236:
! 237: static void
! 238: istgt_destroy_portal_array(ISTGT_Ptr istgt)
! 239: {
! 240: int i;
! 241:
! 242: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destroy_portal_array\n");
! 243: for (i = 0; i < istgt->nportal; i++) {
! 244: xfree(istgt->portal[i].label);
! 245: xfree(istgt->portal[i].host);
! 246: xfree(istgt->portal[i].port);
! 247:
! 248: istgt->portal[i].label = NULL;
! 249: istgt->portal[i].host = NULL;
! 250: istgt->portal[i].port = NULL;
! 251: istgt->portal[i].idx = i;
! 252: istgt->portal[i].tag = 0;
! 253: }
! 254: istgt->nportal = 0;
! 255: }
! 256:
! 257: static int
! 258: istgt_open_portal(ISTGT_Ptr istgt)
! 259: {
! 260: int port;
! 261: int sock;
! 262: int i;
! 263:
! 264: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_portal\n");
! 265: for (i = 0; i < istgt->nportal; i++) {
! 266: if (istgt->portal[i].sock < 0) {
! 267: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 268: "open host %s, port %s, tag %d\n",
! 269: istgt->portal[i].host, istgt->portal[i].port,
! 270: istgt->portal[i].tag);
! 271: port = (int)strtol(istgt->portal[i].port, NULL, 0);
! 272: sock = istgt_listen(istgt->portal[i].host, port);
! 273: if (sock < 0) {
! 274: ISTGT_ERRLOG("listen error %.64s:%d\n",
! 275: istgt->portal[i].host, port);
! 276: return -1;
! 277: }
! 278: istgt->portal[i].sock = sock;
! 279: }
! 280: }
! 281: return 0;
! 282: }
! 283:
! 284: static int
! 285: istgt_close_portal(ISTGT_Ptr istgt)
! 286: {
! 287: int i;
! 288:
! 289: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_portal\n");
! 290: for (i = 0; i < istgt->nportal; i++) {
! 291: if (istgt->portal[i].sock >= 0) {
! 292: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 293: "close host %s, port %s, tag %d\n",
! 294: istgt->portal[i].host, istgt->portal[i].port,
! 295: istgt->portal[i].tag);
! 296: close(istgt->portal[i].sock);
! 297: istgt->portal[i].sock = -1;
! 298: }
! 299: }
! 300: return 0;
! 301: }
! 302:
! 303: static int
! 304: istgt_add_initiator_group(ISTGT_Ptr istgt, CF_SECTION *sp)
! 305: {
! 306: const char *val;
! 307: int alloc_len;
! 308: int idx;
! 309: int names;
! 310: int masks;
! 311: int i;
! 312:
! 313: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add initiator group %d\n", sp->num);
! 314:
! 315: val = istgt_get_val(sp, "Comment");
! 316: if (val != NULL) {
! 317: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
! 318: }
! 319:
! 320: /* counts number of definition */
! 321: for (i = 0; ; i++) {
! 322: val = istgt_get_nval(sp, "InitiatorName", i);
! 323: if (val == NULL)
! 324: break;
! 325: }
! 326: names = i;
! 327: if (names > MAX_INITIATOR) {
! 328: ISTGT_ERRLOG("%d > MAX_INITIATOR\n", names);
! 329: return -1;
! 330: }
! 331: for (i = 0; ; i++) {
! 332: val = istgt_get_nval(sp, "Netmask", i);
! 333: if (val == NULL)
! 334: break;
! 335: }
! 336: masks = i;
! 337: if (masks > MAX_NETMASK) {
! 338: ISTGT_ERRLOG("%d > MAX_NETMASK\n", masks);
! 339: return -1;
! 340: }
! 341:
! 342: idx = istgt->ninitiator_group;
! 343: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 344: "Index=%d, Tag=%d, Names=%d, Masks=%d\n",
! 345: idx, sp->num, names, masks);
! 346: if (idx < MAX_INITIATOR_GROUP) {
! 347: istgt->initiator_group[idx].ninitiators = names;
! 348: alloc_len = sizeof (char *) * names;
! 349: istgt->initiator_group[idx].initiators = xmalloc(alloc_len);
! 350: istgt->initiator_group[idx].nnetmasks = masks;
! 351: alloc_len = sizeof (char *) * masks;
! 352: istgt->initiator_group[idx].netmasks = xmalloc(alloc_len);
! 353: istgt->initiator_group[idx].idx = idx;
! 354: istgt->initiator_group[idx].tag = sp->num;
! 355:
! 356: for (i = 0; i < names; i++) {
! 357: val = istgt_get_nval(sp, "InitiatorName", i);
! 358: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 359: "InitiatorName %s\n", val);
! 360: istgt->initiator_group[idx].initiators[i] = xstrdup(val);
! 361: }
! 362: for (i = 0; i < masks; i++) {
! 363: val = istgt_get_nval(sp, "Netmask", i);
! 364: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Netmask %s\n", val);
! 365: istgt->initiator_group[idx].netmasks[i] = xstrdup(val);
! 366: }
! 367:
! 368: idx++;
! 369: istgt->ninitiator_group = idx;
! 370: } else {
! 371: ISTGT_ERRLOG("ninitiator_group(%d) >= MAX_INITIATOR_GROUP\n", idx);
! 372: return -1;
! 373: }
! 374: return 0;
! 375: }
! 376:
! 377: static int
! 378: istgt_build_initiator_group_array(ISTGT_Ptr istgt)
! 379: {
! 380: CF_SECTION *sp;
! 381: int rc;
! 382:
! 383: sp = istgt->config->section;
! 384: while (sp != NULL) {
! 385: if (sp->type == ST_INITIATORGROUP) {
! 386: if (sp->num == 0) {
! 387: ISTGT_ERRLOG("Group 0 is invalid\n");
! 388: return -1;
! 389: }
! 390: rc = istgt_add_initiator_group(istgt, sp);
! 391: if (rc < 0) {
! 392: ISTGT_ERRLOG("add_initiator_group() failed\n");
! 393: return -1;
! 394: }
! 395: }
! 396: sp = sp->next;
! 397: }
! 398: return 0;
! 399: }
! 400:
! 401: static void
! 402: istgt_destory_initiator_group_array(ISTGT_Ptr istgt)
! 403: {
! 404: int i, j;
! 405:
! 406: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destory_initiator_group_array\n");
! 407: for (i = 0; i < istgt->ninitiator_group; i++) {
! 408: for (j = 0; j < istgt->initiator_group[i].ninitiators; j++) {
! 409: xfree(istgt->initiator_group[i].initiators[j]);
! 410: }
! 411: xfree(istgt->initiator_group[i].initiators);
! 412: for (j = 0; j < istgt->initiator_group[i].nnetmasks; j++) {
! 413: xfree(istgt->initiator_group[i].netmasks[j]);
! 414: }
! 415: xfree(istgt->initiator_group[i].netmasks);
! 416:
! 417: istgt->initiator_group[i].ninitiators = 0;
! 418: istgt->initiator_group[i].initiators = NULL;
! 419: istgt->initiator_group[i].nnetmasks = 0;
! 420: istgt->initiator_group[i].netmasks = NULL;
! 421: istgt->initiator_group[i].idx = i;
! 422: istgt->initiator_group[i].tag = 0;
! 423: }
! 424: istgt->ninitiator_group = 0;
! 425: }
! 426:
! 427: static int
! 428: istgt_build_uctl_portal(ISTGT_Ptr istgt)
! 429: {
! 430: CF_SECTION *sp;
! 431: const char *val;
! 432: char *label, *portal, *host, *port;
! 433: int tag;
! 434: int idx;
! 435: int rc;
! 436: int i;
! 437:
! 438: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_build_uctl_portal\n");
! 439:
! 440: sp = istgt_find_cf_section(istgt->config, "UnitControl");
! 441: if (sp == NULL) {
! 442: ISTGT_ERRLOG("find_cf_section failed()\n");
! 443: return -1;
! 444: }
! 445:
! 446: for (i = 0; ; i++) {
! 447: val = istgt_get_nval(sp, "Portal", i);
! 448: if (val == NULL)
! 449: break;
! 450:
! 451: label = istgt_get_nmval(sp, "Portal", i, 0);
! 452: portal = istgt_get_nmval(sp, "Portal", i, 1);
! 453: if (label == NULL || portal == NULL) {
! 454: ISTGT_ERRLOG("uctl portal error\n");
! 455: return -1;
! 456: }
! 457:
! 458: rc = istgt_parse_portal(portal, &host, &port);
! 459: if (rc < 0) {
! 460: ISTGT_ERRLOG("parse uctl portal error\n");
! 461: return -1;
! 462: }
! 463:
! 464: idx = istgt->nuctl_portal;
! 465: tag = ISTGT_UC_TAG;
! 466: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 467: "Index=%d, Host=%s, Port=%s, Tag=%d\n",
! 468: idx, host, port, tag);
! 469: if (idx < MAX_UCPORTAL) {
! 470: istgt->uctl_portal[idx].label = xstrdup(label);
! 471: istgt->uctl_portal[idx].host = host;
! 472: istgt->uctl_portal[idx].port = port;
! 473: istgt->uctl_portal[idx].idx = idx;
! 474: istgt->uctl_portal[idx].tag = tag;
! 475: istgt->uctl_portal[idx].sock = -1;
! 476: idx++;
! 477: istgt->nuctl_portal = idx;
! 478: } else {
! 479: ISTGT_ERRLOG("nportal(%d) >= MAX_UCPORTAL\n", idx);
! 480: xfree(host);
! 481: xfree(port);
! 482: return -1;
! 483: }
! 484: }
! 485:
! 486: return 0;
! 487: }
! 488:
! 489: static void
! 490: istgt_destroy_uctl_portal(ISTGT_Ptr istgt)
! 491: {
! 492: int i;
! 493:
! 494: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_destroy_uctl_portal\n");
! 495: for (i = 0; i < istgt->nportal; i++) {
! 496: xfree(istgt->uctl_portal[i].label);
! 497: xfree(istgt->uctl_portal[i].host);
! 498: xfree(istgt->uctl_portal[i].port);
! 499:
! 500: istgt->uctl_portal[i].label = NULL;
! 501: istgt->uctl_portal[i].host = NULL;
! 502: istgt->uctl_portal[i].port = NULL;
! 503: istgt->uctl_portal[i].idx = i;
! 504: istgt->uctl_portal[i].tag = 0;
! 505: }
! 506: istgt->nuctl_portal = 0;
! 507: }
! 508:
! 509: static int
! 510: istgt_open_uctl_portal(ISTGT_Ptr istgt)
! 511: {
! 512: int port;
! 513: int sock;
! 514: int i;
! 515:
! 516: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_open_uctl_portal\n");
! 517: for (i = 0; i < istgt->nuctl_portal; i++) {
! 518: if (istgt->uctl_portal[i].sock < 0) {
! 519: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 520: "open host %s, port %s, tag %d\n",
! 521: istgt->uctl_portal[i].host,
! 522: istgt->uctl_portal[i].port,
! 523: istgt->uctl_portal[i].tag);
! 524: port = (int)strtol(istgt->uctl_portal[i].port, NULL, 0);
! 525: sock = istgt_listen(istgt->uctl_portal[i].host, port);
! 526: if (sock < 0) {
! 527: ISTGT_ERRLOG("listen error %.64s:%d\n",
! 528: istgt->uctl_portal[i].host, port);
! 529: return -1;
! 530: }
! 531: istgt->uctl_portal[i].sock = sock;
! 532: }
! 533: }
! 534: return 0;
! 535: }
! 536:
! 537: static int
! 538: istgt_close_uctl_portal(ISTGT_Ptr istgt)
! 539: {
! 540: int i;
! 541:
! 542: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_close_uctl_portal\n");
! 543: for (i = 0; i < istgt->nuctl_portal; i++) {
! 544: if (istgt->uctl_portal[i].sock >= 0) {
! 545: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 546: "close host %s, port %s, tag %d\n",
! 547: istgt->uctl_portal[i].host,
! 548: istgt->uctl_portal[i].port,
! 549: istgt->uctl_portal[i].tag);
! 550: close(istgt->uctl_portal[i].sock);
! 551: istgt->uctl_portal[i].sock = -1;
! 552: }
! 553: }
! 554: return 0;
! 555: }
! 556:
! 557: static int
! 558: istgt_write_pidfile(ISTGT_Ptr istgt)
! 559: {
! 560: FILE *fp;
! 561: pid_t pid;
! 562: int rc;
! 563:
! 564: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_write_pidfile\n");
! 565: rc = remove(istgt->pidfile);
! 566: if (rc != 0) {
! 567: if (errno != ENOENT) {
! 568: ISTGT_ERRLOG("pidfile remove error %d\n", errno);
! 569: return -1;
! 570: }
! 571: }
! 572: fp = fopen(istgt->pidfile, "w");
! 573: if (fp == NULL) {
! 574: ISTGT_ERRLOG("pidfile open error %d\n", errno);
! 575: return -1;
! 576: }
! 577: pid = getpid();
! 578: fprintf(fp, "%d\n", (int)pid);
! 579: fclose(fp);
! 580: return 0;
! 581: }
! 582:
! 583: static void
! 584: istgt_remove_pidfile(ISTGT_Ptr istgt)
! 585: {
! 586: int rc;
! 587:
! 588: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_remove_pidfile\n");
! 589: rc = remove(istgt->pidfile);
! 590: if (rc != 0) {
! 591: ISTGT_ERRLOG("pidfile remove error %d\n", errno);
! 592: /* ignore error */
! 593: }
! 594: }
! 595:
! 596: char *
! 597: istgt_get_nmval(CF_SECTION *sp, const char *key, int idx1, int idx2)
! 598: {
! 599: CF_ITEM *ip;
! 600: CF_VALUE *vp;
! 601: int i;
! 602:
! 603: ip = istgt_find_cf_nitem(sp, key, idx1);
! 604: if (ip == NULL)
! 605: return NULL;
! 606: vp = ip->val;
! 607: if (vp == NULL)
! 608: return NULL;
! 609: for (i = 0; vp != NULL; vp = vp->next) {
! 610: if (i == idx2)
! 611: return vp->value;
! 612: i++;
! 613: }
! 614: return NULL;
! 615: }
! 616:
! 617: char *
! 618: istgt_get_nval(CF_SECTION *sp, const char *key, int idx)
! 619: {
! 620: CF_ITEM *ip;
! 621: CF_VALUE *vp;
! 622:
! 623: ip = istgt_find_cf_nitem(sp, key, idx);
! 624: if (ip == NULL)
! 625: return NULL;
! 626: vp = ip->val;
! 627: if (vp == NULL)
! 628: return NULL;
! 629: return vp->value;
! 630: }
! 631:
! 632: char *
! 633: istgt_get_val(CF_SECTION *sp, const char *key)
! 634: {
! 635: return istgt_get_nval(sp, key, 0);
! 636: }
! 637:
! 638: int
! 639: istgt_get_nintval(CF_SECTION *sp, const char *key, int idx)
! 640: {
! 641: const char *v;
! 642: int value;
! 643:
! 644: v = istgt_get_nval(sp, key, idx);
! 645: if (v == NULL)
! 646: return -1;
! 647: value = (int)strtol(v, NULL, 10);
! 648: return value;
! 649: }
! 650:
! 651: int
! 652: istgt_get_intval(CF_SECTION *sp, const char *key)
! 653: {
! 654: return istgt_get_nintval(sp, key, 0);
! 655: }
! 656:
! 657: static const char *
! 658: istgt_get_log_facility(CONFIG *config)
! 659: {
! 660: CF_SECTION *sp;
! 661: const char *logfacility;
! 662:
! 663: sp = istgt_find_cf_section(config, "Global");
! 664: if (sp == NULL) {
! 665: return NULL;
! 666: }
! 667: logfacility = istgt_get_val(sp, "LogFacility");
! 668: if (logfacility == NULL) {
! 669: logfacility = DEFAULT_LOG_FACILITY;
! 670: }
! 671: #if 0
! 672: if (g_trace_flag & ISTGT_TRACE_DEBUG) {
! 673: fprintf(stderr, "LogFacility %s\n", logfacility);
! 674: }
! 675: #endif
! 676:
! 677: return logfacility;
! 678: }
! 679:
! 680: static int
! 681: istgt_init(ISTGT_Ptr istgt)
! 682: {
! 683: CF_SECTION *sp;
! 684: const char *ag_tag;
! 685: const char *val;
! 686: size_t stacksize;
! 687: int ag_tag_i;
! 688: int MaxSessions;
! 689: int MaxConnections;
! 690: int MaxOutstandingR2T;
! 691: int DefaultTime2Wait;
! 692: int DefaultTime2Retain;
! 693: int FirstBurstLength;
! 694: int MaxBurstLength;
! 695: int MaxRecvDataSegmentLength;
! 696: int InitialR2T;
! 697: int ImmediateData;
! 698: int DataPDUInOrder;
! 699: int DataSequenceInOrder;
! 700: int ErrorRecoveryLevel;
! 701: int timeout;
! 702: int nopininterval;
! 703: int maxr2t;
! 704: int rc;
! 705: int i;
! 706:
! 707: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_init\n");
! 708: sp = istgt_find_cf_section(istgt->config, "Global");
! 709: if (sp == NULL) {
! 710: ISTGT_ERRLOG("find_cf_section failed()\n");
! 711: return -1;
! 712: }
! 713:
! 714: val = istgt_get_val(sp, "Comment");
! 715: if (val != NULL) {
! 716: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
! 717: }
! 718:
! 719: val = istgt_get_val(sp, "PidFile");
! 720: if (val == NULL) {
! 721: val = DEFAULT_PIDFILE;
! 722: }
! 723: istgt->pidfile = xstrdup(val);
! 724: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "PidFile %s\n",
! 725: istgt->pidfile);
! 726:
! 727: val = istgt_get_val(sp, "AuthFile");
! 728: if (val == NULL) {
! 729: val = DEFAULT_AUTHFILE;
! 730: }
! 731: istgt->authfile = xstrdup(val);
! 732: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthFile %s\n",
! 733: istgt->authfile);
! 734:
! 735: #if 0
! 736: val = istgt_get_val(sp, "MediaFile");
! 737: if (val == NULL) {
! 738: val = DEFAULT_MEDIAFILE;
! 739: }
! 740: istgt->mediafile = xstrdup(val);
! 741: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaFile %s\n",
! 742: istgt->mediafile);
! 743: #endif
! 744:
! 745: #if 0
! 746: val = istgt_get_val(sp, "LiveFile");
! 747: if (val == NULL) {
! 748: val = DEFAULT_LIVEFILE;
! 749: }
! 750: istgt->livefile = xstrdup(val);
! 751: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LiveFile %s\n",
! 752: istgt->livefile);
! 753: #endif
! 754:
! 755: val = istgt_get_val(sp, "MediaDirectory");
! 756: if (val == NULL) {
! 757: val = DEFAULT_MEDIADIRECTORY;
! 758: }
! 759: istgt->mediadirectory = xstrdup(val);
! 760: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MediaDirectory %s\n",
! 761: istgt->mediadirectory);
! 762:
! 763: val = istgt_get_val(sp, "NodeBase");
! 764: if (val == NULL) {
! 765: val = DEFAULT_NODEBASE;
! 766: }
! 767: istgt->nodebase = xstrdup(val);
! 768: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NodeBase %s\n",
! 769: istgt->nodebase);
! 770:
! 771: MaxSessions = istgt_get_intval(sp, "MaxSessions");
! 772: if (MaxSessions < 1) {
! 773: MaxSessions = DEFAULT_MAX_SESSIONS;
! 774: }
! 775: istgt->MaxSessions = MaxSessions;
! 776: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxSessions %d\n",
! 777: istgt->MaxSessions);
! 778:
! 779: MaxConnections = istgt_get_intval(sp, "MaxConnections");
! 780: if (MaxConnections < 1) {
! 781: MaxConnections = DEFAULT_MAX_CONNECTIONS;
! 782: }
! 783: istgt->MaxConnections = MaxConnections;
! 784: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxConnections %d\n",
! 785: istgt->MaxConnections);
! 786:
! 787: /* limited to 16bits - RFC3720(12.2) */
! 788: if (MaxSessions > 0xffff) {
! 789: ISTGT_ERRLOG("over 65535 sessions are not supported\n");
! 790: return -1;
! 791: }
! 792: if (MaxConnections > 0xffff) {
! 793: ISTGT_ERRLOG("over 65535 connections are not supported\n");
! 794: return -1;
! 795: }
! 796:
! 797: MaxOutstandingR2T = istgt_get_intval(sp, "MaxOutstandingR2T");
! 798: if (MaxOutstandingR2T < 1) {
! 799: MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T;
! 800: }
! 801: istgt->MaxOutstandingR2T = MaxOutstandingR2T;
! 802: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxOutstandingR2T %d\n",
! 803: istgt->MaxOutstandingR2T);
! 804:
! 805: DefaultTime2Wait = istgt_get_intval(sp, "DefaultTime2Wait");
! 806: if (DefaultTime2Wait < 0) {
! 807: DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
! 808: }
! 809: istgt->DefaultTime2Wait = DefaultTime2Wait;
! 810: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Wait %d\n",
! 811: istgt->DefaultTime2Wait);
! 812:
! 813: DefaultTime2Retain = istgt_get_intval(sp, "DefaultTime2Retain");
! 814: if (DefaultTime2Retain < 0) {
! 815: DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
! 816: }
! 817: istgt->DefaultTime2Retain = DefaultTime2Retain;
! 818: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Retain %d\n",
! 819: istgt->DefaultTime2Retain);
! 820:
! 821: /* check size limit - RFC3720(12.15, 12.16, 12.17) */
! 822: if (istgt->MaxOutstandingR2T > 65535) {
! 823: ISTGT_ERRLOG("MaxOutstandingR2T(%d) > 65535\n",
! 824: istgt->MaxOutstandingR2T);
! 825: return -1;
! 826: }
! 827: if (istgt->DefaultTime2Wait > 3600) {
! 828: ISTGT_ERRLOG("DefaultTime2Wait(%d) > 3600\n",
! 829: istgt->DefaultTime2Wait);
! 830: return -1;
! 831: }
! 832: if (istgt->DefaultTime2Retain > 3600) {
! 833: ISTGT_ERRLOG("DefaultTime2Retain(%d) > 3600\n",
! 834: istgt->DefaultTime2Retain);
! 835: return -1;
! 836: }
! 837:
! 838: FirstBurstLength = istgt_get_intval(sp, "FirstBurstLength");
! 839: if (FirstBurstLength < 0) {
! 840: FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
! 841: }
! 842: istgt->FirstBurstLength = FirstBurstLength;
! 843: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "FirstBurstLength %d\n",
! 844: istgt->FirstBurstLength);
! 845:
! 846: MaxBurstLength = istgt_get_intval(sp, "MaxBurstLength");
! 847: if (MaxBurstLength < 0) {
! 848: MaxBurstLength = DEFAULT_MAXBURSTLENGTH;
! 849: }
! 850: istgt->MaxBurstLength = MaxBurstLength;
! 851: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxBurstLength %d\n",
! 852: istgt->MaxBurstLength);
! 853:
! 854: MaxRecvDataSegmentLength
! 855: = istgt_get_intval(sp, "MaxRecvDataSegmentLength");
! 856: if (MaxRecvDataSegmentLength < 0) {
! 857: MaxRecvDataSegmentLength = DEFAULT_MAXRECVDATASEGMENTLENGTH;
! 858: }
! 859: istgt->MaxRecvDataSegmentLength = MaxRecvDataSegmentLength;
! 860: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxRecvDataSegmentLength %d\n",
! 861: istgt->MaxRecvDataSegmentLength);
! 862:
! 863: /* check size limit (up to 24bits - RFC3720(12.12)) */
! 864: if (istgt->MaxBurstLength < 512) {
! 865: ISTGT_ERRLOG("MaxBurstLength(%d) < 512\n",
! 866: istgt->MaxBurstLength);
! 867: return -1;
! 868: }
! 869: if (istgt->FirstBurstLength < 512) {
! 870: ISTGT_ERRLOG("FirstBurstLength(%d) < 512\n",
! 871: istgt->FirstBurstLength);
! 872: return -1;
! 873: }
! 874: if (istgt->FirstBurstLength > istgt->MaxBurstLength) {
! 875: ISTGT_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
! 876: istgt->FirstBurstLength, istgt->MaxBurstLength);
! 877: return -1;
! 878: }
! 879: if (istgt->MaxBurstLength > 0x00ffffff) {
! 880: ISTGT_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
! 881: istgt->MaxBurstLength);
! 882: return -1;
! 883: }
! 884: if (istgt->MaxRecvDataSegmentLength < 512) {
! 885: ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
! 886: istgt->MaxRecvDataSegmentLength);
! 887: return -1;
! 888: }
! 889: if (istgt->MaxRecvDataSegmentLength > 0x00ffffff) {
! 890: ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
! 891: istgt->MaxRecvDataSegmentLength);
! 892: return -1;
! 893: }
! 894:
! 895: val = istgt_get_val(sp, "InitialR2T");
! 896: if (val == NULL) {
! 897: InitialR2T = DEFAULT_INITIALR2T;
! 898: } else if (strcasecmp(val, "Yes") == 0) {
! 899: InitialR2T = 1;
! 900: } else if (strcasecmp(val, "No") == 0) {
! 901: #if 0
! 902: InitialR2T = 0;
! 903: #else
! 904: ISTGT_ERRLOG("not supported value %s\n", val);
! 905: return -1;
! 906: #endif
! 907: } else {
! 908: ISTGT_ERRLOG("unknown value %s\n", val);
! 909: return -1;
! 910: }
! 911: istgt->InitialR2T = InitialR2T;
! 912: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "InitialR2T %s\n",
! 913: istgt->InitialR2T ? "Yes" : "No");
! 914:
! 915: val = istgt_get_val(sp, "ImmediateData");
! 916: if (val == NULL) {
! 917: ImmediateData = DEFAULT_IMMEDIATEDATA;
! 918: } else if (strcasecmp(val, "Yes") == 0) {
! 919: ImmediateData = 1;
! 920: } else if (strcasecmp(val, "No") == 0) {
! 921: ImmediateData = 0;
! 922: } else {
! 923: ISTGT_ERRLOG("unknown value %s\n", val);
! 924: return -1;
! 925: }
! 926: istgt->ImmediateData = ImmediateData;
! 927: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ImmediateData %s\n",
! 928: istgt->ImmediateData ? "Yes" : "No");
! 929:
! 930: val = istgt_get_val(sp, "DataPDUInOrder");
! 931: if (val == NULL) {
! 932: DataPDUInOrder = DEFAULT_DATAPDUINORDER;
! 933: } else if (strcasecmp(val, "Yes") == 0) {
! 934: DataPDUInOrder = 1;
! 935: } else if (strcasecmp(val, "No") == 0) {
! 936: #if 0
! 937: DataPDUInOrder = 0;
! 938: #else
! 939: ISTGT_ERRLOG("not supported value %s\n", val);
! 940: return -1;
! 941: #endif
! 942: } else {
! 943: ISTGT_ERRLOG("unknown value %s\n", val);
! 944: return -1;
! 945: }
! 946: istgt->DataPDUInOrder = DataPDUInOrder;
! 947: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataPDUInOrder %s\n",
! 948: istgt->DataPDUInOrder ? "Yes" : "No");
! 949:
! 950: val = istgt_get_val(sp, "DataSequenceInOrder");
! 951: if (val == NULL) {
! 952: DataSequenceInOrder = DEFAULT_DATASEQUENCEINORDER;
! 953: } else if (strcasecmp(val, "Yes") == 0) {
! 954: DataSequenceInOrder = 1;
! 955: } else if (strcasecmp(val, "No") == 0) {
! 956: #if 0
! 957: DataSequenceInOrder = 0;
! 958: #else
! 959: ISTGT_ERRLOG("not supported value %s\n", val);
! 960: return -1;
! 961: #endif
! 962: } else {
! 963: ISTGT_ERRLOG("unknown value %s\n", val);
! 964: return -1;
! 965: }
! 966: istgt->DataSequenceInOrder = DataSequenceInOrder;
! 967: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataSequenceInOrder %s\n",
! 968: istgt->DataSequenceInOrder ? "Yes" : "No");
! 969:
! 970: ErrorRecoveryLevel = istgt_get_intval(sp, "ErrorRecoveryLevel");
! 971: if (ErrorRecoveryLevel < 0) {
! 972: ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
! 973: } else if (ErrorRecoveryLevel == 0) {
! 974: ErrorRecoveryLevel = 0;
! 975: } else if (ErrorRecoveryLevel == 1) {
! 976: #if 0
! 977: ErrorRecoveryLevel = 1;
! 978: #else
! 979: ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
! 980: return -1;
! 981: #endif
! 982: } else if (ErrorRecoveryLevel == 2) {
! 983: #if 0
! 984: ErrorRecoveryLevel = 2;
! 985: #else
! 986: ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
! 987: return -1;
! 988: #endif
! 989: } else {
! 990: ISTGT_ERRLOG("not supported value %d\n", ErrorRecoveryLevel);
! 991: return -1;
! 992: }
! 993: istgt->ErrorRecoveryLevel = ErrorRecoveryLevel;
! 994: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ErrorRecoveryLevel %d\n",
! 995: istgt->ErrorRecoveryLevel);
! 996:
! 997: timeout = istgt_get_intval(sp, "Timeout");
! 998: if (timeout < 0) {
! 999: timeout = DEFAULT_TIMEOUT;
! 1000: }
! 1001: istgt->timeout = timeout;
! 1002: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Timeout %d\n",
! 1003: istgt->timeout);
! 1004:
! 1005: nopininterval = istgt_get_intval(sp, "NopInInterval");
! 1006: if (nopininterval < 0) {
! 1007: nopininterval = DEFAULT_NOPININTERVAL;
! 1008: }
! 1009: istgt->nopininterval = nopininterval;
! 1010: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "NopInInterval %d\n",
! 1011: istgt->nopininterval);
! 1012:
! 1013: maxr2t = istgt_get_intval(sp, "MaxR2T");
! 1014: if (maxr2t < 0) {
! 1015: maxr2t = DEFAULT_MAXR2T;
! 1016: }
! 1017: if (maxr2t > MAX_R2T) {
! 1018: ISTGT_ERRLOG("MaxR2T(%d) > %d\n",
! 1019: maxr2t, MAX_R2T);
! 1020: return -1;
! 1021: }
! 1022: istgt->maxr2t = maxr2t;
! 1023: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxR2T %d\n",
! 1024: istgt->maxr2t);
! 1025:
! 1026: val = istgt_get_val(sp, "DiscoveryAuthMethod");
! 1027: if (val == NULL) {
! 1028: istgt->no_discovery_auth = 0;
! 1029: istgt->req_discovery_auth = 0;
! 1030: istgt->req_discovery_auth_mutual = 0;
! 1031: } else {
! 1032: istgt->no_discovery_auth = 0;
! 1033: for (i = 0; ; i++) {
! 1034: val = istgt_get_nmval(sp, "DiscoveryAuthMethod", 0, i);
! 1035: if (val == NULL)
! 1036: break;
! 1037: if (strcasecmp(val, "CHAP") == 0) {
! 1038: istgt->req_discovery_auth = 1;
! 1039: } else if (strcasecmp(val, "Mutual") == 0) {
! 1040: istgt->req_discovery_auth_mutual = 1;
! 1041: } else if (strcasecmp(val, "Auto") == 0) {
! 1042: istgt->req_discovery_auth = 0;
! 1043: istgt->req_discovery_auth_mutual = 0;
! 1044: } else if (strcasecmp(val, "None") == 0) {
! 1045: istgt->no_discovery_auth = 1;
! 1046: istgt->req_discovery_auth = 0;
! 1047: istgt->req_discovery_auth_mutual = 0;
! 1048: } else {
! 1049: ISTGT_ERRLOG("unknown auth\n");
! 1050: return -1;
! 1051: }
! 1052: }
! 1053: if (istgt->req_discovery_auth_mutual && !istgt->req_discovery_auth) {
! 1054: ISTGT_ERRLOG("Mutual but not CHAP\n");
! 1055: return -1;
! 1056: }
! 1057: }
! 1058: if (istgt->no_discovery_auth != 0) {
! 1059: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1060: "DiscoveryAuthMethod None\n");
! 1061: } else if (istgt->req_discovery_auth == 0) {
! 1062: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1063: "DiscoveryAuthMethod Auto\n");
! 1064: } else {
! 1065: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1066: "DiscoveryAuthMethod %s %s\n",
! 1067: istgt->req_discovery_auth ? "CHAP" : "",
! 1068: istgt->req_discovery_auth_mutual ? "Mutual" : "");
! 1069: }
! 1070:
! 1071: val = istgt_get_val(sp, "DiscoveryAuthGroup");
! 1072: if (val == NULL) {
! 1073: istgt->discovery_auth_group = 0;
! 1074: } else {
! 1075: ag_tag = val;
! 1076: if (strcasecmp(ag_tag, "None") == 0) {
! 1077: ag_tag_i = 0;
! 1078: } else {
! 1079: if (strncasecmp(ag_tag, "AuthGroup",
! 1080: strlen("AuthGroup")) != 0
! 1081: || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) {
! 1082: ISTGT_ERRLOG("auth group error\n");
! 1083: return -1;
! 1084: }
! 1085: if (ag_tag_i == 0) {
! 1086: ISTGT_ERRLOG("invalid auth group %d\n",
! 1087: ag_tag_i);
! 1088: return -1;
! 1089: }
! 1090: }
! 1091: istgt->discovery_auth_group = ag_tag_i;
! 1092: }
! 1093: if (istgt->discovery_auth_group == 0) {
! 1094: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1095: "DiscoveryAuthGroup None\n");
! 1096: } else {
! 1097: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1098: "DiscoveryAuthGroup AuthGroup%d\n",
! 1099: istgt->discovery_auth_group);
! 1100: }
! 1101:
! 1102: rc = istgt_init_uctl(istgt);
! 1103: if (rc < 0) {
! 1104: ISTGT_ERRLOG("istgt_init_uctl() failed\n");
! 1105: return -1;
! 1106: }
! 1107: rc = istgt_build_uctl_portal(istgt);
! 1108: if (rc < 0) {
! 1109: ISTGT_ERRLOG("istgt_build_uctl_portal() failed\n");
! 1110: return -1;
! 1111: }
! 1112: rc = istgt_build_portal_array(istgt);
! 1113: if (rc < 0) {
! 1114: ISTGT_ERRLOG("istgt_build_portal_array() failed\n");
! 1115: return -1;
! 1116: }
! 1117: rc = istgt_build_initiator_group_array(istgt);
! 1118: if (rc < 0) {
! 1119: ISTGT_ERRLOG("build_initiator_group_array() failed\n");
! 1120: return -1;
! 1121: }
! 1122:
! 1123: rc = pthread_attr_init(&istgt->attr);
! 1124: if (rc != 0) {
! 1125: ISTGT_ERRLOG("pthread_attr_init() failed\n");
! 1126: return -1;
! 1127: }
! 1128: rc = pthread_attr_getstacksize(&istgt->attr, &stacksize);
! 1129: if (rc != 0) {
! 1130: ISTGT_ERRLOG("pthread_attr_getstacksize() failed\n");
! 1131: return -1;
! 1132: }
! 1133: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "current thread stack = %zd\n", stacksize);
! 1134: if (stacksize < ISTGT_STACKSIZE) {
! 1135: stacksize = ISTGT_STACKSIZE;
! 1136: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "new thread stack = %zd\n", stacksize);
! 1137: rc = pthread_attr_setstacksize(&istgt->attr, stacksize);
! 1138: if (rc != 0) {
! 1139: ISTGT_ERRLOG("pthread_attr_setstacksize() failed\n");
! 1140: return -1;
! 1141: }
! 1142: }
! 1143:
! 1144: rc = pthread_mutex_init(&istgt->mutex, NULL);
! 1145: if (rc != 0) {
! 1146: ISTGT_ERRLOG("mutex_init() failed\n");
! 1147: return -1;
! 1148: }
! 1149:
! 1150: /* XXX TODO: add initializer */
! 1151:
! 1152: istgt_set_state(istgt, ISTGT_STATE_INITIALIZED);
! 1153:
! 1154: return 0;
! 1155: }
! 1156:
! 1157: #ifdef SIGINFO
! 1158: static void
! 1159: istgt_siginfo(int signo)
! 1160: {
! 1161: /* nothing */
! 1162: }
! 1163: #endif
! 1164:
! 1165: static void
! 1166: istgt_sigwakeup(int signo)
! 1167: {
! 1168: }
! 1169:
! 1170: #ifdef SIGIO
! 1171: static void
! 1172: istgt_sigio(int signo)
! 1173: {
! 1174: }
! 1175: #endif
! 1176:
! 1177: static void *
! 1178: istgt_sighandler(void *arg)
! 1179: {
! 1180: ISTGT_Ptr istgt = (ISTGT_Ptr) arg;
! 1181: sigset_t signew;
! 1182: int signo;
! 1183:
! 1184: sigemptyset(&signew);
! 1185: sigaddset(&signew, SIGINT);
! 1186: sigaddset(&signew, SIGTERM);
! 1187: sigaddset(&signew, SIGQUIT);
! 1188: sigaddset(&signew, SIGHUP);
! 1189: #ifdef SIGINFO
! 1190: sigaddset(&signew, SIGINFO);
! 1191: #endif
! 1192: sigaddset(&signew, SIGUSR1);
! 1193: sigaddset(&signew, SIGUSR2);
! 1194: #ifdef SIGIO
! 1195: sigaddset(&signew, SIGIO);
! 1196: #endif
! 1197:
! 1198: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
! 1199: while (1) {
! 1200: if (istgt_get_state(istgt) == ISTGT_STATE_EXITING
! 1201: || istgt_get_state(istgt) == ISTGT_STATE_SHUTDOWN) {
! 1202: break;
! 1203: }
! 1204: sigwait(&signew, &signo);
! 1205: switch (signo) {
! 1206: case SIGINT:
! 1207: printf("SIGINT catch\n");
! 1208: istgt_set_state(istgt, ISTGT_STATE_EXITING);
! 1209: istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
! 1210: break;
! 1211: case SIGTERM:
! 1212: printf("SIGTERM catch\n");
! 1213: istgt_set_state(istgt, ISTGT_STATE_EXITING);
! 1214: istgt_lu_set_all_state(istgt, ISTGT_STATE_EXITING);
! 1215: break;
! 1216: case SIGQUIT:
! 1217: printf("SIGQUIT catch\n");
! 1218: exit(EXIT_SUCCESS);
! 1219: break;
! 1220: case SIGHUP:
! 1221: printf("SIGHUP catch\n");
! 1222: break;
! 1223: #ifdef SIGINFO
! 1224: case SIGINFO:
! 1225: printf("SIGINFO catch\n");
! 1226: istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
! 1227: break;
! 1228: #endif
! 1229: case SIGUSR1:
! 1230: printf("SIGUSR1 catch\n");
! 1231: istgt_set_trace_flag(ISTGT_TRACE_NONE);
! 1232: break;
! 1233: case SIGUSR2:
! 1234: printf("SIGUSR2 catch\n");
! 1235: //istgt_set_trace_flag(ISTGT_TRACE_SCSI);
! 1236: istgt_set_trace_flag(ISTGT_TRACE_ALL);
! 1237: break;
! 1238: #ifdef SIGIO
! 1239: case SIGIO:
! 1240: //printf("SIGIO catch\n");
! 1241: break;
! 1242: #endif
! 1243: default:
! 1244: break;
! 1245: }
! 1246: }
! 1247: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
! 1248:
! 1249: return NULL;
! 1250: }
! 1251:
! 1252: static int
! 1253: istgt_acceptor(ISTGT_Ptr istgt)
! 1254: {
! 1255: #ifdef ISTGT_USE_KQUEUE
! 1256: int kq;
! 1257: struct kevent kev;
! 1258: struct timespec kev_timeout;
! 1259: #else
! 1260: struct pollfd fds[MAX_PORTAL + MAX_UCPORTAL];
! 1261: #endif /* ISTGT_USE_KQUEUE */
! 1262: struct sockaddr_storage sa;
! 1263: socklen_t salen;
! 1264: int sock;
! 1265: int rc, n;
! 1266: int ucidx;
! 1267: int nidx;
! 1268: int i;
! 1269:
! 1270: if (istgt_get_state(istgt) != ISTGT_STATE_INITIALIZED) {
! 1271: ISTGT_ERRLOG("not initialized\n");
! 1272: return -1;
! 1273: }
! 1274: /* now running main thread */
! 1275: istgt_set_state(istgt, ISTGT_STATE_RUNNING);
! 1276:
! 1277: #ifdef ISTGT_USE_KQUEUE
! 1278: kq = kqueue();
! 1279: if (kq == -1) {
! 1280: ISTGT_ERRLOG("kqueue() failed\n");
! 1281: return -1;
! 1282: }
! 1283: for (i = 0; i < istgt->nportal; i++) {
! 1284: EV_SET(&kev, istgt->portal[i].sock,
! 1285: EVFILT_READ, EV_ADD, 0, 0, NULL);
! 1286: rc = kevent(kq, &kev, 1, NULL, 0, NULL);
! 1287: if (rc == -1) {
! 1288: ISTGT_ERRLOG("kevent() failed\n");
! 1289: close(kq);
! 1290: return -1;
! 1291: }
! 1292: }
! 1293: ucidx = istgt->nportal;
! 1294: for (i = 0; i < istgt->nuctl_portal; i++) {
! 1295: EV_SET(&kev, istgt->uctl_portal[i].sock,
! 1296: EVFILT_READ, EV_ADD, 0, 0, NULL);
! 1297: rc = kevent(kq, &kev, 1, NULL, 0, NULL);
! 1298: if (rc == -1) {
! 1299: ISTGT_ERRLOG("kevent() failed\n");
! 1300: close(kq);
! 1301: return -1;
! 1302: }
! 1303: }
! 1304: nidx = istgt->nportal + istgt->nuctl_portal;
! 1305:
! 1306: EV_SET(&kev, SIGINT, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
! 1307: rc = kevent(kq, &kev, 1, NULL, 0, NULL);
! 1308: if (rc == -1) {
! 1309: ISTGT_ERRLOG("kevent() failed\n");
! 1310: close(kq);
! 1311: return -1;
! 1312: }
! 1313: EV_SET(&kev, SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
! 1314: rc = kevent(kq, &kev, 1, NULL, 0, NULL);
! 1315: if (rc == -1) {
! 1316: ISTGT_ERRLOG("kevent() failed\n");
! 1317: close(kq);
! 1318: return -1;
! 1319: }
! 1320: #else
! 1321: memset(&fds, 0, sizeof fds);
! 1322: for (i = 0; i < istgt->nportal; i++) {
! 1323: fds[i].fd = istgt->portal[i].sock;
! 1324: fds[i].events = POLLIN;
! 1325: }
! 1326: ucidx = istgt->nportal;
! 1327: for (i = 0; i < istgt->nuctl_portal; i++) {
! 1328: fds[ucidx + i].fd = istgt->uctl_portal[i].sock;
! 1329: fds[ucidx + i].events = POLLIN;
! 1330: }
! 1331: nidx = istgt->nportal + istgt->nuctl_portal;
! 1332: #endif /* ISTGT_USE_KQUEUE */
! 1333:
! 1334: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop start\n");
! 1335: while (1) {
! 1336: if (istgt_get_state(istgt) != ISTGT_STATE_RUNNING) {
! 1337: break;
! 1338: }
! 1339: #ifdef ISTGT_USE_KQUEUE
! 1340: //ISTGT_TRACELOG(ISTGT_TRACE_NET, "kevent %d\n", nidx);
! 1341: kev_timeout.tv_sec = 10;
! 1342: kev_timeout.tv_nsec = 0;
! 1343: rc = kevent(kq, NULL, 0, &kev, 1, &kev_timeout);
! 1344: if (rc == -1 && errno == EINTR) {
! 1345: continue;
! 1346: }
! 1347: if (rc == -1) {
! 1348: ISTGT_ERRLOG("kevent() failed\n");
! 1349: break;
! 1350: }
! 1351: if (rc == 0) {
! 1352: /* idle timeout */
! 1353: continue;
! 1354: }
! 1355: if (kev.filter == EVFILT_SIGNAL) {
! 1356: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "kevent SIGNAL\n");
! 1357: if (kev.ident == SIGINT || kev.ident == SIGTERM) {
! 1358: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1359: "kevent SIGNAL SIGINT/SIGTERM\n");
! 1360: break;
! 1361: }
! 1362: continue;
! 1363: }
! 1364: #else
! 1365: //ISTGT_TRACELOG(ISTGT_TRACE_NET, "poll %d\n", nidx);
! 1366: rc = poll(fds, nidx, POLLWAIT);
! 1367: if (rc == -1 && errno == EINTR) {
! 1368: continue;
! 1369: }
! 1370: if (rc == -1) {
! 1371: ISTGT_ERRLOG("poll() failed\n");
! 1372: break;
! 1373: }
! 1374: if (rc == 0) {
! 1375: /* no fds */
! 1376: continue;
! 1377: }
! 1378: #endif /* ISTGT_USE_KQUEUE */
! 1379:
! 1380: n = rc;
! 1381: for (i = 0; n != 0 && i < istgt->nportal; i++) {
! 1382: #ifdef ISTGT_USE_KQUEUE
! 1383: if (kev.ident == istgt->portal[i].sock) {
! 1384: if (kev.flags) {
! 1385: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1386: "flags %x\n",
! 1387: kev.flags);
! 1388: }
! 1389: #else
! 1390: if (fds[i].revents) {
! 1391: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1392: "events %x\n",
! 1393: fds[i].revents);
! 1394: }
! 1395: if (fds[i].revents & POLLIN) {
! 1396: #endif /* ISTGT_USE_KQUEUE */
! 1397: n--;
! 1398: memset(&sa, 0, sizeof(sa));
! 1399: salen = sizeof(sa);
! 1400: #ifdef ISTGT_USE_KQUEUE
! 1401: ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
! 1402: kev.ident);
! 1403: rc = accept(kev.ident, (struct sockaddr *) &sa, &salen);
! 1404: #else
! 1405: ISTGT_TRACELOG(ISTGT_TRACE_NET, "accept %d\n",
! 1406: fds[i].fd);
! 1407: rc = accept(fds[i].fd, (struct sockaddr *) &sa, &salen);
! 1408: #endif /* ISTGT_USE_KQUEUE */
! 1409: if (rc < 0) {
! 1410: ISTGT_ERRLOG("accept error: %d\n", rc);
! 1411: continue;
! 1412: }
! 1413: sock = rc;
! 1414: #if 0
! 1415: rc = fcntl(sock, F_GETFL, 0);
! 1416: if (rc == -1) {
! 1417: ISTGT_ERRLOG("fcntl() failed\n");
! 1418: continue;
! 1419: }
! 1420: rc = fcntl(sock, F_SETFL, (rc | O_NONBLOCK));
! 1421: if (rc == -1) {
! 1422: ISTGT_ERRLOG("fcntl() failed\n");
! 1423: continue;
! 1424: }
! 1425: #endif
! 1426: rc = istgt_create_conn(istgt,
! 1427: &istgt->portal[i], sock,
! 1428: (struct sockaddr *) &sa, salen);
! 1429: if (rc < 0) {
! 1430: close(sock);
! 1431: ISTGT_ERRLOG("istgt_create_conn() failed\n");
! 1432: continue;
! 1433: }
! 1434: }
! 1435: }
! 1436:
! 1437: /* check for control */
! 1438: for (i = 0; n != 0 && i < istgt->nuctl_portal; i++) {
! 1439: #ifdef ISTGT_USE_KQUEUE
! 1440: if (kev.ident == istgt->uctl_portal[i].sock) {
! 1441: if (kev.flags) {
! 1442: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1443: "flags %x\n",
! 1444: kev.flags);
! 1445: }
! 1446: #else
! 1447: if (fds[ucidx + i].revents) {
! 1448: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1449: "events %x\n",
! 1450: fds[ucidx + i].revents);
! 1451: }
! 1452: if (fds[ucidx + i].revents & POLLIN) {
! 1453: #endif /* ISTGT_USE_KQUEUE */
! 1454: n--;
! 1455: memset(&sa, 0, sizeof(sa));
! 1456: salen = sizeof(sa);
! 1457: #ifdef ISTGT_USE_KQUEUE
! 1458: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 1459: "accept %d\n", kev.ident);
! 1460: rc = accept(kev.ident,
! 1461: (struct sockaddr *) &sa, &salen);
! 1462: #else
! 1463: ISTGT_TRACELOG(ISTGT_TRACE_NET,
! 1464: "accept %d\n", fds[ucidx + i].fd);
! 1465: rc = accept(fds[ucidx + i].fd,
! 1466: (struct sockaddr *) &sa, &salen);
! 1467: #endif /* ISTGT_USE_KQUEUE */
! 1468: if (rc < 0) {
! 1469: ISTGT_ERRLOG("accept error: %d\n", rc);
! 1470: continue;
! 1471: }
! 1472: sock = rc;
! 1473: rc = istgt_create_uctl(istgt,
! 1474: &istgt->uctl_portal[i], sock,
! 1475: (struct sockaddr *) &sa, salen);
! 1476: if (rc < 0) {
! 1477: close(sock);
! 1478: ISTGT_ERRLOG("istgt_create_uctl() failed\n");
! 1479: continue;
! 1480: }
! 1481: }
! 1482: }
! 1483: }
! 1484: #ifdef ISTGT_USE_KQUEUE
! 1485: close(kq);
! 1486: #endif /* ISTGT_USE_KQUEUE */
! 1487: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "loop ended\n");
! 1488: istgt_set_state(istgt, ISTGT_STATE_EXITING);
! 1489:
! 1490: return 0;
! 1491: }
! 1492:
! 1493: static void
! 1494: usage(void)
! 1495: {
! 1496: printf("istgt [options]\n");
! 1497: printf("options:\n");
! 1498: printf(" -c config config file (default %s)\n", DEFAULT_CONFIG);
! 1499: printf(" -p pidfile use specific file\n");
! 1500: printf(" -l facility use specific syslog facility (default %s)\n",
! 1501: DEFAULT_LOG_FACILITY);
! 1502: printf(" -m mode operational mode (default %d, 0=traditional, "
! 1503: "1=normal, 2=experimental)\n", DEFAULT_ISTGT_SWMODE);
! 1504: printf(" -t flag trace flag (all, net, iscsi, scsi, lu)\n");
! 1505: printf(" -q quiet warnings\n");
! 1506: printf(" -D don't detach from tty\n");
! 1507: printf(" -H show this usage\n");
! 1508: printf(" -V show version\n");
! 1509: }
! 1510:
! 1511: int
! 1512: main(int argc, char **argv)
! 1513: {
! 1514: ISTGT_Ptr istgt;
! 1515: const char *config_file = DEFAULT_CONFIG;
! 1516: const char *pidfile = NULL;
! 1517: const char *logfacility = NULL;
! 1518: const char *logpriority = NULL;
! 1519: CONFIG *config;
! 1520: pthread_t sigthread;
! 1521: struct sigaction sigact, sigoldact_pipe, sigoldact_info;
! 1522: struct sigaction sigoldact_wakeup, sigoldact_io;
! 1523: sigset_t signew, sigold;
! 1524: int retry = 10;
! 1525: int detach = 1;
! 1526: int swmode;
! 1527: int ch;
! 1528: int rc;
! 1529:
! 1530: if (sizeof (ISCSI_BHS) != ISCSI_BHS_LEN) {
! 1531: fprintf(stderr, "Internal Error\n");
! 1532: exit(EXIT_FAILURE);
! 1533: }
! 1534:
! 1535: memset(&g_istgt, 0, sizeof g_istgt);
! 1536: istgt = &g_istgt;
! 1537: istgt_set_state(istgt, ISTGT_STATE_INVALID);
! 1538: istgt->swmode = DEFAULT_ISTGT_SWMODE;
! 1539:
! 1540: while ((ch = getopt(argc, argv, "c:p:l:m:t:qDHV")) != -1) {
! 1541: switch (ch) {
! 1542: case 'c':
! 1543: config_file = optarg;
! 1544: break;
! 1545: case 'p':
! 1546: pidfile = optarg;
! 1547: break;
! 1548: case 'l':
! 1549: logfacility = optarg;
! 1550: break;
! 1551: case 'm':
! 1552: swmode = strtol(optarg, NULL, 10);
! 1553: if (swmode == ISTGT_SWMODE_TRADITIONAL
! 1554: || swmode == ISTGT_SWMODE_NORMAL
! 1555: || swmode == ISTGT_SWMODE_EXPERIMENTAL) {
! 1556: istgt->swmode = swmode;
! 1557: } else {
! 1558: fprintf(stderr, "unknown mode %x\n", swmode);
! 1559: usage();
! 1560: exit(EXIT_FAILURE);
! 1561: }
! 1562: break;
! 1563: case 't':
! 1564: if (strcasecmp(optarg, "NET") == 0) {
! 1565: istgt_set_trace_flag(ISTGT_TRACE_NET);
! 1566: } else if (strcasecmp(optarg, "ISCSI") == 0) {
! 1567: istgt_set_trace_flag(ISTGT_TRACE_ISCSI);
! 1568: } else if (strcasecmp(optarg, "SCSI") == 0) {
! 1569: istgt_set_trace_flag(ISTGT_TRACE_SCSI);
! 1570: } else if (strcasecmp(optarg, "LU") == 0) {
! 1571: istgt_set_trace_flag(ISTGT_TRACE_LU);
! 1572: } else if (strcasecmp(optarg, "ALL") == 0) {
! 1573: istgt_set_trace_flag(ISTGT_TRACE_ALL);
! 1574: } else if (strcasecmp(optarg, "NONE") == 0) {
! 1575: istgt_set_trace_flag(ISTGT_TRACE_NONE);
! 1576: } else {
! 1577: fprintf(stderr, "unknown flag\n");
! 1578: usage();
! 1579: exit(EXIT_FAILURE);
! 1580: }
! 1581: break;
! 1582: case 'q':
! 1583: g_warn_flag = 0;
! 1584: break;
! 1585: case 'D':
! 1586: detach = 0;
! 1587: break;
! 1588: case 'V':
! 1589: printf("istgt version %s\n", ISTGT_VERSION);
! 1590: printf("istgt extra version %s\n", ISTGT_EXTRA_VERSION);
! 1591: exit(EXIT_SUCCESS);
! 1592: case 'H':
! 1593: default:
! 1594: usage();
! 1595: exit(EXIT_SUCCESS);
! 1596: }
! 1597: }
! 1598:
! 1599: /* read config files */
! 1600: config = istgt_allocate_config();
! 1601: rc = istgt_read_config(config, config_file);
! 1602: if (rc < 0) {
! 1603: fprintf(stderr, "config error\n");
! 1604: exit(EXIT_FAILURE);
! 1605: }
! 1606: if (config->section == NULL) {
! 1607: fprintf(stderr, "empty config\n");
! 1608: istgt_free_config(config);
! 1609: exit(EXIT_FAILURE);
! 1610: }
! 1611: istgt->config = config;
! 1612: //istgt_print_config(config);
! 1613:
! 1614: /* open log files */
! 1615: if (logfacility == NULL) {
! 1616: logfacility = istgt_get_log_facility(config);
! 1617: }
! 1618: rc = istgt_set_log_facility(logfacility);
! 1619: if (rc < 0) {
! 1620: fprintf(stderr, "log facility error\n");
! 1621: istgt_free_config(config);
! 1622: exit(EXIT_FAILURE);
! 1623: }
! 1624: if (logpriority == NULL) {
! 1625: logpriority = DEFAULT_LOG_PRIORITY;
! 1626: }
! 1627: rc = istgt_set_log_priority(logpriority);
! 1628: if (rc < 0) {
! 1629: fprintf(stderr, "log priority error\n");
! 1630: istgt_free_config(config);
! 1631: exit(EXIT_FAILURE);
! 1632: }
! 1633: istgt_open_log();
! 1634:
! 1635: ISTGT_NOTICELOG("istgt version %s (%s)\n", ISTGT_VERSION,
! 1636: ISTGT_EXTRA_VERSION);
! 1637: switch (istgt->swmode) {
! 1638: case ISTGT_SWMODE_TRADITIONAL:
! 1639: ISTGT_NOTICELOG("traditional mode\n");
! 1640: break;
! 1641: case ISTGT_SWMODE_NORMAL:
! 1642: ISTGT_NOTICELOG("normal mode\n");
! 1643: break;
! 1644: case ISTGT_SWMODE_EXPERIMENTAL:
! 1645: ISTGT_NOTICELOG("experimental mode\n");
! 1646: break;
! 1647: default:
! 1648: break;
! 1649: }
! 1650:
! 1651: #ifdef ISTGT_USE_CRC32C_TABLE
! 1652: /* build crc32c table */
! 1653: istgt_init_crc32c_table();
! 1654: #endif /* ISTGT_USE_CRC32C_TABLE */
! 1655:
! 1656: /* initialize sub modules */
! 1657: rc = istgt_init(istgt);
! 1658: if (rc < 0) {
! 1659: ISTGT_ERRLOG("istgt_init() failed\n");
! 1660: initialize_error:
! 1661: istgt_close_log();
! 1662: istgt_free_config(config);
! 1663: exit(EXIT_FAILURE);
! 1664: }
! 1665: rc = istgt_lu_init(istgt);
! 1666: if (rc < 0) {
! 1667: ISTGT_ERRLOG("istgt_lu_init() failed\n");
! 1668: goto initialize_error;
! 1669: }
! 1670: rc = istgt_iscsi_init(istgt);
! 1671: if (rc < 0) {
! 1672: ISTGT_ERRLOG("istgt_iscsi_init() failed\n");
! 1673: goto initialize_error;
! 1674: }
! 1675:
! 1676: /* override by command line */
! 1677: if (pidfile != NULL) {
! 1678: xfree(istgt->pidfile);
! 1679: istgt->pidfile = xstrdup(pidfile);
! 1680: }
! 1681:
! 1682: /* detach from tty and run background */
! 1683: fflush(stdout);
! 1684: if (detach) {
! 1685: rc = daemon(0, 0);
! 1686: if (rc < 0) {
! 1687: ISTGT_ERRLOG("daemon() failed\n");
! 1688: goto initialize_error;
! 1689: }
! 1690: }
! 1691:
! 1692: /* setup signal handler thread */
! 1693: memset(&sigact, 0, sizeof sigact);
! 1694: memset(&sigoldact_pipe, 0, sizeof sigoldact_pipe);
! 1695: memset(&sigoldact_info, 0, sizeof sigoldact_info);
! 1696: memset(&sigoldact_wakeup, 0, sizeof sigoldact_wakeup);
! 1697: memset(&sigoldact_io, 0, sizeof sigoldact_io);
! 1698: sigact.sa_handler = SIG_IGN;
! 1699: sigemptyset(&sigact.sa_mask);
! 1700: rc = sigaction(SIGPIPE, &sigact, &sigoldact_pipe);
! 1701: if (rc < 0) {
! 1702: ISTGT_ERRLOG("sigaction(SIGPIPE) failed\n");
! 1703: goto initialize_error;
! 1704: }
! 1705: #ifdef SIGINFO
! 1706: sigact.sa_handler = istgt_siginfo;
! 1707: sigemptyset(&sigact.sa_mask);
! 1708: rc = sigaction(SIGINFO, &sigact, &sigoldact_info);
! 1709: if (rc < 0) {
! 1710: ISTGT_ERRLOG("sigaction(SIGINFO) failed\n");
! 1711: goto initialize_error;
! 1712: }
! 1713: #endif
! 1714: #ifdef ISTGT_USE_SIGRT
! 1715: if (ISTGT_SIGWAKEUP < SIGRTMIN
! 1716: || ISTGT_SIGWAKEUP > SIGRTMAX) {
! 1717: ISTGT_ERRLOG("SIGRT error\n");
! 1718: goto initialize_error;
! 1719: }
! 1720: #endif /* ISTGT_USE_SIGRT */
! 1721: sigact.sa_handler = istgt_sigwakeup;
! 1722: sigemptyset(&sigact.sa_mask);
! 1723: rc = sigaction(ISTGT_SIGWAKEUP, &sigact, &sigoldact_wakeup);
! 1724: if (rc < 0) {
! 1725: ISTGT_ERRLOG("sigaction(ISTGT_SIGWAKEUP) failed\n");
! 1726: goto initialize_error;
! 1727: }
! 1728: #ifdef SIGIO
! 1729: sigact.sa_handler = istgt_sigio;
! 1730: sigemptyset(&sigact.sa_mask);
! 1731: rc = sigaction(SIGIO, &sigact, &sigoldact_io);
! 1732: if (rc < 0) {
! 1733: ISTGT_ERRLOG("sigaction(SIGIO) failed\n");
! 1734: goto initialize_error;
! 1735: }
! 1736: #endif
! 1737: pthread_sigmask(SIG_SETMASK, NULL, &signew);
! 1738: sigaddset(&signew, SIGINT);
! 1739: sigaddset(&signew, SIGTERM);
! 1740: sigaddset(&signew, SIGQUIT);
! 1741: sigaddset(&signew, SIGHUP);
! 1742: #ifdef SIGINFO
! 1743: sigaddset(&signew, SIGINFO);
! 1744: #endif
! 1745: sigaddset(&signew, SIGUSR1);
! 1746: sigaddset(&signew, SIGUSR2);
! 1747: #ifdef SIGIO
! 1748: sigaddset(&signew, SIGIO);
! 1749: #endif
! 1750: sigaddset(&signew, ISTGT_SIGWAKEUP);
! 1751: pthread_sigmask(SIG_SETMASK, &signew, &sigold);
! 1752: #ifdef ISTGT_STACKSIZE
! 1753: rc = pthread_create(&sigthread, &istgt->attr, &istgt_sighandler,
! 1754: #else
! 1755: rc = pthread_create(&sigthread, NULL, &istgt_sighandler,
! 1756: #endif
! 1757: (void *) istgt);
! 1758: if (rc != 0) {
! 1759: ISTGT_ERRLOG("pthread_create() failed\n");
! 1760: goto initialize_error;
! 1761: }
! 1762: #if 0
! 1763: rc = pthread_detach(sigthread);
! 1764: if (rc != 0) {
! 1765: ISTGT_ERRLOG("pthread_detach() failed\n");
! 1766: goto initialize_error;
! 1767: }
! 1768: #endif
! 1769: #ifdef HAVE_PTHREAD_SET_NAME_NP
! 1770: pthread_set_name_np(sigthread, "sigthread");
! 1771: pthread_set_name_np(pthread_self(), "mainthread");
! 1772: #endif
! 1773:
! 1774: /* create LUN threads for command queuing */
! 1775: rc = istgt_lu_create_threads(istgt);
! 1776: if (rc < 0) {
! 1777: ISTGT_ERRLOG("lu_create_threads() failed\n");
! 1778: goto initialize_error;
! 1779: }
! 1780: rc = istgt_lu_set_all_state(istgt, ISTGT_STATE_RUNNING);
! 1781: if (rc < 0) {
! 1782: ISTGT_ERRLOG("lu_set_all_state() failed\n");
! 1783: goto initialize_error;
! 1784: }
! 1785:
! 1786: /* open portals */
! 1787: rc = istgt_open_uctl_portal(istgt);
! 1788: if (rc < 0) {
! 1789: ISTGT_ERRLOG("istgt_open_uctl_portal() failed\n");
! 1790: goto initialize_error;
! 1791: }
! 1792: rc = istgt_open_portal(istgt);
! 1793: if (rc < 0) {
! 1794: ISTGT_ERRLOG("istgt_open_portal() failed\n");
! 1795: goto initialize_error;
! 1796: }
! 1797:
! 1798: /* write pid */
! 1799: rc = istgt_write_pidfile(istgt);
! 1800: if (rc < 0) {
! 1801: ISTGT_ERRLOG("istgt_write_pid() failed\n");
! 1802: goto initialize_error;
! 1803: }
! 1804:
! 1805: /* accept loop */
! 1806: rc = istgt_acceptor(istgt);
! 1807: if (rc < 0) {
! 1808: ISTGT_ERRLOG("istgt_acceptor() failed\n");
! 1809: istgt_close_portal(istgt);
! 1810: istgt_close_uctl_portal(istgt);
! 1811: istgt_iscsi_shutdown(istgt);
! 1812: istgt_lu_shutdown(istgt);
! 1813: istgt_destory_initiator_group_array(istgt);
! 1814: istgt_destroy_portal_array(istgt);
! 1815: istgt_destroy_uctl_portal(istgt);
! 1816: istgt_remove_pidfile(istgt);
! 1817: istgt_close_log();
! 1818: istgt->config = NULL;
! 1819: istgt_free_config(config);
! 1820: exit(EXIT_FAILURE);
! 1821: }
! 1822:
! 1823: /* wait threads */
! 1824: while (retry > 0) {
! 1825: if (istgt_get_active_conns() == 0) {
! 1826: break;
! 1827: }
! 1828: sleep(1);
! 1829: retry--;
! 1830: }
! 1831: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "retry=%d\n", retry);
! 1832:
! 1833: ISTGT_NOTICELOG("istgt version %s (%s) exiting\n", ISTGT_VERSION,
! 1834: ISTGT_EXTRA_VERSION);
! 1835:
! 1836: /* cleanup */
! 1837: istgt_close_portal(istgt);
! 1838: istgt_close_uctl_portal(istgt);
! 1839: istgt_iscsi_shutdown(istgt);
! 1840: istgt_lu_shutdown(istgt);
! 1841: istgt_destory_initiator_group_array(istgt);
! 1842: istgt_destroy_portal_array(istgt);
! 1843: istgt_destroy_uctl_portal(istgt);
! 1844: istgt_remove_pidfile(istgt);
! 1845: istgt_close_log();
! 1846: istgt->config = NULL;
! 1847: istgt_free_config(config);
! 1848: istgt_set_state(istgt, ISTGT_STATE_SHUTDOWN);
! 1849:
! 1850: /* stop signal thread */
! 1851: rc = pthread_join(sigthread, NULL);
! 1852: if (rc != 0) {
! 1853: ISTGT_ERRLOG("pthread_join() failed\n");
! 1854: exit (EXIT_FAILURE);
! 1855: }
! 1856:
! 1857: return 0;
! 1858: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>