Annotation of embedaddon/istgt/src/istgt_lu.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 <ctype.h>
! 36: #include <errno.h>
! 37: #include <signal.h>
! 38: #include <stdio.h>
! 39: #include <stdlib.h>
! 40: #include <string.h>
! 41: #include <limits.h>
! 42: #include <pthread.h>
! 43: #ifdef HAVE_PTHREAD_NP_H
! 44: #include <pthread_np.h>
! 45: #endif
! 46: #include <time.h>
! 47: #include <sys/types.h>
! 48: #include <sys/stat.h>
! 49: #include <netinet/in.h>
! 50: #include <arpa/inet.h>
! 51:
! 52: #include <fcntl.h>
! 53: #include <unistd.h>
! 54: #include <sys/ioctl.h>
! 55: #ifdef HAVE_SYS_DISK_H
! 56: #include <sys/disk.h>
! 57: #endif
! 58: #ifdef HAVE_SYS_DISKLABEL_H
! 59: #include <sys/disklabel.h>
! 60: #endif
! 61: #ifdef __linux__
! 62: #include <linux/fs.h>
! 63: #endif
! 64:
! 65: #include "istgt.h"
! 66: #include "istgt_ver.h"
! 67: #include "istgt_log.h"
! 68: #include "istgt_conf.h"
! 69: #include "istgt_sock.h"
! 70: #include "istgt_misc.h"
! 71: #include "istgt_md5.h"
! 72: #include "istgt_iscsi.h"
! 73: #include "istgt_lu.h"
! 74: #include "istgt_proto.h"
! 75: #include "istgt_scsi.h"
! 76:
! 77: #define MAX_MASKBUF 128
! 78: static int
! 79: istgt_lu_allow_ipv6(const char *netmask, const char *addr)
! 80: {
! 81: struct in6_addr in6_mask;
! 82: struct in6_addr in6_addr;
! 83: char mask[MAX_MASKBUF];
! 84: const char *p;
! 85: int bits, bmask;
! 86: int n;
! 87: int i;
! 88:
! 89: if (netmask[0] != '[')
! 90: return 0;
! 91: p = strchr(netmask, ']');
! 92: if (p == NULL)
! 93: return 0;
! 94: n = p - (netmask + 1);
! 95: if (n + 1 > sizeof mask)
! 96: return 0;
! 97:
! 98: memcpy(mask, netmask + 1, n);
! 99: mask[n] = '\0';
! 100: p++;
! 101:
! 102: if (p[0] == '/') {
! 103: bits = (int) strtol(p + 1, NULL, 10);
! 104: if (bits < 0 || bits > 128)
! 105: return 0;
! 106: } else {
! 107: bits = 128;
! 108: }
! 109:
! 110: #if 0
! 111: printf("input %s\n", addr);
! 112: printf("mask %s / %d\n", mask, bits);
! 113: #endif
! 114:
! 115: /* presentation to network order binary */
! 116: if (inet_pton(AF_INET6, mask, &in6_mask) <= 0
! 117: || inet_pton(AF_INET6, addr, &in6_addr) <= 0) {
! 118: return 0;
! 119: }
! 120:
! 121: /* check 128bits */
! 122: for (i = 0; i < (bits / 8); i++) {
! 123: if (in6_mask.s6_addr[i] != in6_addr.s6_addr[i])
! 124: return 0;
! 125: }
! 126: if (bits % 8) {
! 127: bmask = (0xffU << (8 - (bits % 8))) & 0xffU;
! 128: if ((in6_mask.s6_addr[i] & bmask) != (in6_addr.s6_addr[i] & bmask))
! 129: return 0;
! 130: }
! 131:
! 132: /* match */
! 133: return 1;
! 134: }
! 135:
! 136: static int
! 137: istgt_lu_allow_ipv4(const char *netmask, const char *addr)
! 138: {
! 139: struct in_addr in4_mask;
! 140: struct in_addr in4_addr;
! 141: char mask[MAX_MASKBUF];
! 142: const char *p;
! 143: uint32_t bmask;
! 144: int bits;
! 145: int n;
! 146:
! 147: p = strchr(netmask, '/');
! 148: if (p == NULL) {
! 149: p = netmask + strlen(netmask);
! 150: }
! 151: n = p - netmask;
! 152: if (n + 1 > sizeof mask)
! 153: return 0;
! 154:
! 155: memcpy(mask, netmask, n);
! 156: mask[n] = '\0';
! 157:
! 158: if (p[0] == '/') {
! 159: bits = (int) strtol(p + 1, NULL, 10);
! 160: if (bits < 0 || bits > 32)
! 161: return 0;
! 162: } else {
! 163: bits = 32;
! 164: }
! 165:
! 166: #if 0
! 167: printf("input %s\n", addr);
! 168: printf("mask %s / %d\n", mask, bits);
! 169: #endif
! 170:
! 171: /* presentation to network order binary */
! 172: if (inet_pton(AF_INET, mask, &in4_mask) <= 0
! 173: || inet_pton(AF_INET, addr, &in4_addr) <= 0) {
! 174: return 0;
! 175: }
! 176:
! 177: /* check 32bits */
! 178: bmask = (0xffffffffU << (32 - bits)) & 0xffffffffU;
! 179: if ((ntohl(in4_mask.s_addr) & bmask) != (ntohl(in4_addr.s_addr) & bmask))
! 180: return 0;
! 181:
! 182: /* match */
! 183: return 1;
! 184: }
! 185:
! 186: int
! 187: istgt_lu_allow_netmask(const char *netmask, const char *addr)
! 188: {
! 189: if (netmask == NULL || addr == NULL)
! 190: return 0;
! 191: if (strcasecmp(netmask, "ALL") == 0)
! 192: return 1;
! 193: if (netmask[0] == '[') {
! 194: /* IPv6 */
! 195: if (istgt_lu_allow_ipv6(netmask, addr))
! 196: return 1;
! 197: } else {
! 198: /* IPv4 */
! 199: if (istgt_lu_allow_ipv4(netmask, addr))
! 200: return 1;
! 201: }
! 202: return 0;
! 203: }
! 204:
! 205: int
! 206: istgt_lu_access(CONN_Ptr conn, ISTGT_LU_Ptr lu, const char *iqn, const char *addr)
! 207: {
! 208: ISTGT_Ptr istgt;
! 209: INITIATOR_GROUP *igp;
! 210: int pg_tag;
! 211: int ig_tag;
! 212: int rc;
! 213: int i, j, k;
! 214:
! 215: if (conn == NULL || lu == NULL || iqn == NULL || addr == NULL)
! 216: return 0;
! 217: istgt = conn->istgt;
! 218: pg_tag = conn->portal.tag;
! 219:
! 220: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "pg=%d, iqn=%s, addr=%s\n",
! 221: pg_tag, iqn, addr);
! 222: for (i = 0; i < lu->maxmap; i++) {
! 223: /* skip excluding self portal group tag */
! 224: if (pg_tag != lu->map[i].pg_tag)
! 225: continue;
! 226: /* iqn is initiator group? */
! 227: ig_tag = lu->map[i].ig_tag;
! 228: igp = istgt_lu_find_initiatorgroup(istgt, ig_tag);
! 229: if (igp == NULL) {
! 230: ISTGT_ERRLOG("LU%d: ig_tag not found\n", lu->num);
! 231: continue;
! 232: }
! 233: for (j = 0; j < igp->ninitiators; j++) {
! 234: /* deny initiators */
! 235: if (igp->initiators[j][0] == '!'
! 236: && (strcasecmp(&igp->initiators[j][1], "ALL") == 0
! 237: || strcasecmp(&igp->initiators[j][1], iqn) == 0)) {
! 238: /* NG */
! 239: ISTGT_WARNLOG("access denied from %s (%s) to %s (%s:%s,%d)\n",
! 240: iqn, addr, conn->target_name, conn->portal.host,
! 241: conn->portal.port, conn->portal.tag);
! 242: return 0;
! 243: }
! 244: /* allow initiators */
! 245: if (strcasecmp(igp->initiators[j], "ALL") == 0
! 246: || strcasecmp(igp->initiators[j], iqn) == 0) {
! 247: /* OK iqn, check netmask */
! 248: if (igp->nnetmasks == 0) {
! 249: /* OK, empty netmask as ALL */
! 250: return 1;
! 251: }
! 252: for (k = 0; k < igp->nnetmasks; k++) {
! 253: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 254: "netmask=%s, addr=%s\n",
! 255: igp->netmasks[k], addr);
! 256: rc = istgt_lu_allow_netmask(igp->netmasks[k], addr);
! 257: if (rc > 0) {
! 258: /* OK netmask */
! 259: return 1;
! 260: }
! 261: }
! 262: /* NG netmask in this group */
! 263: }
! 264: }
! 265: }
! 266:
! 267: /* NG */
! 268: ISTGT_WARNLOG("access denied from %s (%s) to %s (%s:%s,%d)\n",
! 269: iqn, addr, conn->target_name, conn->portal.host,
! 270: conn->portal.port, conn->portal.tag);
! 271: return 0;
! 272: }
! 273:
! 274: int
! 275: istgt_lu_visible(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu, const char *iqn, int pg_tag)
! 276: {
! 277: INITIATOR_GROUP *igp;
! 278: int match_pg_tag;
! 279: int ig_tag;
! 280: int i, j;
! 281:
! 282: if (istgt == NULL || lu == NULL || iqn == NULL)
! 283: return 0;
! 284: /* pg_tag exist map? */
! 285: match_pg_tag = 0;
! 286: for (i = 0; i < lu->maxmap; i++) {
! 287: if (lu->map[i].pg_tag == pg_tag) {
! 288: match_pg_tag = 1;
! 289: break;
! 290: }
! 291: }
! 292: if (match_pg_tag == 0) {
! 293: /* cat't access from pg_tag */
! 294: return 0;
! 295: }
! 296: for (i = 0; i < lu->maxmap; i++) {
! 297: /* iqn is initiator group? */
! 298: ig_tag = lu->map[i].ig_tag;
! 299: igp = istgt_lu_find_initiatorgroup(istgt, ig_tag);
! 300: if (igp == NULL) {
! 301: ISTGT_ERRLOG("LU%d: ig_tag not found\n", lu->num);
! 302: continue;
! 303: }
! 304: for (j = 0; j < igp->ninitiators; j++) {
! 305: if (igp->initiators[j][0] == '!'
! 306: && (strcasecmp(&igp->initiators[j][1], "ALL") == 0
! 307: || strcasecmp(&igp->initiators[j][1], iqn) == 0)) {
! 308: /* NG */
! 309: return 0;
! 310: }
! 311: if (strcasecmp(igp->initiators[j], "ALL") == 0
! 312: || strcasecmp(igp->initiators[j], iqn) == 0) {
! 313: /* OK iqn, no check addr */
! 314: return 1;
! 315: }
! 316: }
! 317: }
! 318:
! 319: /* NG */
! 320: return 0;
! 321: }
! 322:
! 323: int
! 324: istgt_lu_sendtargets(CONN_Ptr conn, const char *iiqn, const char *iaddr, const char *tiqn, uint8_t *data, int alloc_len, int data_len)
! 325: {
! 326: char buf[MAX_TMPBUF];
! 327: ISTGT_Ptr istgt;
! 328: ISTGT_LU_Ptr lu;
! 329: char *host;
! 330: int total;
! 331: int len;
! 332: int rc;
! 333: int pg_tag;
! 334: int i, j, k;
! 335:
! 336: if (conn == NULL)
! 337: return 0;
! 338: istgt = conn->istgt;
! 339:
! 340: total = data_len;
! 341: if (alloc_len < 1) {
! 342: return 0;
! 343: }
! 344: if (total > alloc_len) {
! 345: total = alloc_len;
! 346: data[total - 1] = '\0';
! 347: return total;
! 348: }
! 349:
! 350: if (alloc_len - total < 1) {
! 351: ISTGT_ERRLOG("data space small %d\n", alloc_len);
! 352: return total;
! 353: }
! 354:
! 355: MTX_LOCK(&istgt->mutex);
! 356: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 357: lu = istgt->logical_unit[i];
! 358: if (lu == NULL)
! 359: continue;
! 360: if (strcasecmp(tiqn, "ALL") != 0
! 361: && strcasecmp(tiqn, lu->name) != 0) {
! 362: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 363: "SKIP iqn=%s for %s from %s (%s)\n",
! 364: tiqn, lu->name, iiqn, iaddr);
! 365: continue;
! 366: }
! 367: rc = istgt_lu_visible(istgt, lu, iiqn, conn->portal.tag);
! 368: if (rc == 0) {
! 369: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 370: "SKIP iqn=%s for %s from %s (%s)\n",
! 371: tiqn, lu->name, iiqn, iaddr);
! 372: continue;
! 373: }
! 374:
! 375: /* DO SENDTARGETS */
! 376: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 377: "OK iqn=%s for %s from %s (%s)\n",
! 378: tiqn, lu->name, iiqn, iaddr);
! 379:
! 380: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 381: "TargetName=%s\n", lu->name);
! 382: len = snprintf((char *) data + total, alloc_len - total,
! 383: "TargetName=%s", lu->name);
! 384: total += len + 1;
! 385:
! 386: for (j = 0; j < lu->maxmap; j++) {
! 387: pg_tag = lu->map[j].pg_tag;
! 388: /* skip same pg_tag */
! 389: for (k = 0; k < j; k++) {
! 390: if (lu->map[k].pg_tag == pg_tag) {
! 391: goto skip_pg_tag;
! 392: }
! 393: }
! 394: /* write to data */
! 395: for (k = 0; k < istgt->nportal; k++) {
! 396: if (istgt->portal[k].tag == pg_tag) {
! 397: if (alloc_len - total < 1) {
! 398: MTX_UNLOCK(&istgt->mutex);
! 399: ISTGT_ERRLOG("data space small %d\n", alloc_len);
! 400: return total;
! 401: }
! 402: host = istgt->portal[k].host;
! 403: /* wildcard? */
! 404: if (strcasecmp(host, "[::]") == 0
! 405: || strcasecmp(host, "[*]") == 0
! 406: || strcasecmp(host, "0.0.0.0") == 0
! 407: || strcasecmp(host, "*") == 0) {
! 408: if ((strcasecmp(host, "[::]") == 0
! 409: || strcasecmp(host, "[*]") == 0)
! 410: && conn->initiator_family == AF_INET6) {
! 411: snprintf(buf, sizeof buf, "[%s]",
! 412: conn->target_addr);
! 413: host = buf;
! 414: } else if ((strcasecmp(host, "0.0.0.0") == 0
! 415: || strcasecmp(host, "*") == 0)
! 416: && conn->initiator_family == AF_INET) {
! 417: snprintf(buf, sizeof buf, "%s",
! 418: conn->target_addr);
! 419: host = buf;
! 420: } else {
! 421: /* skip portal for the family */
! 422: continue;
! 423: }
! 424: }
! 425: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 426: "TargetAddress=%s:%s,%d\n",
! 427: host,
! 428: istgt->portal[k].port,
! 429: istgt->portal[k].tag);
! 430: len = snprintf((char *) data + total,
! 431: alloc_len - total,
! 432: "TargetAddress=%s:%s,%d",
! 433: host,
! 434: istgt->portal[k].port,
! 435: istgt->portal[k].tag);
! 436: total += len + 1;
! 437: }
! 438: }
! 439: skip_pg_tag:
! 440: ;
! 441: }
! 442: }
! 443: MTX_UNLOCK(&istgt->mutex);
! 444:
! 445: return total;
! 446: }
! 447:
! 448: ISTGT_LU_Ptr
! 449: istgt_lu_find_target(ISTGT_Ptr istgt, const char *target_name)
! 450: {
! 451: ISTGT_LU_Ptr lu;
! 452: int i;
! 453:
! 454: if (istgt == NULL || target_name == NULL)
! 455: return NULL;
! 456: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 457: lu = istgt->logical_unit[i];
! 458: if (lu == NULL)
! 459: continue;
! 460: if (strcasecmp(target_name, lu->name) == 0) {
! 461: return lu;
! 462: }
! 463: }
! 464: ISTGT_WARNLOG("can't find target %s\n",
! 465: target_name);
! 466: return NULL;
! 467: }
! 468:
! 469: uint16_t
! 470: istgt_lu_allocate_tsih(ISTGT_LU_Ptr lu, const char *initiator_port, int tag)
! 471: {
! 472: uint16_t tsih;
! 473: int retry = 10;
! 474: int i;
! 475:
! 476: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_allocate_tsih\n");
! 477: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "initiator_port=%s, tag=%d\n",
! 478: initiator_port, tag);
! 479: if (lu == NULL || initiator_port == NULL || tag == 0)
! 480: return 0;
! 481: /* tsih 0 is reserved */
! 482: tsih = 0;
! 483: MTX_LOCK(&lu->mutex);
! 484: #if 0
! 485: for (i = 1; i < MAX_LU_TSIH; i++) {
! 486: if (lu->tsih[i].initiator_port == NULL)
! 487: continue;
! 488: if (tag != lu->tsih[i].tag)
! 489: continue;
! 490: if (strcasecmp(initiator_port, lu->tsih[i].initiator_port) == 0) {
! 491: tsih = lu->tsih[i].tsih;
! 492: break;
! 493: }
! 494: }
! 495: #endif
! 496: if (tsih == 0) {
! 497: if (lu->maxtsih >= MAX_LU_TSIH) {
! 498: ISTGT_ERRLOG("LU%d: tsih is maximum\n", lu->num);
! 499: MTX_UNLOCK(&lu->mutex);
! 500: return 0;
! 501: }
! 502: retry:
! 503: lu->last_tsih++;
! 504: tsih = lu->last_tsih;
! 505: if (tsih == 0) {
! 506: if (retry > 0) {
! 507: retry--;
! 508: goto retry;
! 509: }
! 510: ISTGT_ERRLOG("LU%d: retry error\n", lu->num);
! 511: MTX_UNLOCK(&lu->mutex);
! 512: return 0;
! 513: }
! 514: for (i = 1; i < MAX_LU_TSIH; i++) {
! 515: if (lu->tsih[i].initiator_port != NULL
! 516: && lu->tsih[i].tsih == tsih) {
! 517: ISTGT_ERRLOG("tsih is found in list\n");
! 518: if (retry > 0) {
! 519: retry--;
! 520: goto retry;
! 521: }
! 522: ISTGT_ERRLOG("LU%d: retry error\n", lu->num);
! 523: MTX_UNLOCK(&lu->mutex);
! 524: return 0;
! 525: }
! 526: }
! 527: for (i = 1; i < MAX_LU_TSIH; i++) {
! 528: if (lu->tsih[i].initiator_port == NULL) {
! 529: lu->tsih[i].tag = tag;
! 530: lu->tsih[i].tsih = tsih;
! 531: lu->tsih[i].initiator_port = xstrdup(initiator_port);
! 532: lu->maxtsih++;
! 533: break;
! 534: }
! 535: }
! 536: }
! 537: MTX_UNLOCK(&lu->mutex);
! 538: return tsih;
! 539: }
! 540:
! 541: void
! 542: istgt_lu_free_tsih(ISTGT_LU_Ptr lu, uint16_t tsih, char *initiator_port)
! 543: {
! 544: int i;
! 545:
! 546: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_free_tsih\n");
! 547: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "tsih=%u, initiator_port=%s\n",
! 548: tsih, initiator_port);
! 549: if (lu == NULL || initiator_port == NULL)
! 550: return;
! 551: if (tsih == 0)
! 552: return;
! 553:
! 554: MTX_LOCK(&lu->mutex);
! 555: for (i = 1; i < MAX_LU_TSIH; i++) {
! 556: if (lu->tsih[i].initiator_port == NULL)
! 557: continue;
! 558: if (lu->tsih[i].tsih != tsih)
! 559: continue;
! 560:
! 561: if (strcasecmp(initiator_port, lu->tsih[i].initiator_port) == 0) {
! 562: lu->tsih[i].tag = 0;
! 563: lu->tsih[i].tsih = 0;
! 564: xfree(lu->tsih[i].initiator_port);
! 565: lu->tsih[i].initiator_port = NULL;
! 566: lu->maxtsih--;
! 567: break;
! 568: }
! 569: }
! 570: MTX_UNLOCK(&lu->mutex);
! 571: return;
! 572: }
! 573:
! 574: char *
! 575: istgt_lu_get_media_flags_string(int flags, char *buf, size_t len)
! 576: {
! 577: char *p;
! 578: size_t rest;
! 579:
! 580: p = buf;
! 581: rest = len;
! 582: if (flags & ISTGT_LU_FLAG_MEDIA_READONLY) {
! 583: snprintf(p, rest, "%s", "ro");
! 584: } else {
! 585: snprintf(p, rest, "%s", "rw");
! 586: }
! 587: p = buf + strlen(buf);
! 588: rest = len - strlen(buf);
! 589: if (flags & ISTGT_LU_FLAG_MEDIA_EXTEND) {
! 590: snprintf(p, rest, ",%s", "extend");
! 591: }
! 592: p = buf + strlen(buf);
! 593: rest = len - strlen(buf);
! 594: if (flags & ISTGT_LU_FLAG_MEDIA_DYNAMIC) {
! 595: snprintf(p, rest, ",%s", "dynamic");
! 596: }
! 597: return buf;
! 598: }
! 599:
! 600: uint64_t
! 601: istgt_lu_get_devsize(const char *file)
! 602: {
! 603: uint64_t val;
! 604: struct stat st;
! 605: int fd;
! 606: int rc;
! 607:
! 608: val = 0ULL;
! 609: rc = lstat(file, &st);
! 610: if (rc != 0)
! 611: return val;
! 612: if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode))
! 613: return val;
! 614:
! 615: fd = open(file, O_RDONLY, 0);
! 616: if (fd >= 0) {
! 617: #ifdef DIOCGMEDIASIZE
! 618: if (val == 0) {
! 619: off_t offset;
! 620: rc = ioctl(fd, DIOCGMEDIASIZE, &offset);
! 621: if (rc != -1) {
! 622: val = (uint64_t) offset;
! 623: }
! 624: }
! 625: #endif /* DIOCGMEDIASIZE */
! 626: #ifdef DIOCGDINFO
! 627: if (val == 0) {
! 628: struct disklabel dl;
! 629: rc = ioctl(fd, DIOCGDINFO, &dl);
! 630: if (rc != -1) {
! 631: val = (uint64_t) dl.d_secperunit;
! 632: val *= (uint64_t) dl.d_secsize;
! 633: }
! 634: }
! 635: #endif /* DIOCGDINFO */
! 636: #if defined(DKIOCGETBLOCKSIZE) && defined(DKIOCGETBLOCKCOUNT)
! 637: if (val == 0) {
! 638: uint32_t blocklen;
! 639: uint64_t blockcnt;
! 640: rc = ioctl(fd, DKIOCGETBLOCKSIZE, &blocklen);
! 641: if (rc != -1) {
! 642: rc = ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcnt);
! 643: if (rc != -1) {
! 644: val = (uint64_t) blocklen;
! 645: val *= (uint64_t) blockcnt;
! 646: }
! 647: }
! 648: }
! 649: #endif /* DKIOCGETBLOCKSIZE && DKIOCGETBLOCKCOUNT */
! 650: #ifdef __linux__
! 651: #ifdef BLKGETSIZE64
! 652: if (val == 0) {
! 653: uint64_t blocksize;
! 654: rc = ioctl(fd, BLKGETSIZE64, &blocksize);
! 655: if (rc != -1) {
! 656: val = (uint64_t) blocksize;
! 657: }
! 658: }
! 659: #endif /* BLKGETSIZE64 */
! 660: #ifdef BLKGETSIZE
! 661: if (val == 0) {
! 662: uint32_t blocksize;
! 663: rc = ioctl(fd, BLKGETSIZE, &blocksize);
! 664: if (rc != -1) {
! 665: val = (uint64_t) 512;
! 666: val *= (uint64_t) blocksize;
! 667: }
! 668: }
! 669: #endif /* BLKGETSIZE */
! 670: #endif /* __linux__ */
! 671: if (val == 0) {
! 672: ISTGT_ERRLOG("unknown device size\n");
! 673: }
! 674: (void) close(fd);
! 675: } else {
! 676: if (g_trace_flag) {
! 677: ISTGT_WARNLOG("open error %s (errno=%d)\n", file, errno);
! 678: }
! 679: val = 0ULL;
! 680: }
! 681: return val;
! 682: }
! 683:
! 684: uint64_t
! 685: istgt_lu_get_filesize(const char *file)
! 686: {
! 687: uint64_t val;
! 688: struct stat st;
! 689: int rc;
! 690:
! 691: val = 0ULL;
! 692: rc = lstat(file, &st);
! 693: if (rc < 0)
! 694: return val;
! 695: if (S_ISLNK(st.st_mode))
! 696: return val;
! 697:
! 698: if (S_ISCHR(st.st_mode)) {
! 699: val = istgt_lu_get_devsize(file);
! 700: } else if (S_ISBLK(st.st_mode)) {
! 701: val = istgt_lu_get_devsize(file);
! 702: } else if (S_ISREG(st.st_mode)) {
! 703: val = st.st_size;
! 704: } else {
! 705: ISTGT_ERRLOG("lstat is neither REG, CHR nor BLK\n");
! 706: val = 0ULL;
! 707: }
! 708: return val;
! 709: }
! 710:
! 711: uint64_t
! 712: istgt_lu_parse_size(const char *size)
! 713: {
! 714: uint64_t val, val1, val2;
! 715: char *endp, *p;
! 716: size_t idx;
! 717: int sign;
! 718:
! 719: val1 = (uint64_t) strtoull(size, &endp, 10);
! 720: val = val1;
! 721: val2 = 0;
! 722: if (endp != NULL) {
! 723: p = endp;
! 724: switch (toupper((int) *p)) {
! 725: case 'Z': val1 *= (uint64_t) 1024ULL;
! 726: case 'E': val1 *= (uint64_t) 1024ULL;
! 727: case 'P': val1 *= (uint64_t) 1024ULL;
! 728: case 'T': val1 *= (uint64_t) 1024ULL;
! 729: case 'G': val1 *= (uint64_t) 1024ULL;
! 730: case 'M': val1 *= (uint64_t) 1024ULL;
! 731: case 'K': val1 *= (uint64_t) 1024ULL;
! 732: break;
! 733: }
! 734: val = val1;
! 735: p++;
! 736: idx = strspn(p, "Bb \t");
! 737: p += idx;
! 738: if (*p == '-' || *p == '+') {
! 739: sign = (int) *p++;
! 740: idx = strspn(p, " \t");
! 741: p += idx;
! 742: val2 = (uint64_t) strtoull(p, &endp, 10);
! 743: if (endp != NULL) {
! 744: p = endp;
! 745: switch (toupper((int) *p)) {
! 746: case 'Z': val2 *= (uint64_t) 1024ULL;
! 747: case 'E': val2 *= (uint64_t) 1024ULL;
! 748: case 'P': val2 *= (uint64_t) 1024ULL;
! 749: case 'T': val2 *= (uint64_t) 1024ULL;
! 750: case 'G': val2 *= (uint64_t) 1024ULL;
! 751: case 'M': val2 *= (uint64_t) 1024ULL;
! 752: case 'K': val2 *= (uint64_t) 1024ULL;
! 753: break;
! 754: }
! 755: }
! 756: if (sign == '-') {
! 757: if (val2 > val1) {
! 758: /* underflow */
! 759: val = (uint64_t) 0ULL;
! 760: } else {
! 761: val = val1 - val2;
! 762: }
! 763: } else {
! 764: if (val2 > (UINT64_MAX - val1)) {
! 765: /* overflow */
! 766: val = UINT64_MAX;
! 767: } else {
! 768: val = val1 + val2;
! 769: }
! 770: }
! 771: }
! 772: }
! 773: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 774: "size=%s, val=%"PRIu64", val1=%"PRIu64", val2=%"PRIu64"\n",
! 775: size, val, val1, val2);
! 776: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 777: "size=%s, val=%"PRIx64", val1=%"PRIx64", val2=%"PRIx64"\n",
! 778: size, val, val1, val2);
! 779:
! 780: return val;
! 781: }
! 782:
! 783: int
! 784: istgt_lu_parse_media_flags(const char *flags)
! 785: {
! 786: char buf[MAX_TMPBUF];
! 787: const char *delim = ",";
! 788: char *next_p;
! 789: char *p;
! 790: int mflags;
! 791:
! 792: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "mflags=%s\n", flags);
! 793: mflags = 0;
! 794: strlcpy(buf, flags, MAX_TMPBUF);
! 795: next_p = buf;
! 796: while ((p = strsep(&next_p, delim)) != NULL) {
! 797: if (strcasecmp(p, "ro") == 0) {
! 798: mflags |= ISTGT_LU_FLAG_MEDIA_READONLY;
! 799: } else if (strcasecmp(p, "rw") == 0) {
! 800: mflags &= ~ISTGT_LU_FLAG_MEDIA_READONLY;
! 801: } else if (strcasecmp(p, "extend") == 0) {
! 802: mflags |= ISTGT_LU_FLAG_MEDIA_EXTEND;
! 803: } else if (strcasecmp(p, "dynamic") == 0) {
! 804: mflags |= ISTGT_LU_FLAG_MEDIA_DYNAMIC;
! 805: } else {
! 806: ISTGT_ERRLOG("unknown media flag %.64s\n", p);
! 807: }
! 808: }
! 809:
! 810: return mflags;
! 811: }
! 812:
! 813: uint64_t
! 814: istgt_lu_parse_media_size(const char *file, const char *size, int *flags)
! 815: {
! 816: uint64_t msize, fsize;
! 817:
! 818: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "msize=%s\n", size);
! 819: if (strcasecmp(file, "/dev/null") == 0) {
! 820: return 0;
! 821: }
! 822: if (strcasecmp(size, "Auto") == 0
! 823: || strcasecmp(size, "Size") == 0) {
! 824: msize = istgt_lu_get_filesize(file);
! 825: if (msize == 0) {
! 826: msize = ISTGT_LU_MEDIA_SIZE_MIN;
! 827: }
! 828: *flags |= ISTGT_LU_FLAG_MEDIA_AUTOSIZE;
! 829: } else {
! 830: msize = istgt_lu_parse_size(size);
! 831: if (*flags & ISTGT_LU_FLAG_MEDIA_EXTEND) {
! 832: fsize = istgt_lu_get_filesize(file);
! 833: if (fsize > msize) {
! 834: msize = fsize;
! 835: }
! 836: }
! 837: }
! 838:
! 839: if (*flags & ISTGT_LU_FLAG_MEDIA_DYNAMIC) {
! 840: if (msize < ISTGT_LU_MEDIA_SIZE_MIN) {
! 841: msize = ISTGT_LU_MEDIA_SIZE_MIN;
! 842: }
! 843: } else {
! 844: if (msize < ISTGT_LU_MEDIA_SIZE_MIN) {
! 845: ISTGT_ERRLOG("media size too small\n");
! 846: return 0ULL;
! 847: }
! 848: }
! 849:
! 850: return msize;
! 851: }
! 852:
! 853: PORTAL *
! 854: istgt_lu_find_portalgroup(ISTGT_Ptr istgt, int tag)
! 855: {
! 856: PORTAL *pp;
! 857: int i;
! 858:
! 859: for (i = 0; i < istgt->nportal; i++) {
! 860: if (istgt->portal[i].tag == tag) {
! 861: pp = &istgt->portal[i];
! 862: return pp;
! 863: }
! 864: }
! 865: return NULL;
! 866: }
! 867:
! 868: INITIATOR_GROUP *
! 869: istgt_lu_find_initiatorgroup(ISTGT_Ptr istgt, int tag)
! 870: {
! 871: INITIATOR_GROUP *igp;
! 872: int i;
! 873:
! 874: for (i = 0; i < istgt->ninitiator_group; i++) {
! 875: if (istgt->initiator_group[i].tag == tag) {
! 876: igp = &istgt->initiator_group[i];
! 877: return igp;
! 878: }
! 879: }
! 880: return NULL;
! 881: }
! 882:
! 883: static int
! 884: istgt_lu_check_iscsi_name(const char *name)
! 885: {
! 886: const unsigned char *up = (const unsigned char *) name;
! 887: size_t n;
! 888:
! 889: /* valid iSCSI name? */
! 890: for (n = 0; up[n] != 0; n++) {
! 891: if (up[n] > 0x00U && up[n] <= 0x2cU)
! 892: return -1;
! 893: if (up[n] == 0x2fU)
! 894: return -1;
! 895: if (up[n] >= 0x3bU && up[n] <= 0x40U)
! 896: return -1;
! 897: if (up[n] >= 0x5bU && up[n] <= 0x60U)
! 898: return -1;
! 899: if (up[n] >= 0x7bU && up[n] <= 0x7fU)
! 900: return -1;
! 901: if (isspace(up[n]))
! 902: return -1;
! 903: }
! 904: /* valid format? */
! 905: if (strncasecmp(name, "iqn.", 4) == 0) {
! 906: /* iqn.YYYY-MM.reversed.domain.name */
! 907: if (!isdigit(up[4]) || !isdigit(up[5]) || !isdigit(up[6])
! 908: || !isdigit(up[7]) || up[8] != '-' || !isdigit(up[9])
! 909: || !isdigit(up[10]) || up[11] != '.') {
! 910: ISTGT_ERRLOG("invalid iqn format. "
! 911: "expect \"iqn.YYYY-MM.reversed.domain.name\"\n");
! 912: return -1;
! 913: }
! 914: } else if (strncasecmp(name, "eui.", 4) == 0) {
! 915: /* EUI-64 -> 16bytes */
! 916: /* XXX */
! 917: } else if (strncasecmp(name, "naa.", 4) == 0) {
! 918: /* 64bit -> 16bytes, 128bit -> 32bytes */
! 919: /* XXX */
! 920: }
! 921: /* OK */
! 922: return 0;
! 923: }
! 924:
! 925: static uint64_t
! 926: istgt_lu_get_nbserial(const char *nodebase)
! 927: {
! 928: ISTGT_MD5CTX md5ctx;
! 929: uint8_t nbsmd5[ISTGT_MD5DIGEST_LEN];
! 930: char buf[MAX_TMPBUF];
! 931: uint64_t nbs;
! 932: int idx;
! 933: int i;
! 934:
! 935: snprintf(buf, sizeof buf, "%s", nodebase);
! 936: if (strcasecmp(buf, "iqn.2007-09.jp.ne.peach.istgt") == 0
! 937: || strcasecmp(buf, "iqn.2007-09.jp.ne.peach") == 0) {
! 938: /* always zero */
! 939: return 0;
! 940: }
! 941:
! 942: istgt_md5init(&md5ctx);
! 943: istgt_md5update(&md5ctx, buf, strlen(buf));
! 944: istgt_md5final(nbsmd5, &md5ctx);
! 945:
! 946: nbs = 0U;
! 947: idx = ISTGT_MD5DIGEST_LEN - 8;
! 948: if (idx < 0) {
! 949: ISTGT_WARNLOG("missing MD5 length\n");
! 950: idx = 0;
! 951: }
! 952: for (i = idx; i < ISTGT_MD5DIGEST_LEN; i++) {
! 953: nbs |= (uint64_t) nbsmd5[i];
! 954: nbs = nbs << 8;
! 955: }
! 956: return nbs;
! 957: }
! 958:
! 959: static int
! 960: istgt_lu_set_local_settings(ISTGT_Ptr istgt, CF_SECTION *sp, ISTGT_LU_Ptr lu)
! 961: {
! 962: const char *val;
! 963:
! 964: val = istgt_get_val(sp, "MaxOutstandingR2T");
! 965: if (val == NULL) {
! 966: lu->MaxOutstandingR2T = lu->istgt->MaxOutstandingR2T;
! 967: } else {
! 968: lu->MaxOutstandingR2T = (int)strtol(val, NULL, 10);
! 969: if (lu->MaxOutstandingR2T < 1) {
! 970: lu->MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T;
! 971: }
! 972: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxOutstandingR2T %d\n",
! 973: lu->MaxOutstandingR2T);
! 974: }
! 975:
! 976: val = istgt_get_val(sp, "DefaultTime2Wait");
! 977: if (val == NULL) {
! 978: lu->DefaultTime2Wait = lu->istgt->DefaultTime2Wait;
! 979: } else {
! 980: lu->DefaultTime2Wait = (int)strtol(val, NULL, 10);
! 981: if (lu->DefaultTime2Wait < 0) {
! 982: lu->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
! 983: }
! 984: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Wait %d\n",
! 985: lu->DefaultTime2Wait);
! 986: }
! 987:
! 988: val = istgt_get_val(sp, "DefaultTime2Retain");
! 989: if (val == NULL) {
! 990: lu->DefaultTime2Retain = lu->istgt->DefaultTime2Retain;
! 991: } else {
! 992: lu->DefaultTime2Retain = (int)strtol(val, NULL, 10);
! 993: if (lu->DefaultTime2Retain < 0) {
! 994: lu->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
! 995: }
! 996: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Retain %d\n",
! 997: lu->DefaultTime2Retain);
! 998: }
! 999:
! 1000: /* check size limit - RFC3720(12.15, 12.16, 12.17) */
! 1001: if (lu->MaxOutstandingR2T > 65535) {
! 1002: ISTGT_ERRLOG("MaxOutstandingR2T(%d) > 65535\n",
! 1003: lu->MaxOutstandingR2T);
! 1004: return -1;
! 1005: }
! 1006: if (lu->DefaultTime2Wait > 3600) {
! 1007: ISTGT_ERRLOG("DefaultTime2Wait(%d) > 3600\n",
! 1008: lu->DefaultTime2Wait);
! 1009: return -1;
! 1010: }
! 1011: if (lu->DefaultTime2Retain > 3600) {
! 1012: ISTGT_ERRLOG("DefaultTime2Retain(%d) > 3600\n",
! 1013: lu->DefaultTime2Retain);
! 1014: return -1;
! 1015: }
! 1016:
! 1017: val = istgt_get_val(sp, "FirstBurstLength");
! 1018: if (val == NULL) {
! 1019: lu->FirstBurstLength = lu->istgt->FirstBurstLength;
! 1020: } else {
! 1021: lu->FirstBurstLength = (int)strtol(val, NULL, 10);
! 1022: if (lu->FirstBurstLength < 0) {
! 1023: lu->FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
! 1024: }
! 1025: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "FirstBurstLength %d\n",
! 1026: lu->FirstBurstLength);
! 1027: }
! 1028:
! 1029: val = istgt_get_val(sp, "MaxBurstLength");
! 1030: if (val == NULL) {
! 1031: lu->MaxBurstLength = lu->istgt->MaxBurstLength;
! 1032: } else {
! 1033: lu->MaxBurstLength = (int)strtol(val, NULL, 10);
! 1034: if (lu->MaxBurstLength < 0) {
! 1035: lu->MaxBurstLength = DEFAULT_MAXBURSTLENGTH;
! 1036: }
! 1037: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxBurstLength %d\n",
! 1038: lu->MaxBurstLength);
! 1039: }
! 1040:
! 1041: val = istgt_get_val(sp, "MaxRecvDataSegmentLength");
! 1042: if (val == NULL) {
! 1043: lu->MaxRecvDataSegmentLength
! 1044: = lu->istgt->MaxRecvDataSegmentLength;
! 1045: } else {
! 1046: lu->MaxRecvDataSegmentLength = (int)strtol(val, NULL, 10);
! 1047: if (lu->MaxRecvDataSegmentLength < 0) {
! 1048: lu->MaxRecvDataSegmentLength
! 1049: = DEFAULT_MAXRECVDATASEGMENTLENGTH;
! 1050: }
! 1051: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1052: "MaxRecvDataSegmentLength %d\n",
! 1053: lu->MaxRecvDataSegmentLength);
! 1054: }
! 1055:
! 1056: /* check size limit (up to 24bits - RFC3720(12.12)) */
! 1057: if (lu->MaxBurstLength < 512) {
! 1058: ISTGT_ERRLOG("MaxBurstLength(%d) < 512\n",
! 1059: lu->MaxBurstLength);
! 1060: return -1;
! 1061: }
! 1062: if (lu->FirstBurstLength < 512) {
! 1063: ISTGT_ERRLOG("FirstBurstLength(%d) < 512\n",
! 1064: lu->FirstBurstLength);
! 1065: return -1;
! 1066: }
! 1067: if (lu->FirstBurstLength > lu->MaxBurstLength) {
! 1068: ISTGT_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
! 1069: lu->FirstBurstLength, istgt->MaxBurstLength);
! 1070: return -1;
! 1071: }
! 1072: if (lu->MaxBurstLength > 0x00ffffff) {
! 1073: ISTGT_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
! 1074: lu->MaxBurstLength);
! 1075: return -1;
! 1076: }
! 1077: if (lu->MaxRecvDataSegmentLength < 512) {
! 1078: ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
! 1079: lu->MaxRecvDataSegmentLength);
! 1080: return -1;
! 1081: }
! 1082: if (lu->MaxRecvDataSegmentLength > 0x00ffffff) {
! 1083: ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
! 1084: lu->MaxRecvDataSegmentLength);
! 1085: return -1;
! 1086: }
! 1087:
! 1088: val = istgt_get_val(sp, "InitialR2T");
! 1089: if (val == NULL) {
! 1090: lu->InitialR2T = lu->istgt->InitialR2T;
! 1091: } else {
! 1092: if (strcasecmp(val, "Yes") == 0) {
! 1093: lu->InitialR2T = 1;
! 1094: } else if (strcasecmp(val, "No") == 0) {
! 1095: #if 0
! 1096: lu->InitialR2T = 0;
! 1097: #else
! 1098: ISTGT_ERRLOG("not supported value %s\n", val);
! 1099: return -1;
! 1100: #endif
! 1101: } else {
! 1102: ISTGT_ERRLOG("unknown value %s\n", val);
! 1103: return -1;
! 1104: }
! 1105: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "InitialR2T %s\n",
! 1106: lu->InitialR2T ? "Yes" : "No");
! 1107: }
! 1108:
! 1109: val = istgt_get_val(sp, "ImmediateData");
! 1110: if (val == NULL) {
! 1111: lu->ImmediateData = lu->istgt->ImmediateData;
! 1112: } else {
! 1113: if (strcasecmp(val, "Yes") == 0) {
! 1114: lu->ImmediateData = 1;
! 1115: } else if (strcasecmp(val, "No") == 0) {
! 1116: lu->ImmediateData = 0;
! 1117: } else {
! 1118: ISTGT_ERRLOG("unknown value %s\n", val);
! 1119: return -1;
! 1120: }
! 1121: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ImmediateData %s\n",
! 1122: lu->ImmediateData ? "Yes" : "No");
! 1123: }
! 1124:
! 1125: val = istgt_get_val(sp, "DataPDUInOrder");
! 1126: if (val == NULL) {
! 1127: lu->DataPDUInOrder = lu->istgt->DataPDUInOrder;
! 1128: } else {
! 1129: if (strcasecmp(val, "Yes") == 0) {
! 1130: lu->DataPDUInOrder = 1;
! 1131: } else if (strcasecmp(val, "No") == 0) {
! 1132: #if 0
! 1133: lu->DataPDUInOrder = 0;
! 1134: #else
! 1135: ISTGT_ERRLOG("not supported value %s\n", val);
! 1136: return -1;
! 1137: #endif
! 1138: } else {
! 1139: ISTGT_ERRLOG("unknown value %s\n", val);
! 1140: return -1;
! 1141: }
! 1142: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataPDUInOrder %s\n",
! 1143: lu->DataPDUInOrder ? "Yes" : "No");
! 1144: }
! 1145:
! 1146: val = istgt_get_val(sp, "DataSequenceInOrder");
! 1147: if (val == NULL) {
! 1148: lu->DataSequenceInOrder = lu->istgt->DataSequenceInOrder;
! 1149: } else {
! 1150: if (strcasecmp(val, "Yes") == 0) {
! 1151: lu->DataSequenceInOrder = 1;
! 1152: } else if (strcasecmp(val, "No") == 0) {
! 1153: #if 0
! 1154: lu->DataSequenceInOrder = 0;
! 1155: #else
! 1156: ISTGT_ERRLOG("not supported value %s\n", val);
! 1157: return -1;
! 1158: #endif
! 1159: } else {
! 1160: ISTGT_ERRLOG("unknown value %s\n", val);
! 1161: return -1;
! 1162: }
! 1163: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataSequenceInOrder %s\n",
! 1164: lu->DataSequenceInOrder ? "Yes" : "No");
! 1165: }
! 1166:
! 1167: val = istgt_get_val(sp, "ErrorRecoveryLevel");
! 1168: if (val == NULL) {
! 1169: lu->ErrorRecoveryLevel = lu->istgt->ErrorRecoveryLevel;
! 1170: } else {
! 1171: lu->ErrorRecoveryLevel = (int)strtol(val, NULL, 10);
! 1172: if (lu->ErrorRecoveryLevel < 0) {
! 1173: lu->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
! 1174: } else if (lu->ErrorRecoveryLevel == 0) {
! 1175: lu->ErrorRecoveryLevel = 0;
! 1176: } else if (lu->ErrorRecoveryLevel == 1) {
! 1177: #if 0
! 1178: lu->ErrorRecoveryLevel = 1;
! 1179: #else
! 1180: ISTGT_ERRLOG("not supported value %d\n",
! 1181: lu->ErrorRecoveryLevel);
! 1182: return -1;
! 1183: #endif
! 1184: } else if (lu->ErrorRecoveryLevel == 2) {
! 1185: #if 0
! 1186: lu->ErrorRecoveryLevel = 2;
! 1187: #else
! 1188: ISTGT_ERRLOG("not supported value %d\n",
! 1189: lu->ErrorRecoveryLevel);
! 1190: return -1;
! 1191: #endif
! 1192: } else {
! 1193: ISTGT_ERRLOG("not supported value %d\n",
! 1194: lu->ErrorRecoveryLevel);
! 1195: return -1;
! 1196: }
! 1197: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ErrorRecoveryLevel %d\n",
! 1198: istgt->ErrorRecoveryLevel);
! 1199: }
! 1200:
! 1201: return 0;
! 1202: }
! 1203:
! 1204: static int
! 1205: istgt_lu_add_unit(ISTGT_Ptr istgt, CF_SECTION *sp)
! 1206: {
! 1207: char buf[MAX_TMPBUF], buf2[MAX_TMPBUF];
! 1208: ISTGT_LU_Ptr lu;
! 1209: const char *vendor, *product, *revision, *serial;
! 1210: const char *pg_tag, *ig_tag;
! 1211: const char *ag_tag;
! 1212: const char *flags, *file, *size;
! 1213: const char *key, *val;
! 1214: uint64_t msize;
! 1215: uint64_t nbs64;
! 1216: int pg_tag_i, ig_tag_i;
! 1217: int ag_tag_i;
! 1218: int rpm, formfactor;
! 1219: int mflags;
! 1220: int slot;
! 1221: int nbs;
! 1222: int i, j, k;
! 1223: int rc;
! 1224:
! 1225: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add unit %d\n", sp->num);
! 1226:
! 1227: if (sp->num >= MAX_LOGICAL_UNIT) {
! 1228: ISTGT_ERRLOG("LU%d: over maximum unit number\n", sp->num);
! 1229: return -1;
! 1230: }
! 1231: if (istgt->logical_unit[sp->num] != NULL) {
! 1232: ISTGT_ERRLOG("LU%d: duplicate unit\n", sp->num);
! 1233: return -1;
! 1234: }
! 1235:
! 1236: lu = xmalloc(sizeof *lu);
! 1237: memset(lu, 0, sizeof *lu);
! 1238: lu->num = sp->num;
! 1239: lu->istgt = istgt;
! 1240: istgt_lu_set_state(lu, ISTGT_STATE_INVALID);
! 1241: nbs64 = istgt_lu_get_nbserial(istgt->nodebase);
! 1242: #if 0
! 1243: /* disabled now */
! 1244: nbs = (int) (nbs64 % 900) * 100000;
! 1245: #else
! 1246: nbs = 0;
! 1247: #endif
! 1248:
! 1249: val = istgt_get_val(sp, "Comment");
! 1250: if (val != NULL) {
! 1251: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
! 1252: }
! 1253:
! 1254: val = istgt_get_val(sp, "TargetName");
! 1255: if (val == NULL) {
! 1256: ISTGT_ERRLOG("LU%d: TargetName not found\n", lu->num);
! 1257: goto error_return;
! 1258: }
! 1259: if (strncasecmp(val, "iqn.", 4) != 0
! 1260: && strncasecmp(val, "eui.", 4) != 0
! 1261: && strncasecmp(val, "naa.", 4) != 0) {
! 1262: snprintf(buf, sizeof buf, "%s:%s", istgt->nodebase, val);
! 1263: } else {
! 1264: snprintf(buf, sizeof buf, "%s", val);
! 1265: }
! 1266: if (istgt_lu_check_iscsi_name(buf) != 0) {
! 1267: ISTGT_ERRLOG("TargetName %s contains an invalid character or format.\n",
! 1268: buf);
! 1269: #if 0
! 1270: goto error_return;
! 1271: #endif
! 1272: }
! 1273: lu->name = xstrdup(buf);
! 1274: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "TargetName %s\n",
! 1275: lu->name);
! 1276:
! 1277: val = istgt_get_val(sp, "TargetAlias");
! 1278: if (val == NULL) {
! 1279: lu->alias = NULL;
! 1280: } else {
! 1281: lu->alias = xstrdup(val);
! 1282: }
! 1283: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "TargetAlias %s\n",
! 1284: lu->alias);
! 1285:
! 1286: val = istgt_get_val(sp, "Mapping");
! 1287: if (val == NULL) {
! 1288: /* no map */
! 1289: lu->maxmap = 0;
! 1290: } else {
! 1291: lu->maxmap = 0;
! 1292: for (i = 0; ; i++) {
! 1293: val = istgt_get_nmval(sp, "Mapping", i, 0);
! 1294: if (val == NULL)
! 1295: break;
! 1296: if (lu->maxmap >= MAX_LU_MAP) {
! 1297: ISTGT_ERRLOG("LU%d: too many mapping\n", lu->num);
! 1298: goto error_return;
! 1299: }
! 1300: pg_tag = istgt_get_nmval(sp, "Mapping", i, 0);
! 1301: ig_tag = istgt_get_nmval(sp, "Mapping", i, 1);
! 1302: if (pg_tag == NULL || ig_tag == NULL) {
! 1303: ISTGT_ERRLOG("LU%d: mapping error\n", lu->num);
! 1304: goto error_return;
! 1305: }
! 1306: if (strncasecmp(pg_tag, "PortalGroup",
! 1307: strlen("PortalGroup")) != 0
! 1308: || sscanf(pg_tag, "%*[^0-9]%d", &pg_tag_i) != 1) {
! 1309: ISTGT_ERRLOG("LU%d: mapping portal error\n", lu->num);
! 1310: goto error_return;
! 1311: }
! 1312: if (strncasecmp(ig_tag, "InitiatorGroup",
! 1313: strlen("InitiatorGroup")) != 0
! 1314: || sscanf(ig_tag, "%*[^0-9]%d", &ig_tag_i) != 1) {
! 1315: ISTGT_ERRLOG("LU%d: mapping initiator error\n", lu->num);
! 1316: goto error_return;
! 1317: }
! 1318: if (pg_tag_i < 1 || ig_tag_i < 1) {
! 1319: ISTGT_ERRLOG("LU%d: invalid group tag\n", lu->num);
! 1320: goto error_return;
! 1321: }
! 1322: if (istgt_lu_find_portalgroup(istgt, pg_tag_i) == NULL) {
! 1323: ISTGT_ERRLOG("LU%d: PortalGroup%d not found\n",
! 1324: lu->num, pg_tag_i);
! 1325: goto error_return;
! 1326: }
! 1327: if (istgt_lu_find_initiatorgroup(istgt, ig_tag_i) == NULL) {
! 1328: ISTGT_ERRLOG("LU%d: InitiatorGroup%d not found\n",
! 1329: lu->num, ig_tag_i);
! 1330: goto error_return;
! 1331: }
! 1332: lu->map[i].pg_tag = pg_tag_i;
! 1333: lu->map[i].pg_aas = AAS_ACTIVE_OPTIMIZED;
! 1334: //lu->map[i].pg_aas = AAS_ACTIVE_NON_OPTIMIZED;
! 1335: lu->map[i].pg_aas |= AAS_STATUS_IMPLICIT;
! 1336: lu->map[i].ig_tag = ig_tag_i;
! 1337: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1338: "Mapping PortalGroup%d InitiatorGroup%d\n",
! 1339: lu->map[i].pg_tag, lu->map[i].ig_tag);
! 1340: lu->maxmap = i + 1;
! 1341: }
! 1342: }
! 1343: if (lu->maxmap == 0) {
! 1344: ISTGT_ERRLOG("LU%d: no Mapping\n", lu->num);
! 1345: goto error_return;
! 1346: }
! 1347:
! 1348: val = istgt_get_val(sp, "AuthMethod");
! 1349: if (val == NULL) {
! 1350: /* none */
! 1351: lu->no_auth_chap = 0;
! 1352: lu->auth_chap = 0;
! 1353: lu->auth_chap_mutual = 0;
! 1354: } else {
! 1355: lu->no_auth_chap = 0;
! 1356: for (i = 0; ; i++) {
! 1357: val = istgt_get_nmval(sp, "AuthMethod", 0, i);
! 1358: if (val == NULL)
! 1359: break;
! 1360: if (strcasecmp(val, "CHAP") == 0) {
! 1361: lu->auth_chap = 1;
! 1362: } else if (strcasecmp(val, "Mutual") == 0) {
! 1363: lu->auth_chap_mutual = 1;
! 1364: } else if (strcasecmp(val, "Auto") == 0) {
! 1365: lu->auth_chap = 0;
! 1366: lu->auth_chap_mutual = 0;
! 1367: } else if (strcasecmp(val, "None") == 0) {
! 1368: lu->no_auth_chap = 1;
! 1369: lu->auth_chap = 0;
! 1370: lu->auth_chap_mutual = 0;
! 1371: } else {
! 1372: ISTGT_ERRLOG("LU%d: unknown auth\n", lu->num);
! 1373: goto error_return;
! 1374: }
! 1375: }
! 1376: if (lu->auth_chap_mutual && !lu->auth_chap) {
! 1377: ISTGT_ERRLOG("LU%d: Mutual but not CHAP\n", lu->num);
! 1378: goto error_return;
! 1379: }
! 1380: }
! 1381: if (lu->no_auth_chap != 0) {
! 1382: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod None\n");
! 1383: } else if (lu->auth_chap == 0) {
! 1384: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod Auto\n");
! 1385: } else {
! 1386: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod %s %s\n",
! 1387: lu->auth_chap ? "CHAP" : "",
! 1388: lu->auth_chap_mutual ? "Mutual" : "");
! 1389: }
! 1390:
! 1391: val = istgt_get_val(sp, "AuthGroup");
! 1392: if (val == NULL) {
! 1393: lu->auth_group = 0;
! 1394: } else {
! 1395: ag_tag = val;
! 1396: if (strcasecmp(ag_tag, "None") == 0) {
! 1397: ag_tag_i = 0;
! 1398: } else {
! 1399: if (strncasecmp(ag_tag, "AuthGroup",
! 1400: strlen("AuthGroup")) != 0
! 1401: || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) {
! 1402: ISTGT_ERRLOG("LU%d: auth group error\n", lu->num);
! 1403: goto error_return;
! 1404: }
! 1405: if (ag_tag_i == 0) {
! 1406: ISTGT_ERRLOG("LU%d: invalid auth group %d\n", ag_tag_i);
! 1407: goto error_return;
! 1408: }
! 1409: }
! 1410: lu->auth_group = ag_tag_i;
! 1411: }
! 1412: if (lu->auth_group == 0) {
! 1413: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthGroup None\n");
! 1414: } else {
! 1415: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthGroup AuthGroup%d\n",
! 1416: lu->auth_group);
! 1417: }
! 1418:
! 1419: val = istgt_get_val(sp, "UseDigest");
! 1420: if (val != NULL) {
! 1421: for (i = 0; ; i++) {
! 1422: val = istgt_get_nmval(sp, "UseDigest", 0, i);
! 1423: if (val == NULL)
! 1424: break;
! 1425: if (strcasecmp(val, "Header") == 0) {
! 1426: lu->header_digest = 1;
! 1427: } else if (strcasecmp(val, "Data") == 0) {
! 1428: lu->data_digest = 1;
! 1429: } else if (strcasecmp(val, "Auto") == 0) {
! 1430: lu->header_digest = 0;
! 1431: lu->data_digest = 0;
! 1432: } else {
! 1433: ISTGT_ERRLOG("LU%d: unknown digest\n", lu->num);
! 1434: goto error_return;
! 1435: }
! 1436: }
! 1437: }
! 1438: if (lu->header_digest == 0 && lu->data_digest == 0) {
! 1439: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UseDigest Auto\n");
! 1440: } else {
! 1441: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UseDigest %s %s\n",
! 1442: lu->header_digest ? "Header" : "",
! 1443: lu->data_digest ? "Data" : "");
! 1444: }
! 1445:
! 1446: val = istgt_get_val(sp, "ReadOnly");
! 1447: if (val == NULL) {
! 1448: lu->readonly = 0;
! 1449: } else if (strcasecmp(val, "Yes") == 0) {
! 1450: lu->readonly = 1;
! 1451: }
! 1452: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ReadOnly %s\n",
! 1453: lu->readonly ? "Yes" : "No");
! 1454:
! 1455: val = istgt_get_val(sp, "UnitType");
! 1456: if (val == NULL) {
! 1457: ISTGT_ERRLOG("LU%d: unknown unit type\n", lu->num);
! 1458: goto error_return;
! 1459: }
! 1460: if (strcasecmp(val, "Pass") == 0) {
! 1461: lu->type = ISTGT_LU_TYPE_PASS;
! 1462: } else if (strcasecmp(val, "Disk") == 0) {
! 1463: lu->type = ISTGT_LU_TYPE_DISK;
! 1464: } else if (strcasecmp(val, "DVD") == 0) {
! 1465: lu->type = ISTGT_LU_TYPE_DVD;
! 1466: } else if (strcasecmp(val, "Tape") == 0) {
! 1467: lu->type = ISTGT_LU_TYPE_TAPE;
! 1468: } else {
! 1469: ISTGT_ERRLOG("LU%d: unknown unit type\n", lu->num);
! 1470: goto error_return;
! 1471: }
! 1472: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitType %d (%s)\n",
! 1473: lu->type, val);
! 1474:
! 1475: val = istgt_get_val(sp, "UnitOnline");
! 1476: if (val == NULL) {
! 1477: lu->online = 1;
! 1478: } else if (strcasecmp(val, "Yes") == 0) {
! 1479: lu->online = 1;
! 1480: }
! 1481: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitOnline %s\n",
! 1482: lu->online ? "Yes" : "No");
! 1483:
! 1484: vendor = istgt_get_nmval(sp, "UnitInquiry", 0, 0);
! 1485: product = istgt_get_nmval(sp, "UnitInquiry", 0, 1);
! 1486: revision = istgt_get_nmval(sp, "UnitInquiry", 0, 2);
! 1487: serial = istgt_get_nmval(sp, "UnitInquiry", 0, 3);
! 1488: switch (lu->type) {
! 1489: case ISTGT_LU_TYPE_DISK:
! 1490: if (vendor == NULL || strlen(vendor) == 0)
! 1491: vendor = DEFAULT_LU_VENDOR_DISK;
! 1492: if (product == NULL || strlen(product) == 0)
! 1493: product = DEFAULT_LU_PRODUCT_DISK;
! 1494: if (revision == NULL || strlen(revision) == 0)
! 1495: revision = DEFAULT_LU_REVISION_DISK;
! 1496: if (serial == NULL || strlen(serial) == 0) {
! 1497: snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
! 1498: serial = (const char *) &buf[0];
! 1499: }
! 1500: break;
! 1501: case ISTGT_LU_TYPE_DVD:
! 1502: if (vendor == NULL || strlen(vendor) == 0)
! 1503: vendor = DEFAULT_LU_VENDOR_DVD;
! 1504: if (product == NULL || strlen(product) == 0)
! 1505: product = DEFAULT_LU_PRODUCT_DVD;
! 1506: if (revision == NULL || strlen(revision) == 0)
! 1507: revision = DEFAULT_LU_REVISION_DVD;
! 1508: if (serial == NULL || strlen(serial) == 0) {
! 1509: snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
! 1510: serial = (const char *) &buf[0];
! 1511: }
! 1512: break;
! 1513: case ISTGT_LU_TYPE_TAPE:
! 1514: if (vendor == NULL || strlen(vendor) == 0)
! 1515: vendor = DEFAULT_LU_VENDOR_TAPE;
! 1516: if (product == NULL || strlen(product) == 0)
! 1517: product = DEFAULT_LU_PRODUCT_TAPE;
! 1518: if (revision == NULL || strlen(revision) == 0)
! 1519: revision = DEFAULT_LU_REVISION_TAPE;
! 1520: if (serial == NULL || strlen(serial) == 0) {
! 1521: #ifdef USE_LU_TAPE_DLT8000
! 1522: snprintf(buf, sizeof buf, "CX%.8d", 10000000 + nbs + lu->num);
! 1523: #else
! 1524: snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
! 1525: #endif /* USE_LU_TAPE_DLT8000 */
! 1526: serial = (const char *) &buf[0];
! 1527: }
! 1528: break;
! 1529: default:
! 1530: if (vendor == NULL || strlen(vendor) == 0)
! 1531: vendor = DEFAULT_LU_VENDOR;
! 1532: if (product == NULL || strlen(product) == 0)
! 1533: product = DEFAULT_LU_PRODUCT;
! 1534: if (revision == NULL || strlen(revision) == 0)
! 1535: revision = DEFAULT_LU_REVISION;
! 1536: if (serial == NULL || strlen(serial) == 0) {
! 1537: snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
! 1538: serial = (const char *) &buf[0];
! 1539: }
! 1540: break;
! 1541: }
! 1542: lu->inq_vendor = xstrdup(vendor);
! 1543: lu->inq_product = xstrdup(product);
! 1544: lu->inq_revision = xstrdup(revision);
! 1545: lu->inq_serial = xstrdup(serial);
! 1546: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitInquiry %s %s %s %s\n",
! 1547: lu->inq_vendor, lu->inq_product, lu->inq_revision,
! 1548: lu->inq_serial);
! 1549:
! 1550: val = istgt_get_val(sp, "BlockLength");
! 1551: if (val == NULL) {
! 1552: switch (lu->type) {
! 1553: case ISTGT_LU_TYPE_DISK:
! 1554: lu->blocklen = DEFAULT_LU_BLOCKLEN_DISK;
! 1555: break;
! 1556: case ISTGT_LU_TYPE_DVD:
! 1557: lu->blocklen = DEFAULT_LU_BLOCKLEN_DVD;
! 1558: break;
! 1559: case ISTGT_LU_TYPE_TAPE:
! 1560: lu->blocklen = DEFAULT_LU_BLOCKLEN_TAPE;
! 1561: break;
! 1562: default:
! 1563: lu->blocklen = DEFAULT_LU_BLOCKLEN;
! 1564: break;
! 1565: }
! 1566: } else {
! 1567: lu->blocklen = (int) strtol(val, NULL, 10);
! 1568: }
! 1569: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "BlockLength %d\n",
! 1570: lu->blocklen);
! 1571:
! 1572: val = istgt_get_val(sp, "QueueDepth");
! 1573: if (val == NULL) {
! 1574: switch (lu->type) {
! 1575: case ISTGT_LU_TYPE_DISK:
! 1576: lu->queue_depth = DEFAULT_LU_QUEUE_DEPTH;
! 1577: //lu->queue_depth = 0;
! 1578: break;
! 1579: case ISTGT_LU_TYPE_DVD:
! 1580: case ISTGT_LU_TYPE_TAPE:
! 1581: default:
! 1582: lu->queue_depth = 0;
! 1583: break;
! 1584: }
! 1585: } else {
! 1586: lu->queue_depth = (int) strtol(val, NULL, 10);
! 1587: }
! 1588: if (lu->queue_depth < 0 || lu->queue_depth >= MAX_LU_QUEUE_DEPTH) {
! 1589: ISTGT_ERRLOG("LU%d: queue depth range error\n");
! 1590: goto error_return;
! 1591: }
! 1592: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "QueueDepth %d\n",
! 1593: lu->queue_depth);
! 1594:
! 1595: lu->maxlun = 0;
! 1596: for (i = 0; i < MAX_LU_LUN; i++) {
! 1597: lu->lun[i].type = ISTGT_LU_LUN_TYPE_NONE;
! 1598: lu->lun[i].rotationrate = DEFAULT_LU_ROTATIONRATE;
! 1599: lu->lun[i].formfactor = DEFAULT_LU_FORMFACTOR;
! 1600: lu->lun[i].readcache = 1;
! 1601: lu->lun[i].writecache = 1;
! 1602: lu->lun[i].serial = NULL;
! 1603: lu->lun[i].spec = NULL;
! 1604: snprintf(buf, sizeof buf, "LUN%d", i);
! 1605: val = istgt_get_val(sp, buf);
! 1606: if (val == NULL)
! 1607: continue;
! 1608: if (i != 0) {
! 1609: /* default LUN serial (except LUN0) */
! 1610: snprintf(buf2, sizeof buf2, "%sL%d", lu->inq_serial, i);
! 1611: lu->lun[i].serial = xstrdup(buf2);
! 1612: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d Serial %s (default)\n",
! 1613: i, buf2);
! 1614: }
! 1615: for (j = 0; ; j++) {
! 1616: val = istgt_get_nmval(sp, buf, j, 0);
! 1617: if (val == NULL)
! 1618: break;
! 1619: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d\n", i);
! 1620: if (strcasecmp(val, "Device") == 0) {
! 1621: if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
! 1622: ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
! 1623: goto error_return;
! 1624: }
! 1625: lu->lun[i].type = ISTGT_LU_LUN_TYPE_DEVICE;
! 1626:
! 1627: file = istgt_get_nmval(sp, buf, j, 1);
! 1628: if (file == NULL) {
! 1629: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1630: goto error_return;
! 1631: }
! 1632: lu->lun[i].u.device.file = xstrdup(file);
! 1633: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Device file=%s\n",
! 1634: lu->lun[i].u.device.file);
! 1635: } else if (strcasecmp(val, "Storage") == 0) {
! 1636: if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
! 1637: ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
! 1638: goto error_return;
! 1639: }
! 1640: lu->lun[i].type = ISTGT_LU_LUN_TYPE_STORAGE;
! 1641:
! 1642: file = istgt_get_nmval(sp, buf, j, 1);
! 1643: size = istgt_get_nmval(sp, buf, j, 2);
! 1644: if (file == NULL || size == NULL) {
! 1645: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1646: goto error_return;
! 1647: }
! 1648: if (strcasecmp(size, "Auto") == 0
! 1649: || strcasecmp(size, "Size") == 0) {
! 1650: lu->lun[i].u.storage.size = istgt_lu_get_filesize(file);
! 1651: } else {
! 1652: lu->lun[i].u.storage.size = istgt_lu_parse_size(size);
! 1653: }
! 1654: if (lu->lun[i].u.storage.size == 0) {
! 1655: ISTGT_ERRLOG("LU%d: LUN%d: Auto size error (%s)\n", lu->num, i, file);
! 1656: goto error_return;
! 1657: }
! 1658: lu->lun[i].u.storage.fd = -1;
! 1659: lu->lun[i].u.storage.file = xstrdup(file);
! 1660: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1661: "Storage file=%s, size=%"PRIu64"\n",
! 1662: lu->lun[i].u.storage.file,
! 1663: lu->lun[i].u.storage.size);
! 1664: } else if (strcasecmp(val, "Removable") == 0) {
! 1665: if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
! 1666: ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
! 1667: goto error_return;
! 1668: }
! 1669: lu->lun[i].type = ISTGT_LU_LUN_TYPE_REMOVABLE;
! 1670:
! 1671: flags = istgt_get_nmval(sp, buf, j, 1);
! 1672: file = istgt_get_nmval(sp, buf, j, 2);
! 1673: size = istgt_get_nmval(sp, buf, j, 3);
! 1674: if (flags == NULL || file == NULL || size == NULL) {
! 1675: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1676: goto error_return;
! 1677: }
! 1678: mflags = istgt_lu_parse_media_flags(flags);
! 1679: msize = istgt_lu_parse_media_size(file, size, &mflags);
! 1680: if (msize == 0 && strcasecmp(file, "/dev/null") == 0) {
! 1681: /* empty media */
! 1682: } else if (msize == 0) {
! 1683: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1684: goto error_return;
! 1685: }
! 1686: lu->lun[i].u.removable.type = 0;
! 1687: lu->lun[i].u.removable.id = 0;
! 1688: lu->lun[i].u.removable.fd = -1;
! 1689: lu->lun[i].u.removable.flags = mflags;
! 1690: lu->lun[i].u.removable.file = xstrdup(file);
! 1691: lu->lun[i].u.removable.size = msize;
! 1692: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1693: "Removable file=%s, size=%"PRIu64", flags=%x\n",
! 1694: lu->lun[i].u.removable.file,
! 1695: lu->lun[i].u.removable.size,
! 1696: lu->lun[i].u.removable.flags);
! 1697: } else if (strncasecmp(val, "Slot", 4) == 0) {
! 1698: if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_NONE) {
! 1699: lu->lun[i].u.slot.maxslot = 0;
! 1700: for (k = 0; k < MAX_LU_LUN_SLOT; k++) {
! 1701: lu->lun[i].u.slot.present[k] = 0;
! 1702: lu->lun[i].u.slot.flags[k] = 0;
! 1703: lu->lun[i].u.slot.file[k] = NULL;
! 1704: lu->lun[i].u.slot.size[k] = 0;
! 1705: }
! 1706: } else if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_SLOT) {
! 1707: ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
! 1708: goto error_return;
! 1709: }
! 1710: lu->lun[i].type = ISTGT_LU_LUN_TYPE_SLOT;
! 1711: if (sscanf(val, "%*[^0-9]%d", &slot) != 1) {
! 1712: ISTGT_ERRLOG("LU%d: slot number error\n", lu->num);
! 1713: goto error_return;
! 1714: }
! 1715: if (slot < 0 || slot >= MAX_LU_LUN_SLOT) {
! 1716: ISTGT_ERRLOG("LU%d: slot number range error\n", lu->num);
! 1717: goto error_return;
! 1718: }
! 1719: if (lu->lun[i].u.slot.present[slot]) {
! 1720: ISTGT_ERRLOG("LU%d: duplicate slot %d\n", lu->num, slot);
! 1721: goto error_return;
! 1722: }
! 1723: lu->lun[i].u.slot.present[slot] = 1;
! 1724: if (slot + 1 > lu->lun[i].u.slot.maxslot) {
! 1725: lu->lun[i].u.slot.maxslot = slot + 1;
! 1726: }
! 1727:
! 1728: flags = istgt_get_nmval(sp, buf, j, 1);
! 1729: file = istgt_get_nmval(sp, buf, j, 2);
! 1730: size = istgt_get_nmval(sp, buf, j, 3);
! 1731: if (flags == NULL || file == NULL || size == NULL) {
! 1732: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1733: goto error_return;
! 1734: }
! 1735: mflags = istgt_lu_parse_media_flags(flags);
! 1736: msize = istgt_lu_parse_media_size(file, size, &mflags);
! 1737: if (msize == 0) {
! 1738: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1739: goto error_return;
! 1740: }
! 1741: lu->lun[i].u.slot.flags[slot] = mflags;
! 1742: lu->lun[i].u.slot.file[slot] = xstrdup(file);
! 1743: lu->lun[i].u.slot.size[slot] = msize;
! 1744: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 1745: "Slot%d file=%s, size=%"PRIu64", flags=%x\n",
! 1746: slot,
! 1747: lu->lun[i].u.slot.file[slot],
! 1748: lu->lun[i].u.slot.size[slot],
! 1749: lu->lun[i].u.slot.flags[slot]);
! 1750: } else if (strncasecmp(val, "Option", 6) == 0) {
! 1751: key = istgt_get_nmval(sp, buf, j, 1);
! 1752: val = istgt_get_nmval(sp, buf, j, 2);
! 1753: if (key == NULL || val == NULL) {
! 1754: ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
! 1755: goto error_return;
! 1756: }
! 1757: if (strcasecmp(key, "Serial") == 0) {
! 1758: /* set LUN serial */
! 1759: if (strlen(val) == 0) {
! 1760: ISTGT_ERRLOG("LU%d: LUN%d: no serial\n",
! 1761: lu->num, i);
! 1762: goto error_return;
! 1763: }
! 1764: xfree(lu->lun[i].serial);
! 1765: lu->lun[i].serial = xstrdup(val);
! 1766: } else if (strcasecmp(key, "RPM") == 0) {
! 1767: rpm = (int)strtol(val, NULL, 10);
! 1768: if (rpm < 0) {
! 1769: rpm = 0;
! 1770: } else if (rpm > 0xfffe) {
! 1771: rpm = 0xfffe;
! 1772: }
! 1773: lu->lun[i].rotationrate = rpm;
! 1774: } else if (strcasecmp(key, "FormFactor") == 0) {
! 1775: formfactor = (int)strtol(val, NULL, 10);
! 1776: if (formfactor < 0) {
! 1777: formfactor = 0;
! 1778: } else if (formfactor > 0x0f) {
! 1779: formfactor = 0xf;
! 1780: }
! 1781: lu->lun[i].formfactor = formfactor;
! 1782: } else if (strcasecmp(key, "ReadCache") == 0) {
! 1783: if (strcasecmp(val, "Enable") == 0) {
! 1784: lu->lun[i].readcache = 1;
! 1785: } else if (strcasecmp(val, "Disable") == 0) {
! 1786: lu->lun[i].readcache = 0;
! 1787: } else {
! 1788: ISTGT_ERRLOG("LU%d: LUN%d: unknown val(%s)\n",
! 1789: lu->num, i, val);
! 1790: }
! 1791: } else if (strcasecmp(key, "WriteCache") == 0) {
! 1792: if (strcasecmp(val, "Enable") == 0) {
! 1793: lu->lun[i].writecache = 1;
! 1794: } else if (strcasecmp(val, "Disable") == 0) {
! 1795: lu->lun[i].writecache = 0;
! 1796: } else {
! 1797: ISTGT_ERRLOG("LU%d: LUN%d: unknown val(%s)\n",
! 1798: lu->num, i, val);
! 1799: }
! 1800: } else {
! 1801: ISTGT_WARNLOG("LU%d: LUN%d: unknown key(%s)\n",
! 1802: lu->num, i, key);
! 1803: continue;
! 1804: }
! 1805: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d Option %s => %s\n",
! 1806: i, key, val);
! 1807: continue;
! 1808: } else {
! 1809: ISTGT_ERRLOG("LU%d: unknown lun type\n", lu->num);
! 1810: goto error_return;
! 1811: }
! 1812: }
! 1813: if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_SLOT) {
! 1814: if (lu->lun[i].u.slot.maxslot == 0) {
! 1815: ISTGT_ERRLOG("LU%d: no slot\n", lu->num);
! 1816: goto error_return;
! 1817: }
! 1818: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "maxslot=%d\n",
! 1819: lu->lun[i].u.slot.maxslot);
! 1820: }
! 1821: lu->maxlun = i + 1;
! 1822: }
! 1823: if (lu->maxlun == 0) {
! 1824: ISTGT_ERRLOG("LU%d: no LUN\n", lu->num);
! 1825: goto error_return;
! 1826: }
! 1827: if (lu->lun[0].type == ISTGT_LU_LUN_TYPE_NONE) {
! 1828: ISTGT_ERRLOG("LU%d: no LUN0\n", lu->num);
! 1829: goto error_return;
! 1830: }
! 1831:
! 1832: /* set local values if any */
! 1833: rc = istgt_lu_set_local_settings(istgt, sp, lu);
! 1834: if (rc < 0) {
! 1835: ISTGT_ERRLOG("LU%d: local setting error\n", lu->num);
! 1836: goto error_return;
! 1837: }
! 1838:
! 1839: /* tsih 0 is reserved */
! 1840: for (i = 0; i < MAX_LU_TSIH; i++) {
! 1841: lu->tsih[i].tag = 0;
! 1842: lu->tsih[i].tsih = 0;
! 1843: lu->tsih[i].initiator_port = NULL;
! 1844: }
! 1845: lu->maxtsih = 1;
! 1846: lu->last_tsih = 0;
! 1847:
! 1848: MTX_LOCK(&istgt->mutex);
! 1849: istgt->nlogical_unit++;
! 1850: istgt->logical_unit[lu->num] = lu;
! 1851: MTX_UNLOCK(&istgt->mutex);
! 1852: return 0;
! 1853:
! 1854: error_return:
! 1855: xfree(lu->name);
! 1856: xfree(lu->alias);
! 1857: xfree(lu->inq_vendor);
! 1858: xfree(lu->inq_product);
! 1859: xfree(lu->inq_revision);
! 1860: for (i = 0; i < MAX_LU_LUN; i++) {
! 1861: switch (lu->lun[i].type) {
! 1862: case ISTGT_LU_LUN_TYPE_DEVICE:
! 1863: xfree(lu->lun[i].u.device.file);
! 1864: break;
! 1865: case ISTGT_LU_LUN_TYPE_STORAGE:
! 1866: xfree(lu->lun[i].u.storage.file);
! 1867: break;
! 1868: case ISTGT_LU_LUN_TYPE_REMOVABLE:
! 1869: xfree(lu->lun[i].u.removable.file);
! 1870: break;
! 1871: case ISTGT_LU_LUN_TYPE_SLOT:
! 1872: for (j = 0; j < lu->lun[i].u.slot.maxslot; j++) {
! 1873: xfree(lu->lun[i].u.slot.file[j]);
! 1874: }
! 1875: break;
! 1876: case ISTGT_LU_LUN_TYPE_NONE:
! 1877: default:
! 1878: break;
! 1879: }
! 1880: }
! 1881: for (i = 0; i < MAX_LU_TSIH; i++) {
! 1882: xfree(lu->tsih[i].initiator_port);
! 1883: }
! 1884: for (i = 0; i < lu->maxmap; i++) {
! 1885: /* nothing */
! 1886: }
! 1887:
! 1888: xfree(lu);
! 1889: return -1;
! 1890: }
! 1891:
! 1892: static int
! 1893: istgt_lu_del_unit(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
! 1894: {
! 1895: int i, j;
! 1896:
! 1897: if (lu ==NULL)
! 1898: return 0;
! 1899: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "del unit %d\n", lu->num);
! 1900:
! 1901: MTX_LOCK(&istgt->mutex);
! 1902: istgt->nlogical_unit--;
! 1903: istgt->logical_unit[lu->num] = NULL;
! 1904: MTX_UNLOCK(&istgt->mutex);
! 1905:
! 1906: xfree(lu->name);
! 1907: xfree(lu->alias);
! 1908: xfree(lu->inq_vendor);
! 1909: xfree(lu->inq_product);
! 1910: xfree(lu->inq_revision);
! 1911: xfree(lu->inq_serial);
! 1912: for (i = 0; i < MAX_LU_LUN; i++) {
! 1913: xfree(lu->lun[i].serial);
! 1914: switch (lu->lun[i].type) {
! 1915: case ISTGT_LU_LUN_TYPE_DEVICE:
! 1916: xfree(lu->lun[i].u.device.file);
! 1917: break;
! 1918: case ISTGT_LU_LUN_TYPE_STORAGE:
! 1919: xfree(lu->lun[i].u.storage.file);
! 1920: break;
! 1921: case ISTGT_LU_LUN_TYPE_REMOVABLE:
! 1922: xfree(lu->lun[i].u.removable.file);
! 1923: break;
! 1924: case ISTGT_LU_LUN_TYPE_SLOT:
! 1925: for (j = 0; j < lu->lun[i].u.slot.maxslot; j++) {
! 1926: xfree(lu->lun[i].u.slot.file[j]);
! 1927: }
! 1928: break;
! 1929: case ISTGT_LU_LUN_TYPE_NONE:
! 1930: default:
! 1931: break;
! 1932: }
! 1933: }
! 1934: for (i = 0; i < MAX_LU_TSIH; i++) {
! 1935: xfree(lu->tsih[i].initiator_port);
! 1936: }
! 1937: for (i = 0; i < lu->maxmap; i++) {
! 1938: /* nothing */
! 1939: }
! 1940:
! 1941: return 0;
! 1942: }
! 1943:
! 1944: static void *luworker(void *arg);
! 1945:
! 1946: int
! 1947: istgt_lu_init(ISTGT_Ptr istgt)
! 1948: {
! 1949: ISTGT_LU_Ptr lu;
! 1950: CF_SECTION *sp;
! 1951: int rc;
! 1952: int i;
! 1953:
! 1954: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_init\n");
! 1955: sp = istgt_find_cf_section(istgt->config, "Global");
! 1956: if (sp == NULL) {
! 1957: ISTGT_ERRLOG("find_cf_section failed()\n");
! 1958: return -1;
! 1959: }
! 1960:
! 1961: sp = istgt->config->section;
! 1962: while (sp != NULL) {
! 1963: if (sp->type == ST_LOGICAL_UNIT) {
! 1964: if (sp->num == 0) {
! 1965: ISTGT_ERRLOG("Unit 0 is invalid\n");
! 1966: return -1;
! 1967: }
! 1968: if (sp->num > ISTGT_LU_TAG_MAX) {
! 1969: ISTGT_ERRLOG("tag %d is invalid\n", sp->num);
! 1970: return -1;
! 1971: }
! 1972: rc = istgt_lu_add_unit(istgt, sp);
! 1973: if (rc < 0) {
! 1974: ISTGT_ERRLOG("lu_add_unit() failed\n");
! 1975: return -1;
! 1976: }
! 1977: }
! 1978: sp = sp->next;
! 1979: }
! 1980:
! 1981: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 1982: lu = istgt->logical_unit[i];
! 1983: if (lu == NULL)
! 1984: continue;
! 1985:
! 1986: rc = pthread_mutex_init(&lu->mutex, NULL);
! 1987: if (rc != 0) {
! 1988: ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
! 1989: return -1;
! 1990: }
! 1991: rc = pthread_mutex_init(&lu->state_mutex, NULL);
! 1992: if (rc != 0) {
! 1993: ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
! 1994: return -1;
! 1995: }
! 1996: rc = pthread_mutex_init(&lu->queue_mutex, NULL);
! 1997: if (rc != 0) {
! 1998: ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
! 1999: return -1;
! 2000: }
! 2001: rc = pthread_cond_init(&lu->queue_cond, NULL);
! 2002: if (rc != 0) {
! 2003: ISTGT_ERRLOG("LU%d: cond_init() failed\n", lu->num);
! 2004: return -1;
! 2005: }
! 2006:
! 2007: switch (lu->type) {
! 2008: case ISTGT_LU_TYPE_PASS:
! 2009: rc = istgt_lu_pass_init(istgt, lu);
! 2010: if (rc < 0) {
! 2011: ISTGT_ERRLOG("LU%d: lu_pass_init() failed\n", lu->num);
! 2012: return -1;
! 2013: }
! 2014: break;
! 2015:
! 2016: case ISTGT_LU_TYPE_DISK:
! 2017: rc = istgt_lu_disk_init(istgt, lu);
! 2018: if (rc < 0) {
! 2019: ISTGT_ERRLOG("LU%d: lu_disk_init() failed\n", lu->num);
! 2020: return -1;
! 2021: }
! 2022: break;
! 2023:
! 2024: case ISTGT_LU_TYPE_DVD:
! 2025: rc = istgt_lu_dvd_init(istgt, lu);
! 2026: if (rc < 0) {
! 2027: ISTGT_ERRLOG("LU%d: lu_dvd_init() failed\n", lu->num);
! 2028: return -1;
! 2029: }
! 2030: break;
! 2031:
! 2032: case ISTGT_LU_TYPE_TAPE:
! 2033: rc = istgt_lu_tape_init(istgt, lu);
! 2034: if (rc < 0) {
! 2035: ISTGT_ERRLOG("LU%d: lu_tape_init() failed\n", lu->num);
! 2036: return -1;
! 2037: }
! 2038: break;
! 2039:
! 2040: case ISTGT_LU_TYPE_NONE:
! 2041: //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
! 2042: break;
! 2043: default:
! 2044: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2045: return -1;
! 2046: }
! 2047:
! 2048: istgt_lu_set_state(lu, ISTGT_STATE_INITIALIZED);
! 2049: }
! 2050:
! 2051: return 0;
! 2052: }
! 2053:
! 2054: int
! 2055: istgt_lu_set_all_state(ISTGT_Ptr istgt, ISTGT_STATE state)
! 2056: {
! 2057: ISTGT_LU_Ptr lu;
! 2058: int i;
! 2059:
! 2060: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 2061: lu = istgt->logical_unit[i];
! 2062: if (lu == NULL)
! 2063: continue;
! 2064:
! 2065: istgt_lu_set_state(lu, state);
! 2066: }
! 2067:
! 2068: return 0;
! 2069: }
! 2070:
! 2071: int
! 2072: istgt_lu_create_threads(ISTGT_Ptr istgt)
! 2073: {
! 2074: #ifdef HAVE_PTHREAD_SET_NAME_NP
! 2075: char buf[MAX_TMPBUF];
! 2076: #endif
! 2077: ISTGT_LU_Ptr lu;
! 2078: int rc;
! 2079: int i;
! 2080:
! 2081: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_create_threads\n");
! 2082:
! 2083: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 2084: lu = istgt->logical_unit[i];
! 2085: if (lu == NULL)
! 2086: continue;
! 2087:
! 2088: if (lu->queue_depth != 0) {
! 2089: /* create LU thread */
! 2090: #ifdef ISTGT_STACKSIZE
! 2091: rc = pthread_create(&lu->thread, &istgt->attr, &luworker, (void *)lu);
! 2092: #else
! 2093: rc = pthread_create(&lu->thread, NULL, &luworker, (void *)lu);
! 2094: #endif
! 2095: if (rc != 0) {
! 2096: ISTGT_ERRLOG("pthread_create() failed\n");
! 2097: return -1;
! 2098: }
! 2099: #if 0
! 2100: rc = pthread_detach(lu->thread);
! 2101: if (rc != 0) {
! 2102: ISTGT_ERRLOG("pthread_detach() failed\n");
! 2103: return -1;
! 2104: }
! 2105: #endif
! 2106: #ifdef HAVE_PTHREAD_SET_NAME_NP
! 2107: snprintf(buf, sizeof buf, "luthread #%d", i);
! 2108: pthread_set_name_np(lu->thread, buf);
! 2109: #endif
! 2110: }
! 2111: }
! 2112:
! 2113: return 0;
! 2114: }
! 2115:
! 2116: int
! 2117: istgt_lu_shutdown(ISTGT_Ptr istgt)
! 2118: {
! 2119: ISTGT_LU_Ptr lu;
! 2120: int rc;
! 2121: int i;
! 2122:
! 2123: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_shutdown\n");
! 2124:
! 2125: for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
! 2126: lu = istgt->logical_unit[i];
! 2127: if (lu == NULL)
! 2128: continue;
! 2129: istgt_lu_set_state(lu, ISTGT_STATE_SHUTDOWN);
! 2130:
! 2131: switch (lu->type) {
! 2132: case ISTGT_LU_TYPE_PASS:
! 2133: rc = istgt_lu_pass_shutdown(istgt, lu);
! 2134: if (rc < 0) {
! 2135: ISTGT_ERRLOG("LU%d: lu_pass_shutdown() failed\n", lu->num);
! 2136: /* ignore error */
! 2137: }
! 2138: break;
! 2139:
! 2140: case ISTGT_LU_TYPE_DISK:
! 2141: rc = istgt_lu_disk_shutdown(istgt, lu);
! 2142: if (rc < 0) {
! 2143: ISTGT_ERRLOG("LU%d: lu_disk_shutdown() failed\n", lu->num);
! 2144: /* ignore error */
! 2145: }
! 2146: break;
! 2147:
! 2148: case ISTGT_LU_TYPE_DVD:
! 2149: rc = istgt_lu_dvd_shutdown(istgt, lu);
! 2150: if (rc < 0) {
! 2151: ISTGT_ERRLOG("LU%d: lu_dvd_shutdown() failed\n", lu->num);
! 2152: /* ignore error */
! 2153: }
! 2154: break;
! 2155:
! 2156: case ISTGT_LU_TYPE_TAPE:
! 2157: rc = istgt_lu_tape_shutdown(istgt, lu);
! 2158: if (rc < 0) {
! 2159: ISTGT_ERRLOG("LU%d: lu_tape_shutdown() failed\n", lu->num);
! 2160: /* ignore error */
! 2161: }
! 2162: break;
! 2163:
! 2164: case ISTGT_LU_TYPE_NONE:
! 2165: //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
! 2166: break;
! 2167: default:
! 2168: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2169: return -1;
! 2170: }
! 2171:
! 2172: rc = istgt_lu_del_unit(istgt, lu);
! 2173: if (rc < 0) {
! 2174: ISTGT_ERRLOG("LU%d: lu_del_unit() failed\n", lu->num);
! 2175: /* ignore error */
! 2176: }
! 2177:
! 2178: if (lu->queue_depth != 0) {
! 2179: rc = pthread_cond_broadcast(&lu->queue_cond);
! 2180: if (rc != 0) {
! 2181: ISTGT_ERRLOG("LU%d: cond_broadcast() failed\n", lu->num);
! 2182: }
! 2183: rc = pthread_join(lu->thread, NULL);
! 2184: if (rc != 0) {
! 2185: ISTGT_ERRLOG("LU%d: pthread_join() failed\n", lu->num);
! 2186: }
! 2187: }
! 2188: rc = pthread_cond_destroy(&lu->queue_cond);
! 2189: if (rc != 0) {
! 2190: ISTGT_ERRLOG("LU%d: cond_destroy() failed\n", lu->num);
! 2191: /* ignore error */
! 2192: }
! 2193: rc = pthread_mutex_destroy(&lu->queue_mutex);
! 2194: if (rc != 0) {
! 2195: ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
! 2196: /* ignore error */
! 2197: }
! 2198: rc = pthread_mutex_destroy(&lu->state_mutex);
! 2199: if (rc != 0) {
! 2200: ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
! 2201: /* ignore error */
! 2202: }
! 2203: rc = pthread_mutex_destroy(&lu->mutex);
! 2204: if (rc != 0) {
! 2205: ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
! 2206: /* ignore error */
! 2207: }
! 2208: xfree(lu);
! 2209: istgt->logical_unit[i] = NULL;
! 2210: }
! 2211:
! 2212: return 0;
! 2213: }
! 2214:
! 2215: int
! 2216: istgt_lu_islun2lun(uint64_t islun)
! 2217: {
! 2218: uint64_t fmt_lun;
! 2219: uint64_t method;
! 2220: int lun_i;
! 2221:
! 2222: fmt_lun = islun;
! 2223: method = (fmt_lun >> 62) & 0x03U;
! 2224: fmt_lun = fmt_lun >> 48;
! 2225: if (method == 0x00U) {
! 2226: lun_i = (int) (fmt_lun & 0x00ffU);
! 2227: } else if (method == 0x01U) {
! 2228: lun_i = (int) (fmt_lun & 0x3fffU);
! 2229: } else {
! 2230: lun_i = 0xffffU;
! 2231: }
! 2232: return lun_i;
! 2233: }
! 2234:
! 2235: uint64_t
! 2236: istgt_lu_lun2islun(int lun, int maxlun)
! 2237: {
! 2238: uint64_t fmt_lun;
! 2239: uint64_t method;
! 2240: uint64_t islun;
! 2241:
! 2242: islun = (uint64_t) lun;
! 2243: if (maxlun <= 0x0100) {
! 2244: /* below 256 */
! 2245: method = 0x00U;
! 2246: fmt_lun = (method & 0x03U) << 62;
! 2247: fmt_lun |= (islun & 0x00ffU) << 48;
! 2248: } else if (maxlun <= 0x4000U) {
! 2249: /* below 16384 */
! 2250: method = 0x01U;
! 2251: fmt_lun = (method & 0x03U) << 62;
! 2252: fmt_lun |= (islun & 0x3fffU) << 48;
! 2253: } else {
! 2254: /* XXX */
! 2255: fmt_lun = ~((uint64_t) 0);
! 2256: }
! 2257: return fmt_lun;
! 2258: }
! 2259:
! 2260: int
! 2261: istgt_lu_reset(ISTGT_LU_Ptr lu, uint64_t lun)
! 2262: {
! 2263: int lun_i;
! 2264: int rc;
! 2265:
! 2266: if (lu == NULL)
! 2267: return -1;
! 2268:
! 2269: lun_i = istgt_lu_islun2lun(lun);
! 2270:
! 2271: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: Name=%s, LUN=%d\n",
! 2272: lu->num, lu->name, lun_i);
! 2273:
! 2274: switch (lu->type) {
! 2275: case ISTGT_LU_TYPE_PASS:
! 2276: MTX_LOCK(&lu->mutex);
! 2277: rc = istgt_lu_pass_reset(lu, lun_i);
! 2278: MTX_UNLOCK(&lu->mutex);
! 2279: if (rc < 0) {
! 2280: ISTGT_ERRLOG("LU%d: lu_pass_reset() failed\n", lu->num);
! 2281: return -1;
! 2282: }
! 2283: break;
! 2284:
! 2285: case ISTGT_LU_TYPE_DISK:
! 2286: MTX_LOCK(&lu->mutex);
! 2287: rc = istgt_lu_disk_reset(lu, lun_i);
! 2288: MTX_UNLOCK(&lu->mutex);
! 2289: if (rc < 0) {
! 2290: ISTGT_ERRLOG("LU%d: lu_disk_reset() failed\n", lu->num);
! 2291: return -1;
! 2292: }
! 2293: break;
! 2294:
! 2295: case ISTGT_LU_TYPE_DVD:
! 2296: MTX_LOCK(&lu->mutex);
! 2297: rc = istgt_lu_dvd_reset(lu, lun_i);
! 2298: MTX_UNLOCK(&lu->mutex);
! 2299: if (rc < 0) {
! 2300: ISTGT_ERRLOG("LU%d: lu_dvd_reset() failed\n", lu->num);
! 2301: return -1;
! 2302: }
! 2303: break;
! 2304:
! 2305: case ISTGT_LU_TYPE_TAPE:
! 2306: MTX_LOCK(&lu->mutex);
! 2307: rc = istgt_lu_tape_reset(lu, lun_i);
! 2308: MTX_UNLOCK(&lu->mutex);
! 2309: if (rc < 0) {
! 2310: ISTGT_ERRLOG("LU%d: lu_tape_reset() failed\n", lu->num);
! 2311: return -1;
! 2312: }
! 2313: break;
! 2314:
! 2315: case ISTGT_LU_TYPE_NONE:
! 2316: //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
! 2317: break;
! 2318: default:
! 2319: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2320: return -1;
! 2321: }
! 2322:
! 2323: return 0;
! 2324: }
! 2325:
! 2326: int
! 2327: istgt_lu_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd)
! 2328: {
! 2329: ISTGT_LU_Ptr lu;
! 2330: int rc;
! 2331:
! 2332: if (lu_cmd == NULL)
! 2333: return -1;
! 2334: lu = lu_cmd->lu;
! 2335: if (lu == NULL)
! 2336: return -1;
! 2337:
! 2338: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
! 2339: "LU%d: PG=0x%4.4x, Name=%s, LUN=0x%16.16"PRIx64"\n",
! 2340: lu->num, conn->portal.tag, lu->name, lu_cmd->lun);
! 2341:
! 2342: if (lu->online == 0) {
! 2343: ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "LU%d: offline\n", lu->num);
! 2344: /* LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE */
! 2345: lu_cmd->sense_data_len
! 2346: = istgt_lu_scsi_build_sense_data(lu_cmd->sense_data,
! 2347: ISTGT_SCSI_SENSE_NOT_READY,
! 2348: 0x04, 0x00);
! 2349: lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
! 2350: return 0;
! 2351: }
! 2352:
! 2353: rc = 0;
! 2354: switch (lu->type) {
! 2355: case ISTGT_LU_TYPE_PASS:
! 2356: MTX_LOCK(&lu->mutex);
! 2357: rc = istgt_lu_pass_execute(conn, lu_cmd);
! 2358: MTX_UNLOCK(&lu->mutex);
! 2359: if (rc < 0) {
! 2360: ISTGT_ERRLOG("LU%d: lu_pass_execute() failed\n",
! 2361: lu->num);
! 2362: return -1;
! 2363: }
! 2364: break;
! 2365:
! 2366: case ISTGT_LU_TYPE_DISK:
! 2367: if (lu->queue_depth != 0) {
! 2368: //MTX_LOCK(&lu->queue_mutex);
! 2369: rc = istgt_lu_disk_queue(conn, lu_cmd);
! 2370: //MTX_UNLOCK(&lu->queue_mutex);
! 2371: if (rc < 0) {
! 2372: ISTGT_ERRLOG("LU%d: lu_disk_queue() failed\n",
! 2373: lu->num);
! 2374: return -1;
! 2375: }
! 2376: } else {
! 2377: MTX_LOCK(&lu->mutex);
! 2378: rc = istgt_lu_disk_execute(conn, lu_cmd);
! 2379: MTX_UNLOCK(&lu->mutex);
! 2380: if (rc < 0) {
! 2381: ISTGT_ERRLOG("LU%d: lu_disk_execute() failed\n",
! 2382: lu->num);
! 2383: return -1;
! 2384: }
! 2385: }
! 2386: break;
! 2387:
! 2388: case ISTGT_LU_TYPE_DVD:
! 2389: MTX_LOCK(&lu->mutex);
! 2390: rc = istgt_lu_dvd_execute(conn, lu_cmd);
! 2391: MTX_UNLOCK(&lu->mutex);
! 2392: if (rc < 0) {
! 2393: ISTGT_ERRLOG("LU%d: lu_dvd_execute() failed\n",
! 2394: lu->num);
! 2395: return -1;
! 2396: }
! 2397: break;
! 2398:
! 2399: case ISTGT_LU_TYPE_TAPE:
! 2400: MTX_LOCK(&lu->mutex);
! 2401: rc = istgt_lu_tape_execute(conn, lu_cmd);
! 2402: MTX_UNLOCK(&lu->mutex);
! 2403: if (rc < 0) {
! 2404: ISTGT_ERRLOG("LU%d: lu_tape_execute() failed\n",
! 2405: lu->num);
! 2406: return -1;
! 2407: }
! 2408: break;
! 2409:
! 2410: case ISTGT_LU_TYPE_NONE:
! 2411: //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
! 2412: break;
! 2413: default:
! 2414: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2415: return -1;
! 2416: }
! 2417:
! 2418: return rc;
! 2419: }
! 2420:
! 2421: int
! 2422: istgt_lu_create_task(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, ISTGT_LU_TASK_Ptr lu_task, int lun)
! 2423: {
! 2424: ISCSI_PDU_Ptr dst_pdu, src_pdu;
! 2425: uint8_t *cdb;
! 2426: int alloc_len;
! 2427: #if 0
! 2428: int rc;
! 2429: #endif
! 2430:
! 2431: if (lu_task == NULL)
! 2432: return -1;
! 2433:
! 2434: lu_task->type = ISTGT_LU_TASK_RESPONSE;
! 2435: lu_task->conn = conn;
! 2436: strncpy(lu_task->initiator_name, conn->initiator_name,
! 2437: sizeof lu_task->initiator_name);
! 2438: strncpy(lu_task->initiator_port, conn->initiator_port,
! 2439: sizeof lu_task->initiator_port);
! 2440:
! 2441: lu_task->lun = (int) lun;
! 2442: lu_task->use_cond = 0;
! 2443: lu_task->dup_iobuf = 0;
! 2444: lu_task->iobuf = NULL;
! 2445: lu_task->data = NULL;
! 2446: lu_task->sense_data = NULL;
! 2447: lu_task->create_time = 0;
! 2448: lu_task->condwait = 0;
! 2449: lu_task->offset = 0;
! 2450: lu_task->req_execute = 0;
! 2451: lu_task->req_transfer_out = 0;
! 2452: lu_task->error = 0;
! 2453: lu_task->abort = 0;
! 2454: lu_task->execute = 0;
! 2455: lu_task->complete = 0;
! 2456: lu_task->lock = 0;
! 2457:
! 2458: #if 0
! 2459: rc = pthread_mutex_init(&lu_task->trans_mutex, NULL);
! 2460: if (rc != 0) {
! 2461: ISTGT_ERRLOG("mutex_init() failed\n");
! 2462: return -1;
! 2463: }
! 2464: rc = pthread_cond_init(&lu_task->trans_cond, NULL);
! 2465: if (rc != 0) {
! 2466: ISTGT_ERRLOG("cond_init() failed\n");
! 2467: return -1;
! 2468: }
! 2469: rc = pthread_cond_init(&lu_task->exec_cond, NULL);
! 2470: if (rc != 0) {
! 2471: ISTGT_ERRLOG("cond_init() failed\n");
! 2472: return -1;
! 2473: }
! 2474: #endif
! 2475:
! 2476: lu_task->lu_cmd.pdu = xmalloc(sizeof *lu_task->lu_cmd.pdu);
! 2477: memset(lu_task->lu_cmd.pdu, 0, sizeof *lu_task->lu_cmd.pdu);
! 2478:
! 2479: /* copy PDU */
! 2480: dst_pdu = lu_task->lu_cmd.pdu;
! 2481: src_pdu = lu_cmd->pdu;
! 2482: memcpy(&dst_pdu->bhs, &src_pdu->bhs, ISCSI_BHS_LEN);
! 2483: dst_pdu->ahs = src_pdu->ahs;
! 2484: memcpy(dst_pdu->header_digest, src_pdu->header_digest, ISCSI_DIGEST_LEN);
! 2485: if (src_pdu->data == src_pdu->shortdata) {
! 2486: memcpy(dst_pdu->shortdata, src_pdu->shortdata,
! 2487: sizeof src_pdu->shortdata);
! 2488: dst_pdu->data = dst_pdu->shortdata;
! 2489: } else {
! 2490: dst_pdu->data = src_pdu->data;
! 2491: }
! 2492: memcpy(dst_pdu->data_digest, src_pdu->data_digest, ISCSI_DIGEST_LEN);
! 2493: dst_pdu->total_ahs_len = src_pdu->total_ahs_len;
! 2494: dst_pdu->data_segment_len = src_pdu->data_segment_len;
! 2495: dst_pdu->copy_pdu = 0;
! 2496: src_pdu->copy_pdu = 1;
! 2497:
! 2498: /* copy other lu_cmd */
! 2499: lu_task->lu_cmd.lu = lu_cmd->lu;
! 2500: cdb = ((uint8_t *) &lu_task->lu_cmd.pdu->bhs) + 32;
! 2501: lu_task->lu_cmd.I_bit = lu_cmd->I_bit;
! 2502: lu_task->lu_cmd.F_bit = lu_cmd->F_bit;
! 2503: lu_task->lu_cmd.R_bit = lu_cmd->R_bit;
! 2504: lu_task->lu_cmd.W_bit = lu_cmd->W_bit;
! 2505: lu_task->lu_cmd.Attr_bit = lu_cmd->Attr_bit;
! 2506: lu_task->lu_cmd.lun = lu_cmd->lun;
! 2507: lu_task->lu_cmd.task_tag = lu_cmd->task_tag;
! 2508: lu_task->lu_cmd.transfer_len = lu_cmd->transfer_len;
! 2509: //lu_task->lu_cmd.cdb = lu_cmd->cdb;
! 2510: lu_task->lu_cmd.cdb = cdb;
! 2511: lu_task->lu_cmd.CmdSN = lu_cmd->CmdSN;
! 2512:
! 2513: //lu_task->lu_cmd.iobuf = lu_cmd->iobuf;
! 2514: lu_task->lu_cmd.iobuf = NULL;
! 2515: lu_task->lu_cmd.iobufsize = lu_cmd->iobufsize;
! 2516: lu_task->lu_cmd.data = lu_cmd->data;
! 2517: lu_task->lu_cmd.data_len = lu_cmd->data_len;
! 2518: lu_task->lu_cmd.alloc_len = lu_cmd->alloc_len;
! 2519:
! 2520: lu_task->lu_cmd.status = lu_cmd->status;
! 2521: lu_task->lu_cmd.sense_data = lu_cmd->sense_data;
! 2522: lu_task->lu_cmd.sense_data_len = lu_cmd->sense_data_len;
! 2523: lu_task->lu_cmd.sense_alloc_len = lu_cmd->sense_alloc_len;
! 2524:
! 2525: /* pre allocate buffer */
! 2526: lu_task->lu_cmd.iobufsize = lu_cmd->transfer_len + 65536;
! 2527: #if 0
! 2528: lu_task->data = xmalloc(lu_cmd->alloc_len);
! 2529: lu_task->sense_data = xmalloc(lu_cmd->sense_alloc_len);
! 2530: lu_task->iobuf = xmalloc(lu_task->lu_cmd.iobufsize);
! 2531: #else
! 2532: alloc_len = ISCSI_ALIGN(lu_cmd->alloc_len);
! 2533: alloc_len += ISCSI_ALIGN(lu_cmd->sense_alloc_len);
! 2534: alloc_len += ISCSI_ALIGN(lu_task->lu_cmd.iobufsize);
! 2535: lu_task->data = xmalloc(alloc_len);
! 2536: lu_task->sense_data = lu_task->data + ISCSI_ALIGN(lu_cmd->alloc_len);
! 2537: lu_task->iobuf = lu_task->sense_data + ISCSI_ALIGN(lu_cmd->sense_alloc_len);
! 2538: #endif
! 2539:
! 2540: /* creation time */
! 2541: lu_task->create_time = time(NULL);
! 2542: /* wait time */
! 2543: lu_task->condwait = conn->timeout * 1000;
! 2544: if (lu_task->condwait < ISTGT_CONDWAIT_MIN) {
! 2545: lu_task->condwait = ISTGT_CONDWAIT_MIN;
! 2546: }
! 2547:
! 2548: return 0;
! 2549: }
! 2550:
! 2551: int
! 2552: istgt_lu_destroy_task(ISTGT_LU_TASK_Ptr lu_task)
! 2553: {
! 2554: int rc;
! 2555:
! 2556: if (lu_task == NULL)
! 2557: return -1;
! 2558:
! 2559: if (lu_task->use_cond != 0) {
! 2560: rc = pthread_mutex_destroy(&lu_task->trans_mutex);
! 2561: if (rc != 0) {
! 2562: ISTGT_ERRLOG("mutex_destroy() failed\n");
! 2563: return -1;
! 2564: }
! 2565: rc = pthread_cond_destroy(&lu_task->trans_cond);
! 2566: if (rc != 0) {
! 2567: ISTGT_ERRLOG("cond_destroy() failed\n");
! 2568: return -1;
! 2569: }
! 2570: rc = pthread_cond_destroy(&lu_task->exec_cond);
! 2571: if (rc != 0) {
! 2572: ISTGT_ERRLOG("cond_destroy() failed\n");
! 2573: return -1;
! 2574: }
! 2575: }
! 2576: if (lu_task->lu_cmd.pdu != NULL) {
! 2577: if (lu_task->lu_cmd.pdu->copy_pdu == 0) {
! 2578: xfree(lu_task->lu_cmd.pdu->ahs);
! 2579: if (lu_task->lu_cmd.pdu->data
! 2580: != lu_task->lu_cmd.pdu->shortdata) {
! 2581: xfree(lu_task->lu_cmd.pdu->data);
! 2582: }
! 2583: }
! 2584: xfree(lu_task->lu_cmd.pdu);
! 2585: }
! 2586: #if 0
! 2587: if (lu_task->dup_iobuf == 0) {
! 2588: xfree(lu_task->iobuf);
! 2589: }
! 2590: xfree(lu_task->data);
! 2591: xfree(lu_task->sense_data);
! 2592: #else
! 2593: xfree(lu_task->data);
! 2594: #endif
! 2595: xfree(lu_task);
! 2596: return 0;
! 2597: }
! 2598:
! 2599: int
! 2600: istgt_lu_clear_task_IT(CONN_Ptr conn, ISTGT_LU_Ptr lu)
! 2601: {
! 2602: int rc;
! 2603:
! 2604: if (lu == NULL)
! 2605: return -1;
! 2606:
! 2607: if (lu->queue_depth == 0)
! 2608: return 0;
! 2609:
! 2610: rc = 0;
! 2611: switch (lu->type) {
! 2612: case ISTGT_LU_TYPE_DISK:
! 2613: MTX_LOCK(&lu->mutex);
! 2614: rc = istgt_lu_disk_queue_clear_IT(conn, lu);
! 2615: MTX_UNLOCK(&lu->mutex);
! 2616: if (rc < 0) {
! 2617: ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_IT() failed\n", lu->num);
! 2618: return -1;
! 2619: }
! 2620: break;
! 2621:
! 2622: case ISTGT_LU_TYPE_DVD:
! 2623: case ISTGT_LU_TYPE_TAPE:
! 2624: case ISTGT_LU_TYPE_NONE:
! 2625: default:
! 2626: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2627: return -1;
! 2628: }
! 2629:
! 2630: return 0;
! 2631: }
! 2632:
! 2633: int
! 2634: istgt_lu_clear_task_ITL(CONN_Ptr conn, ISTGT_LU_Ptr lu, uint64_t lun)
! 2635: {
! 2636: int lun_i;
! 2637: int rc;
! 2638:
! 2639: if (lu == NULL)
! 2640: return -1;
! 2641:
! 2642: if (lu->queue_depth == 0)
! 2643: return 0;
! 2644:
! 2645: lun_i = istgt_lu_islun2lun(lun);
! 2646:
! 2647: rc = 0;
! 2648: switch (lu->type) {
! 2649: case ISTGT_LU_TYPE_DISK:
! 2650: MTX_LOCK(&lu->mutex);
! 2651: rc = istgt_lu_disk_queue_clear_ITL(conn, lu, lun_i);
! 2652: MTX_UNLOCK(&lu->mutex);
! 2653: if (rc < 0) {
! 2654: ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_ITL() failed\n", lu->num);
! 2655: return -1;
! 2656: }
! 2657: break;
! 2658:
! 2659: case ISTGT_LU_TYPE_DVD:
! 2660: case ISTGT_LU_TYPE_TAPE:
! 2661: case ISTGT_LU_TYPE_NONE:
! 2662: default:
! 2663: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2664: return -1;
! 2665: }
! 2666:
! 2667: return 0;
! 2668: }
! 2669:
! 2670: int
! 2671: istgt_lu_clear_task_ITLQ(CONN_Ptr conn, ISTGT_LU_Ptr lu, uint64_t lun, uint32_t CmdSN)
! 2672: {
! 2673: int lun_i;
! 2674: int rc;
! 2675:
! 2676: if (lu == NULL)
! 2677: return -1;
! 2678:
! 2679: if (lu->queue_depth == 0)
! 2680: return 0;
! 2681:
! 2682: lun_i = istgt_lu_islun2lun(lun);
! 2683:
! 2684: rc = 0;
! 2685: switch (lu->type) {
! 2686: case ISTGT_LU_TYPE_DISK:
! 2687: MTX_LOCK(&lu->mutex);
! 2688: rc = istgt_lu_disk_queue_clear_ITLQ(conn, lu, lun_i, CmdSN);
! 2689: MTX_UNLOCK(&lu->mutex);
! 2690: if (rc < 0) {
! 2691: ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_ITLQ() failed\n", lu->num);
! 2692: return -1;
! 2693: }
! 2694: break;
! 2695:
! 2696: case ISTGT_LU_TYPE_DVD:
! 2697: case ISTGT_LU_TYPE_TAPE:
! 2698: case ISTGT_LU_TYPE_NONE:
! 2699: default:
! 2700: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2701: return -1;
! 2702: }
! 2703:
! 2704: return 0;
! 2705: }
! 2706:
! 2707: int
! 2708: istgt_lu_clear_all_task(ISTGT_LU_Ptr lu, uint64_t lun)
! 2709: {
! 2710: int rc;
! 2711:
! 2712: if (lu == NULL)
! 2713: return -1;
! 2714:
! 2715: if (lu->queue_depth == 0)
! 2716: return 0;
! 2717:
! 2718: rc = 0;
! 2719: switch (lu->type) {
! 2720: case ISTGT_LU_TYPE_DISK:
! 2721: MTX_LOCK(&lu->mutex);
! 2722: rc = istgt_lu_disk_queue_clear_all(lu, lun);
! 2723: MTX_UNLOCK(&lu->mutex);
! 2724: if (rc < 0) {
! 2725: ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_all() failed\n", lu->num);
! 2726: return -1;
! 2727: }
! 2728: break;
! 2729:
! 2730: case ISTGT_LU_TYPE_DVD:
! 2731: case ISTGT_LU_TYPE_TAPE:
! 2732: case ISTGT_LU_TYPE_NONE:
! 2733: default:
! 2734: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2735: return -1;
! 2736: }
! 2737:
! 2738: return 0;
! 2739: }
! 2740:
! 2741: static void *
! 2742: luworker(void *arg)
! 2743: {
! 2744: ISTGT_LU_Ptr lu = (ISTGT_LU_Ptr) arg;
! 2745: sigset_t signew, sigold;
! 2746: #if 0
! 2747: struct timespec abstime;
! 2748: time_t now;
! 2749: int timeout = 20; /* XXX */
! 2750: #endif
! 2751: int qcnt;
! 2752: int lun;
! 2753: int rc;
! 2754:
! 2755: sigemptyset(&signew);
! 2756: sigemptyset(&sigold);
! 2757: sigaddset(&signew, ISTGT_SIGWAKEUP);
! 2758: pthread_sigmask(SIG_UNBLOCK, &signew, &sigold);
! 2759:
! 2760: while (istgt_get_state(lu->istgt) != ISTGT_STATE_RUNNING) {
! 2761: if (istgt_get_state(lu->istgt) == ISTGT_STATE_EXITING
! 2762: || istgt_get_state(lu->istgt) == ISTGT_STATE_SHUTDOWN) {
! 2763: ISTGT_ERRLOG("exit before running\n");
! 2764: return NULL;
! 2765: }
! 2766: //ISTGT_WARNLOG("Wait for running\n");
! 2767: sleep(1);
! 2768: continue;
! 2769: }
! 2770:
! 2771: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d loop start\n", lu->num);
! 2772: lun = 0;
! 2773: qcnt = 0;
! 2774: #if 0
! 2775: memset(&abstime, 0, sizeof abstime);
! 2776: #endif
! 2777: while (1) {
! 2778: switch (lu->type) {
! 2779: case ISTGT_LU_TYPE_DISK:
! 2780: while (1) {
! 2781: if (istgt_lu_get_state(lu) != ISTGT_STATE_RUNNING) {
! 2782: goto loop_exit;
! 2783: }
! 2784: MTX_LOCK(&lu->queue_mutex);
! 2785: qcnt = istgt_lu_disk_queue_count(lu, &lun);
! 2786: if (qcnt == 0) {
! 2787: #if 0
! 2788: now = time(NULL);
! 2789: abstime.tv_sec = now + timeout;
! 2790: abstime.tv_nsec = 0;
! 2791: rc = pthread_cond_timedwait(&lu->queue_cond,
! 2792: &lu->queue_mutex, &abstime);
! 2793: if (rc == ETIMEDOUT) {
! 2794: /* nothing */
! 2795: }
! 2796: #else
! 2797: pthread_cond_wait(&lu->queue_cond,
! 2798: &lu->queue_mutex);
! 2799: #endif
! 2800: qcnt = istgt_lu_disk_queue_count(lu, &lun);
! 2801: if (qcnt == 0) {
! 2802: MTX_UNLOCK(&lu->queue_mutex);
! 2803: continue;
! 2804: }
! 2805: }
! 2806: MTX_UNLOCK(&lu->queue_mutex);
! 2807: break;
! 2808: }
! 2809: if (qcnt < 0) {
! 2810: ISTGT_ERRLOG("LU%d: lu_disk_queue_count() failed\n",
! 2811: lu->num);
! 2812: break;
! 2813: }
! 2814: rc = istgt_lu_disk_queue_start(lu, lun);
! 2815: lun++;
! 2816: if (rc == -2) {
! 2817: ISTGT_WARNLOG("LU%d: lu_disk_queue_start() aborted\n",
! 2818: lu->num);
! 2819: break;
! 2820: }
! 2821: if (rc < 0) {
! 2822: ISTGT_ERRLOG("LU%d: lu_disk_queue_start() failed\n",
! 2823: lu->num);
! 2824: break;
! 2825: }
! 2826: break;
! 2827:
! 2828: case ISTGT_LU_TYPE_DVD:
! 2829: case ISTGT_LU_TYPE_TAPE:
! 2830: case ISTGT_LU_TYPE_NONE:
! 2831: default:
! 2832: ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
! 2833: return NULL;
! 2834: }
! 2835:
! 2836: #if 0
! 2837: /* still running? */
! 2838: if (qcnt <= 1) {
! 2839: if (istgt_lu_get_state(lu) != ISTGT_STATE_RUNNING) {
! 2840: goto loop_exit;
! 2841: }
! 2842: }
! 2843: #endif
! 2844: }
! 2845: loop_exit:
! 2846: ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d loop ended\n", lu->num);
! 2847:
! 2848: return NULL;
! 2849: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>