Annotation of embedaddon/istgt/src/istgt_lu.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
1.1       misho       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;
1.1.1.2 ! misho      85:        size_t n;
1.1       misho      86:        int bits, bmask;
                     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;
1.1.1.2 ! misho     144:        size_t n;
1.1       misho     145:        int bits;
                    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: 
1.1.1.2 ! misho     323: static int
        !           324: istgt_pg_visible(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu, const char *iqn, int pg_tag)
        !           325: {
        !           326:        INITIATOR_GROUP *igp;
        !           327:        int match_idx;
        !           328:        int ig_tag;
        !           329:        int i, j;
        !           330: 
        !           331:        if (istgt == NULL || lu == NULL || iqn == NULL)
        !           332:                return 0;
        !           333:        match_idx = -1;
        !           334:        for (i = 0; i < lu->maxmap; i++) {
        !           335:                if (lu->map[i].pg_tag == pg_tag) {
        !           336:                        match_idx = i;
        !           337:                        break;
        !           338:                }
        !           339:        }
        !           340:        if (match_idx < 0) {
        !           341:                /* cant't find pg_tag */
        !           342:                return 0;
        !           343:        }
        !           344: 
        !           345:        /* iqn is initiator group? */
        !           346:        ig_tag = lu->map[match_idx].ig_tag;
        !           347:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "iqn=%s, pg=%d, ig=%d\n", iqn, pg_tag, ig_tag);
        !           348:        igp = istgt_lu_find_initiatorgroup(istgt, ig_tag);
        !           349:        if (igp == NULL) {
        !           350:                ISTGT_ERRLOG("LU%d: ig_tag not found\n", lu->num);
        !           351:                return 0;
        !           352:        }
        !           353:        for (j = 0; j < igp->ninitiators; j++) {
        !           354:                if (igp->initiators[j][0] == '!'
        !           355:                    && (strcasecmp(&igp->initiators[j][1], "ALL") == 0
        !           356:                        || strcasecmp(&igp->initiators[j][1], iqn) == 0)) {
        !           357:                        /* NG */
        !           358:                        return 0;
        !           359:                }
        !           360:                if (strcasecmp(igp->initiators[j], "ALL") == 0
        !           361:                    || strcasecmp(igp->initiators[j], iqn) == 0) {
        !           362:                        /* OK iqn, no check addr */
        !           363:                        return 1;
        !           364:                }
        !           365:        }
        !           366: 
        !           367:        /* NG */
        !           368:        return 0;
        !           369: }
        !           370: 
1.1       misho     371: int
                    372: istgt_lu_sendtargets(CONN_Ptr conn, const char *iiqn, const char *iaddr, const char *tiqn, uint8_t *data, int alloc_len, int data_len)
                    373: {
                    374:        char buf[MAX_TMPBUF];
                    375:        ISTGT_Ptr istgt;
                    376:        ISTGT_LU_Ptr lu;
                    377:        char *host;
                    378:        int total;
                    379:        int len;
                    380:        int rc;
                    381:        int pg_tag;
1.1.1.2 ! misho     382:        int i, j, k, l;
1.1       misho     383: 
                    384:        if (conn == NULL)
                    385:                return 0;
                    386:        istgt = conn->istgt;
                    387: 
                    388:        total = data_len;
                    389:        if (alloc_len < 1) {
                    390:                return 0;
                    391:        }
                    392:        if (total > alloc_len) {
                    393:                total = alloc_len;
                    394:                data[total - 1] = '\0';
                    395:                return total;
                    396:        }
                    397: 
                    398:        if (alloc_len - total < 1) {
                    399:                ISTGT_ERRLOG("data space small %d\n", alloc_len);
                    400:                return total;
                    401:        }
                    402: 
                    403:        MTX_LOCK(&istgt->mutex);
                    404:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
                    405:                lu = istgt->logical_unit[i];
                    406:                if (lu == NULL)
                    407:                        continue;
                    408:                if (strcasecmp(tiqn, "ALL") != 0
                    409:                        && strcasecmp(tiqn, lu->name) != 0) {
                    410:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    411:                            "SKIP iqn=%s for %s from %s (%s)\n",
                    412:                            tiqn, lu->name, iiqn, iaddr);
                    413:                        continue;
                    414:                }
                    415:                rc = istgt_lu_visible(istgt, lu, iiqn, conn->portal.tag);
                    416:                if (rc == 0) {
                    417:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    418:                            "SKIP iqn=%s for %s from %s (%s)\n",
                    419:                            tiqn, lu->name, iiqn, iaddr);
                    420:                        continue;
                    421:                }
                    422: 
                    423:                /* DO SENDTARGETS */
                    424:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    425:                    "OK iqn=%s for %s from %s (%s)\n",
                    426:                    tiqn, lu->name, iiqn, iaddr);
                    427: 
                    428:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    429:                    "TargetName=%s\n", lu->name);
                    430:                len = snprintf((char *) data + total, alloc_len - total,
                    431:                    "TargetName=%s", lu->name);
                    432:                total += len + 1;
                    433: 
                    434:                for (j = 0; j < lu->maxmap; j++) {
                    435:                        pg_tag = lu->map[j].pg_tag;
                    436:                        /* skip same pg_tag */
                    437:                        for (k = 0; k < j; k++) {
                    438:                                if (lu->map[k].pg_tag == pg_tag) {
                    439:                                        goto skip_pg_tag;
                    440:                                }
                    441:                        }
1.1.1.2 ! misho     442:                        rc = istgt_pg_visible(istgt, lu, iiqn, pg_tag);
        !           443:                        if (rc == 0) {
        !           444:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
        !           445:                                    "SKIP pg=%d, iqn=%s for %s from %s (%s)\n",
        !           446:                                    pg_tag, tiqn, lu->name, iiqn, iaddr);
        !           447:                                goto skip_pg_tag;
        !           448:                        }
        !           449: 
1.1       misho     450:                        /* write to data */
1.1.1.2 ! misho     451:                        for (k = 0; k < istgt->nportal_group; k++) {
        !           452:                                if (istgt->portal_group[k].tag != pg_tag)
        !           453:                                        continue;
        !           454:                                for (l = 0; l < istgt->portal_group[k].nportals; l++) {
1.1       misho     455:                                        if (alloc_len - total < 1) {
                    456:                                                MTX_UNLOCK(&istgt->mutex);
1.1.1.2 ! misho     457:                                                ISTGT_ERRLOG("data space small %d\n",
        !           458:                                                    alloc_len);
1.1       misho     459:                                                return total;
                    460:                                        }
1.1.1.2 ! misho     461:                                        host = istgt->portal_group[k].portals[l]->host;
1.1       misho     462:                                        /* wildcard? */
                    463:                                        if (strcasecmp(host, "[::]") == 0
                    464:                                            || strcasecmp(host, "[*]") == 0
                    465:                                            || strcasecmp(host, "0.0.0.0") == 0
                    466:                                            || strcasecmp(host, "*") == 0) {
                    467:                                                if ((strcasecmp(host, "[::]") == 0
                    468:                                                        || strcasecmp(host, "[*]") == 0)
                    469:                                                    && conn->initiator_family == AF_INET6) {
                    470:                                                        snprintf(buf, sizeof buf, "[%s]",
                    471:                                                            conn->target_addr);
                    472:                                                        host = buf;
                    473:                                                } else if ((strcasecmp(host, "0.0.0.0") == 0
                    474:                                                        || strcasecmp(host, "*") == 0)
                    475:                                                    && conn->initiator_family == AF_INET) {
                    476:                                                        snprintf(buf, sizeof buf, "%s",
                    477:                                                            conn->target_addr);
                    478:                                                        host = buf;
                    479:                                                } else {
                    480:                                                        /* skip portal for the family */
                    481:                                                        continue;
                    482:                                                }
                    483:                                        }
                    484:                                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    485:                                            "TargetAddress=%s:%s,%d\n",
                    486:                                            host,
1.1.1.2 ! misho     487:                                            istgt->portal_group[k].portals[l]->port,
        !           488:                                            istgt->portal_group[k].portals[l]->tag);
1.1       misho     489:                                        len = snprintf((char *) data + total,
                    490:                                            alloc_len - total,
                    491:                                            "TargetAddress=%s:%s,%d",
                    492:                                            host,
1.1.1.2 ! misho     493:                                            istgt->portal_group[k].portals[l]->port,
        !           494:                                            istgt->portal_group[k].portals[l]->tag);
1.1       misho     495:                                        total += len + 1;
                    496:                                }
                    497:                        }
                    498:                skip_pg_tag:
                    499:                        ;
                    500:                }
                    501:        }
                    502:        MTX_UNLOCK(&istgt->mutex);
                    503: 
                    504:        return total;
                    505: }
                    506: 
                    507: ISTGT_LU_Ptr
                    508: istgt_lu_find_target(ISTGT_Ptr istgt, const char *target_name)
                    509: {
                    510:        ISTGT_LU_Ptr lu;
                    511:        int i;
                    512: 
                    513:        if (istgt == NULL || target_name == NULL)
                    514:                return NULL;
                    515:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
                    516:                lu = istgt->logical_unit[i];
                    517:                if (lu == NULL)
                    518:                        continue;
                    519:                if (strcasecmp(target_name, lu->name) == 0) {
                    520:                        return lu;
                    521:                }
                    522:        }
                    523:        ISTGT_WARNLOG("can't find target %s\n",
                    524:            target_name);
                    525:        return NULL;
                    526: }
                    527: 
                    528: uint16_t
                    529: istgt_lu_allocate_tsih(ISTGT_LU_Ptr lu, const char *initiator_port, int tag)
                    530: {
                    531:        uint16_t tsih;
                    532:        int retry = 10;
                    533:        int i;
                    534: 
                    535:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_allocate_tsih\n");
                    536:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "initiator_port=%s, tag=%d\n",
                    537:            initiator_port, tag);
                    538:        if (lu == NULL || initiator_port == NULL || tag == 0)
                    539:                return 0;
                    540:        /* tsih 0 is reserved */
                    541:        tsih = 0;
                    542:        MTX_LOCK(&lu->mutex);
                    543: #if 0
                    544:        for (i = 1; i < MAX_LU_TSIH; i++) {
                    545:                if (lu->tsih[i].initiator_port == NULL)
                    546:                        continue;
                    547:                if (tag != lu->tsih[i].tag)
                    548:                        continue;
                    549:                if (strcasecmp(initiator_port, lu->tsih[i].initiator_port) == 0) {
                    550:                        tsih = lu->tsih[i].tsih;
                    551:                        break;
                    552:                }
                    553:        }
                    554: #endif
                    555:        if (tsih == 0) {
                    556:                if (lu->maxtsih >= MAX_LU_TSIH) {
                    557:                        ISTGT_ERRLOG("LU%d: tsih is maximum\n", lu->num);
                    558:                        MTX_UNLOCK(&lu->mutex);
                    559:                        return 0;
                    560:                }
                    561:        retry:
                    562:                lu->last_tsih++;
                    563:                tsih = lu->last_tsih;
                    564:                if (tsih == 0) {
                    565:                        if (retry > 0) {
                    566:                                retry--;
                    567:                                goto retry;
                    568:                        }
                    569:                        ISTGT_ERRLOG("LU%d: retry error\n", lu->num);
                    570:                        MTX_UNLOCK(&lu->mutex);
                    571:                        return 0;
                    572:                }
                    573:                for (i = 1; i < MAX_LU_TSIH; i++) {
                    574:                        if (lu->tsih[i].initiator_port != NULL
                    575:                                && lu->tsih[i].tsih == tsih) {
                    576:                                ISTGT_ERRLOG("tsih is found in list\n");
                    577:                                if (retry > 0) {
                    578:                                        retry--;
                    579:                                        goto retry;
                    580:                                }
                    581:                                ISTGT_ERRLOG("LU%d: retry error\n", lu->num);
                    582:                                MTX_UNLOCK(&lu->mutex);
                    583:                                return 0;
                    584:                        }
                    585:                }
                    586:                for (i = 1; i < MAX_LU_TSIH; i++) {
                    587:                        if (lu->tsih[i].initiator_port == NULL) {
                    588:                                lu->tsih[i].tag = tag;
                    589:                                lu->tsih[i].tsih = tsih;
                    590:                                lu->tsih[i].initiator_port = xstrdup(initiator_port);
                    591:                                lu->maxtsih++;
                    592:                                break;
                    593:                        }
                    594:                }
                    595:        }
                    596:        MTX_UNLOCK(&lu->mutex);
                    597:        return tsih;
                    598: }
                    599: 
                    600: void
                    601: istgt_lu_free_tsih(ISTGT_LU_Ptr lu, uint16_t tsih, char *initiator_port)
                    602: {
                    603:        int i;
                    604: 
                    605:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_free_tsih\n");
                    606:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "tsih=%u, initiator_port=%s\n",
                    607:            tsih, initiator_port);
                    608:        if (lu == NULL || initiator_port == NULL)
                    609:                return;
                    610:        if (tsih == 0)
                    611:                return;
                    612: 
                    613:        MTX_LOCK(&lu->mutex);
                    614:        for (i = 1; i < MAX_LU_TSIH; i++) {
                    615:                if (lu->tsih[i].initiator_port == NULL)
                    616:                        continue;
                    617:                if (lu->tsih[i].tsih != tsih)
                    618:                        continue;
                    619: 
                    620:                if (strcasecmp(initiator_port, lu->tsih[i].initiator_port) == 0) {
                    621:                        lu->tsih[i].tag = 0;
                    622:                        lu->tsih[i].tsih = 0;
                    623:                        xfree(lu->tsih[i].initiator_port);
                    624:                        lu->tsih[i].initiator_port = NULL;
                    625:                        lu->maxtsih--;
                    626:                        break;
                    627:                }
                    628:        }
                    629:        MTX_UNLOCK(&lu->mutex);
                    630:        return;
                    631: }
                    632: 
                    633: char *
                    634: istgt_lu_get_media_flags_string(int flags, char *buf, size_t len)
                    635: {
                    636:        char *p;
                    637:        size_t rest;
                    638: 
                    639:        p = buf;
                    640:        rest = len;
                    641:        if (flags & ISTGT_LU_FLAG_MEDIA_READONLY) {
                    642:                snprintf(p, rest, "%s", "ro");
                    643:        } else {
                    644:                snprintf(p, rest, "%s", "rw");
                    645:        }
                    646:        p = buf + strlen(buf);
                    647:        rest = len - strlen(buf);
                    648:        if (flags & ISTGT_LU_FLAG_MEDIA_EXTEND) {
                    649:                snprintf(p, rest, ",%s", "extend");
                    650:        }
                    651:        p = buf + strlen(buf);
                    652:        rest = len - strlen(buf);
                    653:        if (flags & ISTGT_LU_FLAG_MEDIA_DYNAMIC) {
                    654:                snprintf(p, rest, ",%s", "dynamic");
                    655:        }
                    656:        return buf;
                    657: }
                    658: 
                    659: uint64_t
                    660: istgt_lu_get_devsize(const char *file)
                    661: {
                    662:        uint64_t val;
                    663:        struct stat st;
                    664:        int fd;
                    665:        int rc;
                    666: 
                    667:        val = 0ULL;
1.1.1.2 ! misho     668: #ifdef ALLOW_SYMLINK_DEVICE
        !           669:        rc = stat(file, &st);
        !           670: #else
1.1       misho     671:        rc = lstat(file, &st);
1.1.1.2 ! misho     672: #endif /* ALLOW_SYMLINK_DEVICE */
1.1       misho     673:        if (rc != 0)
                    674:                return val;
                    675:        if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode))
                    676:                return val;
                    677: 
                    678:        fd = open(file, O_RDONLY, 0);
                    679:        if (fd >= 0) {
                    680: #ifdef DIOCGMEDIASIZE
                    681:                if (val == 0) {
                    682:                        off_t offset;
                    683:                        rc = ioctl(fd, DIOCGMEDIASIZE, &offset);
                    684:                        if (rc != -1) {
                    685:                                val = (uint64_t) offset;
                    686:                        }
                    687:                }
                    688: #endif /* DIOCGMEDIASIZE */
                    689: #ifdef DIOCGDINFO
                    690:                if (val == 0) {
                    691:                        struct disklabel dl;
                    692:                        rc = ioctl(fd, DIOCGDINFO, &dl);
                    693:                        if (rc != -1) {
                    694:                                val = (uint64_t) dl.d_secperunit;
                    695:                                val *= (uint64_t) dl.d_secsize;
                    696:                        }
                    697:                }
                    698: #endif /* DIOCGDINFO */
                    699: #if defined(DKIOCGETBLOCKSIZE) && defined(DKIOCGETBLOCKCOUNT)
                    700:                if (val == 0) {
                    701:                        uint32_t blocklen;
                    702:                        uint64_t blockcnt;
                    703:                        rc = ioctl(fd, DKIOCGETBLOCKSIZE, &blocklen);
                    704:                        if (rc != -1) {
                    705:                                rc = ioctl(fd, DKIOCGETBLOCKCOUNT, &blockcnt);
                    706:                                if (rc != -1) {
                    707:                                        val = (uint64_t) blocklen;
                    708:                                        val *= (uint64_t) blockcnt;
                    709:                                }
                    710:                        }
                    711:                }
                    712: #endif /* DKIOCGETBLOCKSIZE && DKIOCGETBLOCKCOUNT */
                    713: #ifdef __linux__
                    714: #ifdef BLKGETSIZE64
                    715:                if (val == 0) {
                    716:                        uint64_t blocksize;
                    717:                        rc = ioctl(fd, BLKGETSIZE64, &blocksize);
                    718:                        if (rc != -1) {
                    719:                                val = (uint64_t) blocksize;
                    720:                        }
                    721:                }
                    722: #endif /* BLKGETSIZE64 */
                    723: #ifdef BLKGETSIZE
                    724:                if (val == 0) {
                    725:                        uint32_t blocksize;
                    726:                        rc = ioctl(fd, BLKGETSIZE, &blocksize);
                    727:                        if (rc != -1) {
                    728:                                val = (uint64_t) 512;
                    729:                                val *= (uint64_t) blocksize;
                    730:                        }
                    731:                }
                    732: #endif /* BLKGETSIZE */
                    733: #endif /* __linux__ */
                    734:                if (val == 0) {
                    735:                        ISTGT_ERRLOG("unknown device size\n");
                    736:                }
                    737:                (void) close(fd);
                    738:        } else {
                    739:                if (g_trace_flag) {
                    740:                        ISTGT_WARNLOG("open error %s (errno=%d)\n", file, errno);
                    741:                }
                    742:                val = 0ULL;
                    743:        }
                    744:        return val;
                    745: }
                    746: 
                    747: uint64_t
                    748: istgt_lu_get_filesize(const char *file)
                    749: {
                    750:        uint64_t val;
                    751:        struct stat st;
                    752:        int rc;
                    753: 
                    754:        val = 0ULL;
1.1.1.2 ! misho     755: #ifdef ALLOW_SYMLINK_DEVICE
        !           756:        rc = stat(file, &st);
        !           757: #else
1.1       misho     758:        rc = lstat(file, &st);
1.1.1.2 ! misho     759: #endif /* ALLOW_SYMLINK_DEVICE */
        !           760: 
1.1       misho     761:        if (rc < 0)
                    762:                return val;
1.1.1.2 ! misho     763: #ifndef ALLOW_SYMLINK_DEVICE
1.1       misho     764:        if (S_ISLNK(st.st_mode))
                    765:                return val;
1.1.1.2 ! misho     766: #endif /* ALLOW_SYMLINK_DEVICE */
1.1       misho     767: 
                    768:        if (S_ISCHR(st.st_mode)) {
                    769:                val = istgt_lu_get_devsize(file);
                    770:        } else if (S_ISBLK(st.st_mode)) {
                    771:                val = istgt_lu_get_devsize(file);
                    772:        } else if (S_ISREG(st.st_mode)) {
                    773:                val = st.st_size;
                    774:        } else {
1.1.1.2 ! misho     775: #ifdef ALLOW_SYMLINK_DEVICE
        !           776:                ISTGT_ERRLOG("stat is neither REG, CHR nor BLK\n");
        !           777: #else
1.1       misho     778:                ISTGT_ERRLOG("lstat is neither REG, CHR nor BLK\n");
1.1.1.2 ! misho     779: #endif /* ALLOW_SYMLINK_DEVICE */
1.1       misho     780:                val = 0ULL;
                    781:        }
                    782:        return val;
                    783: }
                    784: 
                    785: uint64_t
                    786: istgt_lu_parse_size(const char *size)
                    787: {
                    788:        uint64_t val, val1, val2;
                    789:        char *endp, *p;
                    790:        size_t idx;
                    791:        int sign;
                    792: 
                    793:        val1 = (uint64_t) strtoull(size, &endp, 10);
                    794:        val = val1;
                    795:        val2 = 0;
                    796:        if (endp != NULL) {
                    797:                p = endp;
                    798:                switch (toupper((int) *p)) {
                    799:                case 'Z': val1 *= (uint64_t) 1024ULL;
                    800:                case 'E': val1 *= (uint64_t) 1024ULL;
                    801:                case 'P': val1 *= (uint64_t) 1024ULL;
                    802:                case 'T': val1 *= (uint64_t) 1024ULL;
                    803:                case 'G': val1 *= (uint64_t) 1024ULL;
                    804:                case 'M': val1 *= (uint64_t) 1024ULL;
                    805:                case 'K': val1 *= (uint64_t) 1024ULL;
                    806:                        break;
                    807:                }
                    808:                val = val1;
                    809:                p++;
                    810:                idx = strspn(p, "Bb \t");
                    811:                p += idx;
                    812:                if (*p == '-' || *p == '+') {
                    813:                        sign = (int) *p++;
                    814:                        idx = strspn(p, " \t");
                    815:                        p += idx;
                    816:                        val2 = (uint64_t) strtoull(p, &endp, 10);
                    817:                        if (endp != NULL) {
                    818:                                p = endp;
                    819:                                switch (toupper((int) *p)) {
                    820:                                case 'Z': val2 *= (uint64_t) 1024ULL;
                    821:                                case 'E': val2 *= (uint64_t) 1024ULL;
                    822:                                case 'P': val2 *= (uint64_t) 1024ULL;
                    823:                                case 'T': val2 *= (uint64_t) 1024ULL;
                    824:                                case 'G': val2 *= (uint64_t) 1024ULL;
                    825:                                case 'M': val2 *= (uint64_t) 1024ULL;
                    826:                                case 'K': val2 *= (uint64_t) 1024ULL;
                    827:                                        break;
                    828:                                }
                    829:                        }
                    830:                        if (sign == '-') {
                    831:                                if (val2 > val1) {
                    832:                                        /* underflow */
                    833:                                        val = (uint64_t) 0ULL;
                    834:                                } else {
                    835:                                        val = val1 - val2;
                    836:                                }
                    837:                        } else {
                    838:                                if (val2 > (UINT64_MAX - val1)) {
                    839:                                        /* overflow */
                    840:                                        val = UINT64_MAX;
                    841:                                } else {
                    842:                                        val = val1 + val2;
                    843:                                }
                    844:                        }
                    845:                }
                    846:        }
                    847:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    848:            "size=%s, val=%"PRIu64", val1=%"PRIu64", val2=%"PRIu64"\n",
                    849:            size, val, val1, val2);
                    850:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                    851:            "size=%s, val=%"PRIx64", val1=%"PRIx64", val2=%"PRIx64"\n",
                    852:            size, val, val1, val2);
                    853: 
                    854:        return val;
                    855: }
                    856: 
                    857: int
                    858: istgt_lu_parse_media_flags(const char *flags)
                    859: {
                    860:        char buf[MAX_TMPBUF];
                    861:        const char *delim = ",";
                    862:        char *next_p;
                    863:        char *p;
                    864:        int mflags;
                    865: 
                    866:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "mflags=%s\n", flags);
                    867:        mflags = 0;
                    868:        strlcpy(buf, flags, MAX_TMPBUF);
                    869:        next_p = buf;
                    870:        while ((p = strsep(&next_p, delim)) != NULL) {
                    871:                if (strcasecmp(p, "ro") == 0) {
                    872:                        mflags |= ISTGT_LU_FLAG_MEDIA_READONLY;
                    873:                } else if (strcasecmp(p, "rw") == 0) {
                    874:                        mflags &= ~ISTGT_LU_FLAG_MEDIA_READONLY;
                    875:                } else if (strcasecmp(p, "extend") == 0) {
                    876:                        mflags |= ISTGT_LU_FLAG_MEDIA_EXTEND;
                    877:                } else if (strcasecmp(p, "dynamic") == 0) {
                    878:                        mflags |= ISTGT_LU_FLAG_MEDIA_DYNAMIC;
                    879:                } else {
                    880:                        ISTGT_ERRLOG("unknown media flag %.64s\n", p);
                    881:                }
                    882:        }
                    883: 
                    884:        return mflags;
                    885: }
                    886: 
                    887: uint64_t
                    888: istgt_lu_parse_media_size(const char *file, const char *size, int *flags)
                    889: {
                    890:        uint64_t msize, fsize;
                    891: 
                    892:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "msize=%s\n", size);
                    893:        if (strcasecmp(file, "/dev/null") == 0) {
                    894:                return 0;
                    895:        }
                    896:        if (strcasecmp(size, "Auto") == 0
                    897:            || strcasecmp(size, "Size") == 0) {
                    898:                msize = istgt_lu_get_filesize(file);
                    899:                if (msize == 0) {
                    900:                        msize = ISTGT_LU_MEDIA_SIZE_MIN;
                    901:                }
                    902:                *flags |= ISTGT_LU_FLAG_MEDIA_AUTOSIZE;
                    903:        } else {
                    904:                msize = istgt_lu_parse_size(size);
                    905:                if (*flags & ISTGT_LU_FLAG_MEDIA_EXTEND) {
                    906:                        fsize = istgt_lu_get_filesize(file);
                    907:                        if (fsize > msize) {
                    908:                                msize = fsize;
                    909:                        }
                    910:                }
                    911:        }
                    912: 
                    913:        if (*flags & ISTGT_LU_FLAG_MEDIA_DYNAMIC) {
                    914:                if (msize < ISTGT_LU_MEDIA_SIZE_MIN) {
                    915:                        msize = ISTGT_LU_MEDIA_SIZE_MIN;
                    916:                }
                    917:        } else {
                    918:                if (msize < ISTGT_LU_MEDIA_SIZE_MIN) {
                    919:                        ISTGT_ERRLOG("media size too small\n");
                    920:                        return 0ULL;
                    921:                }
                    922:        }
                    923: 
                    924:        return msize;
                    925: }
                    926: 
1.1.1.2 ! misho     927: PORTAL_GROUP *
1.1       misho     928: istgt_lu_find_portalgroup(ISTGT_Ptr istgt, int tag)
                    929: {
1.1.1.2 ! misho     930:        PORTAL_GROUP *pgp;
1.1       misho     931:        int i;
                    932: 
1.1.1.2 ! misho     933:        for (i = 0; i < istgt->nportal_group; i++) {
        !           934:                if (istgt->portal_group[i].tag == tag) {
        !           935:                        pgp = &istgt->portal_group[i];
        !           936:                        return pgp;
1.1       misho     937:                }
                    938:        }
                    939:        return NULL;
                    940: }
                    941: 
                    942: INITIATOR_GROUP *
                    943: istgt_lu_find_initiatorgroup(ISTGT_Ptr istgt, int tag)
                    944: {
                    945:        INITIATOR_GROUP *igp;
                    946:        int i;
                    947: 
                    948:        for (i = 0; i < istgt->ninitiator_group; i++) {
                    949:                if (istgt->initiator_group[i].tag == tag) {
                    950:                        igp = &istgt->initiator_group[i];
                    951:                        return igp;
                    952:                }
                    953:        }
                    954:        return NULL;
                    955: }
                    956: 
                    957: static int
                    958: istgt_lu_check_iscsi_name(const char *name)
                    959: {
                    960:        const unsigned char *up = (const unsigned char *) name;
                    961:        size_t n;
                    962: 
                    963:        /* valid iSCSI name? */
                    964:        for (n = 0; up[n] != 0; n++) {
                    965:                if (up[n] > 0x00U && up[n] <= 0x2cU)
                    966:                        return -1;
                    967:                if (up[n] == 0x2fU)
                    968:                        return -1;
                    969:                if (up[n] >= 0x3bU && up[n] <= 0x40U)
                    970:                        return -1;
                    971:                if (up[n] >= 0x5bU && up[n] <= 0x60U)
                    972:                        return -1;
                    973:                if (up[n] >= 0x7bU && up[n] <= 0x7fU)
                    974:                        return -1;
                    975:                if (isspace(up[n]))
                    976:                        return -1;
                    977:        }
                    978:        /* valid format? */
                    979:        if (strncasecmp(name, "iqn.", 4) == 0) {
                    980:                /* iqn.YYYY-MM.reversed.domain.name */
                    981:                if (!isdigit(up[4]) || !isdigit(up[5]) || !isdigit(up[6])
                    982:                    || !isdigit(up[7]) || up[8] != '-' || !isdigit(up[9])
                    983:                    || !isdigit(up[10]) || up[11] != '.') {
                    984:                        ISTGT_ERRLOG("invalid iqn format. "
                    985:                            "expect \"iqn.YYYY-MM.reversed.domain.name\"\n");
                    986:                        return -1;
                    987:                }
                    988:        } else if (strncasecmp(name, "eui.", 4) == 0) {
                    989:                /* EUI-64 -> 16bytes */
                    990:                /* XXX */
                    991:        } else if (strncasecmp(name, "naa.", 4) == 0) {
                    992:                /* 64bit -> 16bytes, 128bit -> 32bytes */
                    993:                /* XXX */
                    994:        }
                    995:        /* OK */
                    996:        return 0;
                    997: }
                    998: 
1.1.1.2 ! misho     999: #if 0
1.1       misho    1000: static uint64_t
                   1001: istgt_lu_get_nbserial(const char *nodebase)
                   1002: {
                   1003:        ISTGT_MD5CTX md5ctx;
                   1004:        uint8_t nbsmd5[ISTGT_MD5DIGEST_LEN];
                   1005:        char buf[MAX_TMPBUF];
                   1006:        uint64_t nbs;
                   1007:        int idx;
                   1008:        int i;
                   1009: 
                   1010:        snprintf(buf, sizeof buf, "%s", nodebase);
                   1011:        if (strcasecmp(buf, "iqn.2007-09.jp.ne.peach.istgt") == 0
                   1012:            || strcasecmp(buf, "iqn.2007-09.jp.ne.peach") == 0) {
                   1013:                /* always zero */
                   1014:                return 0;
                   1015:        }
                   1016: 
                   1017:        istgt_md5init(&md5ctx);
                   1018:        istgt_md5update(&md5ctx, buf, strlen(buf));
                   1019:        istgt_md5final(nbsmd5, &md5ctx);
                   1020: 
                   1021:        nbs = 0U;
                   1022:        idx = ISTGT_MD5DIGEST_LEN - 8;
                   1023:        if (idx < 0) {
                   1024:                ISTGT_WARNLOG("missing MD5 length\n");
                   1025:                idx = 0;
                   1026:        }
                   1027:        for (i = idx; i < ISTGT_MD5DIGEST_LEN; i++) {
                   1028:                nbs |= (uint64_t) nbsmd5[i];
                   1029:                nbs = nbs << 8;
                   1030:        }
                   1031:        return nbs;
                   1032: }
1.1.1.2 ! misho    1033: #endif
1.1       misho    1034: 
                   1035: static int
                   1036: istgt_lu_set_local_settings(ISTGT_Ptr istgt, CF_SECTION *sp, ISTGT_LU_Ptr lu)
                   1037: {
                   1038:        const char *val;
                   1039: 
                   1040:        val = istgt_get_val(sp, "MaxOutstandingR2T");
                   1041:        if (val == NULL) {
                   1042:                lu->MaxOutstandingR2T = lu->istgt->MaxOutstandingR2T;
                   1043:        } else {
                   1044:                lu->MaxOutstandingR2T = (int)strtol(val, NULL, 10);
                   1045:                if (lu->MaxOutstandingR2T < 1) {
                   1046:                        lu->MaxOutstandingR2T = DEFAULT_MAXOUTSTANDINGR2T;
                   1047:                }
                   1048:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxOutstandingR2T %d\n",
                   1049:                    lu->MaxOutstandingR2T);
                   1050:        }
                   1051: 
                   1052:        val = istgt_get_val(sp, "DefaultTime2Wait");
                   1053:        if (val == NULL) {
                   1054:                lu->DefaultTime2Wait = lu->istgt->DefaultTime2Wait;
                   1055:        } else {
                   1056:                lu->DefaultTime2Wait = (int)strtol(val, NULL, 10);
                   1057:                if (lu->DefaultTime2Wait < 0) {
                   1058:                        lu->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
                   1059:                }
                   1060:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Wait %d\n",
                   1061:                    lu->DefaultTime2Wait);
                   1062:        }
                   1063: 
                   1064:        val = istgt_get_val(sp, "DefaultTime2Retain");
                   1065:        if (val == NULL) {
                   1066:                lu->DefaultTime2Retain = lu->istgt->DefaultTime2Retain;
                   1067:        } else {
                   1068:                lu->DefaultTime2Retain = (int)strtol(val, NULL, 10);
                   1069:                if (lu->DefaultTime2Retain < 0) {
                   1070:                        lu->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
                   1071:                }
                   1072:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DefaultTime2Retain %d\n",
                   1073:                    lu->DefaultTime2Retain);
                   1074:        }
                   1075: 
                   1076:        /* check size limit - RFC3720(12.15, 12.16, 12.17) */
                   1077:        if (lu->MaxOutstandingR2T > 65535) {
                   1078:                ISTGT_ERRLOG("MaxOutstandingR2T(%d) > 65535\n",
                   1079:                    lu->MaxOutstandingR2T);
                   1080:                return -1;
                   1081:        }
                   1082:        if (lu->DefaultTime2Wait > 3600) {
                   1083:                ISTGT_ERRLOG("DefaultTime2Wait(%d) > 3600\n",
                   1084:                    lu->DefaultTime2Wait);
                   1085:                return -1;
                   1086:        }
                   1087:        if (lu->DefaultTime2Retain > 3600) {
                   1088:                ISTGT_ERRLOG("DefaultTime2Retain(%d) > 3600\n",
                   1089:                    lu->DefaultTime2Retain);
                   1090:                return -1;
                   1091:        }
                   1092: 
                   1093:        val = istgt_get_val(sp, "FirstBurstLength");
                   1094:        if (val == NULL) {
                   1095:                lu->FirstBurstLength = lu->istgt->FirstBurstLength;
                   1096:        } else {
                   1097:                lu->FirstBurstLength = (int)strtol(val, NULL, 10);
                   1098:                if (lu->FirstBurstLength < 0) {
                   1099:                        lu->FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
                   1100:                }
                   1101:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "FirstBurstLength %d\n",
                   1102:                    lu->FirstBurstLength);
                   1103:        }
                   1104: 
                   1105:        val = istgt_get_val(sp, "MaxBurstLength");
                   1106:        if (val == NULL) {
                   1107:                lu->MaxBurstLength = lu->istgt->MaxBurstLength;
                   1108:        } else {
                   1109:                lu->MaxBurstLength = (int)strtol(val, NULL, 10);
                   1110:                if (lu->MaxBurstLength < 0) {
                   1111:                        lu->MaxBurstLength = DEFAULT_MAXBURSTLENGTH;
                   1112:                }
                   1113:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "MaxBurstLength %d\n",
                   1114:                    lu->MaxBurstLength);
                   1115:        }
                   1116: 
                   1117:        val = istgt_get_val(sp, "MaxRecvDataSegmentLength");
                   1118:        if (val == NULL) {
                   1119:                lu->MaxRecvDataSegmentLength
                   1120:                        = lu->istgt->MaxRecvDataSegmentLength;
                   1121:        } else {
                   1122:                lu->MaxRecvDataSegmentLength = (int)strtol(val, NULL, 10);
                   1123:                if (lu->MaxRecvDataSegmentLength < 0) {
                   1124:                        lu->MaxRecvDataSegmentLength
                   1125:                                = DEFAULT_MAXRECVDATASEGMENTLENGTH;
                   1126:                }
                   1127:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   1128:                    "MaxRecvDataSegmentLength %d\n",
                   1129:                    lu->MaxRecvDataSegmentLength);
                   1130:        }
                   1131: 
                   1132:        /* check size limit (up to 24bits - RFC3720(12.12)) */
                   1133:        if (lu->MaxBurstLength < 512) {
                   1134:                ISTGT_ERRLOG("MaxBurstLength(%d) < 512\n",
                   1135:                    lu->MaxBurstLength);
                   1136:                return -1;
                   1137:        }
                   1138:        if (lu->FirstBurstLength < 512) {
                   1139:                ISTGT_ERRLOG("FirstBurstLength(%d) < 512\n",
                   1140:                    lu->FirstBurstLength);
                   1141:                return -1;
                   1142:        }
                   1143:        if (lu->FirstBurstLength > lu->MaxBurstLength) {
                   1144:                ISTGT_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n",
                   1145:                    lu->FirstBurstLength, istgt->MaxBurstLength);
                   1146:                return -1;
                   1147:        }
                   1148:        if (lu->MaxBurstLength > 0x00ffffff) {
                   1149:                ISTGT_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n",
                   1150:                    lu->MaxBurstLength);
                   1151:                return -1;
                   1152:        }
                   1153:        if (lu->MaxRecvDataSegmentLength < 512) {
                   1154:                ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) < 512\n",
                   1155:                    lu->MaxRecvDataSegmentLength);
                   1156:                return -1;
                   1157:        }
                   1158:        if (lu->MaxRecvDataSegmentLength > 0x00ffffff) {
                   1159:                ISTGT_ERRLOG("MaxRecvDataSegmentLength(%d) > 0x00ffffff\n",
                   1160:                    lu->MaxRecvDataSegmentLength);
                   1161:                return -1;
                   1162:        }
                   1163: 
                   1164:        val = istgt_get_val(sp, "InitialR2T");
                   1165:        if (val == NULL) {
                   1166:                lu->InitialR2T = lu->istgt->InitialR2T;
                   1167:        } else {
                   1168:                if (strcasecmp(val, "Yes") == 0) {
                   1169:                        lu->InitialR2T = 1;
                   1170:                } else if (strcasecmp(val, "No") == 0) {
                   1171: #if 0
                   1172:                        lu->InitialR2T = 0;
                   1173: #else
                   1174:                        ISTGT_ERRLOG("not supported value %s\n", val);
                   1175:                        return -1;
                   1176: #endif
                   1177:                } else {
                   1178:                        ISTGT_ERRLOG("unknown value %s\n", val);
                   1179:                        return -1;
                   1180:                }
                   1181:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "InitialR2T %s\n",
                   1182:                    lu->InitialR2T ? "Yes" : "No");
                   1183:        }
                   1184: 
                   1185:        val = istgt_get_val(sp, "ImmediateData");
                   1186:        if (val == NULL) {
                   1187:                lu->ImmediateData = lu->istgt->ImmediateData;
                   1188:        } else {
                   1189:                if (strcasecmp(val, "Yes") == 0) {
                   1190:                        lu->ImmediateData = 1;
                   1191:                } else if (strcasecmp(val, "No") == 0) {
                   1192:                        lu->ImmediateData = 0;
                   1193:                } else {
                   1194:                        ISTGT_ERRLOG("unknown value %s\n", val);
                   1195:                        return -1;
                   1196:                }
                   1197:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ImmediateData %s\n",
                   1198:                    lu->ImmediateData ? "Yes" : "No");
                   1199:        }
                   1200: 
                   1201:        val = istgt_get_val(sp, "DataPDUInOrder");
                   1202:        if (val == NULL) {
                   1203:                lu->DataPDUInOrder = lu->istgt->DataPDUInOrder;
                   1204:        } else {
                   1205:                if (strcasecmp(val, "Yes") == 0) {
                   1206:                        lu->DataPDUInOrder = 1;
                   1207:                } else if (strcasecmp(val, "No") == 0) {
                   1208: #if 0
                   1209:                        lu->DataPDUInOrder = 0;
                   1210: #else
                   1211:                        ISTGT_ERRLOG("not supported value %s\n", val);
                   1212:                        return -1;
                   1213: #endif
                   1214:                } else {
                   1215:                        ISTGT_ERRLOG("unknown value %s\n", val);
                   1216:                        return -1;
                   1217:                }
                   1218:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataPDUInOrder %s\n",
                   1219:                    lu->DataPDUInOrder ? "Yes" : "No");
                   1220:        }
                   1221: 
                   1222:        val = istgt_get_val(sp, "DataSequenceInOrder");
                   1223:        if (val == NULL) {
                   1224:                lu->DataSequenceInOrder = lu->istgt->DataSequenceInOrder;
                   1225:        } else {
                   1226:                if (strcasecmp(val, "Yes") == 0) {
                   1227:                        lu->DataSequenceInOrder = 1;
                   1228:                } else if (strcasecmp(val, "No") == 0) {
                   1229: #if 0
                   1230:                        lu->DataSequenceInOrder = 0;
                   1231: #else
                   1232:                        ISTGT_ERRLOG("not supported value %s\n", val);
                   1233:                        return -1;
                   1234: #endif
                   1235:                } else {
                   1236:                        ISTGT_ERRLOG("unknown value %s\n", val);
                   1237:                        return -1;
                   1238:                }
                   1239:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "DataSequenceInOrder %s\n",
                   1240:                    lu->DataSequenceInOrder ? "Yes" : "No");
                   1241:        }
                   1242: 
                   1243:        val = istgt_get_val(sp, "ErrorRecoveryLevel");
                   1244:        if (val == NULL) {
                   1245:                lu->ErrorRecoveryLevel = lu->istgt->ErrorRecoveryLevel;
                   1246:        } else {
                   1247:                lu->ErrorRecoveryLevel = (int)strtol(val, NULL, 10);
                   1248:                if (lu->ErrorRecoveryLevel < 0) {
                   1249:                        lu->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
                   1250:                } else if (lu->ErrorRecoveryLevel == 0) {
                   1251:                        lu->ErrorRecoveryLevel = 0;
                   1252:                } else if (lu->ErrorRecoveryLevel == 1) {
                   1253: #if 0
                   1254:                        lu->ErrorRecoveryLevel = 1;
                   1255: #else
                   1256:                        ISTGT_ERRLOG("not supported value %d\n",
                   1257:                            lu->ErrorRecoveryLevel);
                   1258:                        return -1;
                   1259: #endif
                   1260:                } else if (lu->ErrorRecoveryLevel == 2) {
                   1261: #if 0
                   1262:                        lu->ErrorRecoveryLevel = 2;
                   1263: #else
                   1264:                        ISTGT_ERRLOG("not supported value %d\n",
                   1265:                            lu->ErrorRecoveryLevel);
                   1266:                        return -1;
                   1267: #endif
                   1268:                } else {
                   1269:                        ISTGT_ERRLOG("not supported value %d\n",
                   1270:                            lu->ErrorRecoveryLevel);
                   1271:                        return -1;
                   1272:                }
                   1273:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ErrorRecoveryLevel %d\n",
                   1274:                    istgt->ErrorRecoveryLevel);
                   1275:        }
                   1276: 
                   1277:        return 0;
                   1278: }
                   1279: 
                   1280: static int
                   1281: istgt_lu_add_unit(ISTGT_Ptr istgt, CF_SECTION *sp)
                   1282: {
                   1283:        char buf[MAX_TMPBUF], buf2[MAX_TMPBUF];
                   1284:        ISTGT_LU_Ptr lu;
1.1.1.2 ! misho    1285:        PORTAL_GROUP *pgp;
        !          1286:        INITIATOR_GROUP *igp;
1.1       misho    1287:        const char *vendor, *product, *revision, *serial;
                   1288:        const char *pg_tag, *ig_tag;
                   1289:        const char *ag_tag;
                   1290:        const char *flags, *file, *size;
                   1291:        const char *key, *val;
                   1292:        uint64_t msize;
1.1.1.2 ! misho    1293:        //uint64_t nbs64;
1.1       misho    1294:        int pg_tag_i, ig_tag_i;
                   1295:        int ag_tag_i;
                   1296:        int rpm, formfactor;
                   1297:        int mflags;
                   1298:        int slot;
                   1299:        int nbs;
                   1300:        int i, j, k;
                   1301:        int rc;
                   1302: 
                   1303:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "add unit %d\n", sp->num);
                   1304: 
                   1305:        if (sp->num >= MAX_LOGICAL_UNIT) {
                   1306:                ISTGT_ERRLOG("LU%d: over maximum unit number\n", sp->num);
                   1307:                return -1;
                   1308:        }
                   1309:        if (istgt->logical_unit[sp->num] != NULL) {
                   1310:                ISTGT_ERRLOG("LU%d: duplicate unit\n", sp->num);
                   1311:                return -1;
                   1312:        }
                   1313: 
                   1314:        lu = xmalloc(sizeof *lu);
                   1315:        memset(lu, 0, sizeof *lu);
                   1316:        lu->num = sp->num;
                   1317:        lu->istgt = istgt;
1.1.1.2 ! misho    1318:        lu->state = ISTGT_STATE_INVALID;
1.1       misho    1319: #if 0
                   1320:        /* disabled now */
1.1.1.2 ! misho    1321:        nbs64 = istgt_lu_get_nbserial(istgt->nodebase);
1.1       misho    1322:        nbs = (int) (nbs64 % 900) * 100000;
                   1323: #else
                   1324:        nbs = 0;
                   1325: #endif
                   1326: 
                   1327:        val = istgt_get_val(sp, "Comment");
                   1328:        if (val != NULL) {
                   1329:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Comment %s\n", val);
                   1330:        }
                   1331: 
                   1332:        val = istgt_get_val(sp, "TargetName");
                   1333:        if (val == NULL) {
                   1334:                ISTGT_ERRLOG("LU%d: TargetName not found\n", lu->num);
                   1335:                goto error_return;
                   1336:        }
                   1337:        if (strncasecmp(val, "iqn.", 4) != 0
                   1338:                && strncasecmp(val, "eui.", 4) != 0
                   1339:                && strncasecmp(val, "naa.", 4) != 0) {
                   1340:                snprintf(buf, sizeof buf, "%s:%s", istgt->nodebase, val);
                   1341:        } else {
                   1342:                snprintf(buf, sizeof buf, "%s", val);
                   1343:        }
                   1344:        if (istgt_lu_check_iscsi_name(buf) != 0) {
                   1345:                ISTGT_ERRLOG("TargetName %s contains an invalid character or format.\n",
                   1346:                    buf);
                   1347: #if 0
                   1348:                goto error_return;
                   1349: #endif
                   1350:        }
                   1351:        lu->name = xstrdup(buf);
                   1352:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "TargetName %s\n",
                   1353:                                   lu->name);
                   1354: 
                   1355:        val = istgt_get_val(sp, "TargetAlias");
                   1356:        if (val == NULL) {
                   1357:                lu->alias = NULL;
                   1358:        } else {
                   1359:                lu->alias = xstrdup(val);
                   1360:        }
                   1361:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "TargetAlias %s\n",
                   1362:            lu->alias);
                   1363: 
                   1364:        val = istgt_get_val(sp, "Mapping");
                   1365:        if (val == NULL) {
                   1366:                /* no map */
                   1367:                lu->maxmap = 0;
                   1368:        } else {
                   1369:                lu->maxmap = 0;
                   1370:                for (i = 0; ; i++) {
                   1371:                        val = istgt_get_nmval(sp, "Mapping", i, 0);
                   1372:                        if (val == NULL)
                   1373:                                break;
                   1374:                        if (lu->maxmap >= MAX_LU_MAP) {
                   1375:                                ISTGT_ERRLOG("LU%d: too many mapping\n", lu->num);
                   1376:                                goto error_return;
                   1377:                        }
                   1378:                        pg_tag = istgt_get_nmval(sp, "Mapping", i, 0);
                   1379:                        ig_tag = istgt_get_nmval(sp, "Mapping", i, 1);
                   1380:                        if (pg_tag == NULL || ig_tag == NULL) {
                   1381:                                ISTGT_ERRLOG("LU%d: mapping error\n", lu->num);
                   1382:                                goto error_return;
                   1383:                        }
                   1384:                        if (strncasecmp(pg_tag, "PortalGroup",
                   1385:                                strlen("PortalGroup")) != 0
                   1386:                            || sscanf(pg_tag, "%*[^0-9]%d", &pg_tag_i) != 1) {
                   1387:                                ISTGT_ERRLOG("LU%d: mapping portal error\n", lu->num);
                   1388:                                goto error_return;
                   1389:                        }
                   1390:                        if (strncasecmp(ig_tag, "InitiatorGroup",
                   1391:                                strlen("InitiatorGroup")) != 0
                   1392:                            || sscanf(ig_tag, "%*[^0-9]%d", &ig_tag_i) != 1) {
                   1393:                                ISTGT_ERRLOG("LU%d: mapping initiator error\n", lu->num);
                   1394:                                goto error_return;
                   1395:                        }
                   1396:                        if (pg_tag_i < 1 || ig_tag_i < 1) {
                   1397:                                ISTGT_ERRLOG("LU%d: invalid group tag\n", lu->num);
                   1398:                                goto error_return;
                   1399:                        }
1.1.1.2 ! misho    1400:                        MTX_LOCK(&istgt->mutex);
        !          1401:                        pgp = istgt_lu_find_portalgroup(istgt, pg_tag_i);
        !          1402:                        if (pgp == NULL) {
        !          1403:                                MTX_UNLOCK(&istgt->mutex);
1.1       misho    1404:                                ISTGT_ERRLOG("LU%d: PortalGroup%d not found\n",
                   1405:                                                         lu->num, pg_tag_i);
                   1406:                                goto error_return;
                   1407:                        }
1.1.1.2 ! misho    1408:                        igp = istgt_lu_find_initiatorgroup(istgt, ig_tag_i);
        !          1409:                        if (igp == NULL) {
        !          1410:                                MTX_UNLOCK(&istgt->mutex);
1.1       misho    1411:                                ISTGT_ERRLOG("LU%d: InitiatorGroup%d not found\n",
                   1412:                                    lu->num, ig_tag_i);
                   1413:                                goto error_return;
                   1414:                        }
1.1.1.2 ! misho    1415:                        pgp->ref++;
        !          1416:                        igp->ref++;
        !          1417:                        MTX_UNLOCK(&istgt->mutex);
1.1       misho    1418:                        lu->map[i].pg_tag = pg_tag_i;
                   1419:                        lu->map[i].pg_aas = AAS_ACTIVE_OPTIMIZED;
                   1420:                        //lu->map[i].pg_aas = AAS_ACTIVE_NON_OPTIMIZED;
                   1421:                        lu->map[i].pg_aas |= AAS_STATUS_IMPLICIT;
                   1422:                        lu->map[i].ig_tag = ig_tag_i;
                   1423:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   1424:                            "Mapping PortalGroup%d InitiatorGroup%d\n",
                   1425:                            lu->map[i].pg_tag, lu->map[i].ig_tag);
                   1426:                        lu->maxmap = i + 1;
                   1427:                }
                   1428:        }
                   1429:        if (lu->maxmap == 0) {
                   1430:                ISTGT_ERRLOG("LU%d: no Mapping\n", lu->num);
                   1431:                goto error_return;
                   1432:        }
                   1433: 
                   1434:        val = istgt_get_val(sp, "AuthMethod");
                   1435:        if (val == NULL) {
                   1436:                /* none */
                   1437:                lu->no_auth_chap = 0;
                   1438:                lu->auth_chap = 0;
                   1439:                lu->auth_chap_mutual = 0;
                   1440:        } else {
                   1441:                lu->no_auth_chap = 0;
                   1442:                for (i = 0; ; i++) {
                   1443:                        val = istgt_get_nmval(sp, "AuthMethod", 0, i);
                   1444:                        if (val == NULL)
                   1445:                                break;
                   1446:                        if (strcasecmp(val, "CHAP") == 0) {
                   1447:                                lu->auth_chap = 1;
                   1448:                        } else if (strcasecmp(val, "Mutual") == 0) {
                   1449:                                lu->auth_chap_mutual = 1;
                   1450:                        } else if (strcasecmp(val, "Auto") == 0) {
                   1451:                                lu->auth_chap = 0;
                   1452:                                lu->auth_chap_mutual = 0;
                   1453:                        } else if (strcasecmp(val, "None") == 0) {
                   1454:                                lu->no_auth_chap = 1;
                   1455:                                lu->auth_chap = 0;
                   1456:                                lu->auth_chap_mutual = 0;
                   1457:                        } else {
                   1458:                                ISTGT_ERRLOG("LU%d: unknown auth\n", lu->num);
                   1459:                                goto error_return;
                   1460:                        }
                   1461:                }
                   1462:                if (lu->auth_chap_mutual && !lu->auth_chap) {
                   1463:                        ISTGT_ERRLOG("LU%d: Mutual but not CHAP\n", lu->num);
                   1464:                        goto error_return;
                   1465:                }
                   1466:        }
                   1467:        if (lu->no_auth_chap != 0) {
                   1468:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod None\n");
                   1469:        } else if (lu->auth_chap == 0) {
                   1470:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod Auto\n");
                   1471:        } else {
                   1472:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthMethod %s %s\n",
                   1473:                    lu->auth_chap ? "CHAP" : "",
                   1474:                    lu->auth_chap_mutual ? "Mutual" : "");
                   1475:        }
                   1476: 
                   1477:        val = istgt_get_val(sp, "AuthGroup");
                   1478:        if (val == NULL) {
                   1479:                lu->auth_group = 0;
                   1480:        } else {
                   1481:                ag_tag = val;
                   1482:                if (strcasecmp(ag_tag, "None") == 0) {
                   1483:                        ag_tag_i = 0;
                   1484:                } else {
                   1485:                        if (strncasecmp(ag_tag, "AuthGroup",
                   1486:                                strlen("AuthGroup")) != 0
                   1487:                            || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) {
                   1488:                                ISTGT_ERRLOG("LU%d: auth group error\n", lu->num);
                   1489:                                goto error_return;
                   1490:                        }
                   1491:                        if (ag_tag_i == 0) {
1.1.1.2 ! misho    1492:                                ISTGT_ERRLOG("LU%d: invalid auth group %d\n", lu->num,
        !          1493:                                    ag_tag_i);
1.1       misho    1494:                                goto error_return;
                   1495:                        }
                   1496:                }
                   1497:                lu->auth_group = ag_tag_i;
                   1498:        }
                   1499:        if (lu->auth_group == 0) {
                   1500:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthGroup None\n");
                   1501:        } else {
                   1502:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "AuthGroup AuthGroup%d\n",
                   1503:                    lu->auth_group);
                   1504:        }
                   1505: 
                   1506:        val = istgt_get_val(sp, "UseDigest");
                   1507:        if (val != NULL) {
                   1508:                for (i = 0; ; i++) {
                   1509:                        val = istgt_get_nmval(sp, "UseDigest", 0, i);
                   1510:                        if (val == NULL)
                   1511:                                break;
                   1512:                        if (strcasecmp(val, "Header") == 0) {
                   1513:                                lu->header_digest = 1;
                   1514:                        } else if (strcasecmp(val, "Data") == 0) {
                   1515:                                lu->data_digest = 1;
                   1516:                        } else if (strcasecmp(val, "Auto") == 0) {
                   1517:                                lu->header_digest = 0;
                   1518:                                lu->data_digest = 0;
                   1519:                        } else {
                   1520:                                ISTGT_ERRLOG("LU%d: unknown digest\n", lu->num);
                   1521:                                goto error_return;
                   1522:                        }
                   1523:                }
                   1524:        }
                   1525:        if (lu->header_digest == 0 && lu->data_digest == 0) {
                   1526:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UseDigest Auto\n");
                   1527:        } else {
                   1528:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UseDigest %s %s\n",
                   1529:                    lu->header_digest ? "Header" : "",
                   1530:                    lu->data_digest ? "Data" : "");
                   1531:        }
                   1532: 
                   1533:        val = istgt_get_val(sp, "ReadOnly");
                   1534:        if (val == NULL) {
                   1535:                lu->readonly = 0;
                   1536:        } else if (strcasecmp(val, "Yes") == 0) {
                   1537:                lu->readonly = 1;
                   1538:        }
                   1539:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "ReadOnly %s\n",
                   1540:            lu->readonly ? "Yes" : "No");
                   1541: 
                   1542:        val = istgt_get_val(sp, "UnitType");
                   1543:        if (val == NULL) {
                   1544:                ISTGT_ERRLOG("LU%d: unknown unit type\n", lu->num);
                   1545:                goto error_return;
                   1546:        }
                   1547:        if (strcasecmp(val, "Pass") == 0) {
                   1548:                lu->type = ISTGT_LU_TYPE_PASS;
                   1549:        } else if (strcasecmp(val, "Disk") == 0) {
                   1550:                lu->type = ISTGT_LU_TYPE_DISK;
                   1551:        } else if (strcasecmp(val, "DVD") == 0) {
                   1552:                lu->type = ISTGT_LU_TYPE_DVD;
                   1553:        } else if (strcasecmp(val, "Tape") == 0) {
                   1554:                lu->type = ISTGT_LU_TYPE_TAPE;
                   1555:        } else {
                   1556:                ISTGT_ERRLOG("LU%d: unknown unit type\n", lu->num);
                   1557:                goto error_return;
                   1558:        }
                   1559:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitType %d (%s)\n",
                   1560:            lu->type, val);
                   1561: 
                   1562:        val = istgt_get_val(sp, "UnitOnline");
                   1563:        if (val == NULL) {
                   1564:                lu->online = 1;
                   1565:        } else if (strcasecmp(val, "Yes") == 0) {
                   1566:                lu->online = 1;
                   1567:        }
                   1568:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitOnline %s\n",
                   1569:            lu->online ? "Yes" : "No");
                   1570: 
                   1571:        vendor = istgt_get_nmval(sp, "UnitInquiry", 0, 0);
                   1572:        product = istgt_get_nmval(sp, "UnitInquiry", 0, 1);
                   1573:        revision = istgt_get_nmval(sp, "UnitInquiry", 0, 2);
                   1574:        serial = istgt_get_nmval(sp, "UnitInquiry", 0, 3);
                   1575:        switch (lu->type) {
                   1576:        case ISTGT_LU_TYPE_DISK:
                   1577:                if (vendor == NULL || strlen(vendor) == 0)
                   1578:                        vendor = DEFAULT_LU_VENDOR_DISK;
                   1579:                if (product == NULL || strlen(product) == 0)
                   1580:                        product = DEFAULT_LU_PRODUCT_DISK;
                   1581:                if (revision == NULL || strlen(revision) == 0)
                   1582:                        revision = DEFAULT_LU_REVISION_DISK;
                   1583:                if (serial == NULL || strlen(serial) == 0) {
                   1584:                        snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
                   1585:                        serial = (const char *) &buf[0];
                   1586:                }
                   1587:                break;
                   1588:        case ISTGT_LU_TYPE_DVD:
                   1589:                if (vendor == NULL || strlen(vendor) == 0)
                   1590:                        vendor = DEFAULT_LU_VENDOR_DVD;
                   1591:                if (product == NULL || strlen(product) == 0)
                   1592:                        product = DEFAULT_LU_PRODUCT_DVD;
                   1593:                if (revision == NULL || strlen(revision) == 0)
                   1594:                        revision = DEFAULT_LU_REVISION_DVD;
                   1595:                if (serial == NULL || strlen(serial) == 0) {
                   1596:                        snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
                   1597:                        serial = (const char *) &buf[0];
                   1598:                }
                   1599:                break;
                   1600:        case ISTGT_LU_TYPE_TAPE:
                   1601:                if (vendor == NULL || strlen(vendor) == 0)
                   1602:                        vendor = DEFAULT_LU_VENDOR_TAPE;
                   1603:                if (product == NULL || strlen(product) == 0)
                   1604:                        product = DEFAULT_LU_PRODUCT_TAPE;
                   1605:                if (revision == NULL || strlen(revision) == 0)
                   1606:                        revision = DEFAULT_LU_REVISION_TAPE;
                   1607:                if (serial == NULL || strlen(serial) == 0) {
                   1608: #ifdef USE_LU_TAPE_DLT8000
                   1609:                        snprintf(buf, sizeof buf, "CX%.8d", 10000000 + nbs + lu->num);
                   1610: #else
                   1611:                        snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
                   1612: #endif /* USE_LU_TAPE_DLT8000 */
                   1613:                        serial = (const char *) &buf[0];
                   1614:                }
                   1615:                break;
                   1616:        default:
                   1617:                if (vendor == NULL || strlen(vendor) == 0)
                   1618:                        vendor = DEFAULT_LU_VENDOR;
                   1619:                if (product == NULL || strlen(product) == 0)
                   1620:                        product = DEFAULT_LU_PRODUCT;
                   1621:                if (revision == NULL || strlen(revision) == 0)
                   1622:                        revision = DEFAULT_LU_REVISION;
                   1623:                if (serial == NULL || strlen(serial) == 0) {
                   1624:                        snprintf(buf, sizeof buf, "%.8d", 10000000 + nbs + lu->num);
                   1625:                        serial = (const char *) &buf[0];
                   1626:                }
                   1627:                break;
                   1628:        }
                   1629:        lu->inq_vendor = xstrdup(vendor);
                   1630:        lu->inq_product = xstrdup(product);
                   1631:        lu->inq_revision = xstrdup(revision);
                   1632:        lu->inq_serial = xstrdup(serial);
                   1633:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "UnitInquiry %s %s %s %s\n",
                   1634:            lu->inq_vendor, lu->inq_product, lu->inq_revision,
                   1635:            lu->inq_serial);
                   1636: 
                   1637:        val = istgt_get_val(sp, "BlockLength");
                   1638:        if (val == NULL) {
                   1639:                switch (lu->type) {
                   1640:                case ISTGT_LU_TYPE_DISK:
                   1641:                        lu->blocklen = DEFAULT_LU_BLOCKLEN_DISK;
                   1642:                        break;
                   1643:                case ISTGT_LU_TYPE_DVD:
                   1644:                        lu->blocklen = DEFAULT_LU_BLOCKLEN_DVD;
                   1645:                        break;
                   1646:                case ISTGT_LU_TYPE_TAPE:
                   1647:                        lu->blocklen = DEFAULT_LU_BLOCKLEN_TAPE;
                   1648:                        break;
                   1649:                default:
                   1650:                        lu->blocklen = DEFAULT_LU_BLOCKLEN;
                   1651:                        break;
                   1652:                }
                   1653:        } else {
                   1654:                lu->blocklen = (int) strtol(val, NULL, 10);
                   1655:        }
                   1656:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "BlockLength %d\n",
                   1657:            lu->blocklen);
                   1658: 
                   1659:        val = istgt_get_val(sp, "QueueDepth");
                   1660:        if (val == NULL) {
                   1661:                switch (lu->type) {
                   1662:                case ISTGT_LU_TYPE_DISK:
                   1663:                        lu->queue_depth = DEFAULT_LU_QUEUE_DEPTH;
                   1664:                        //lu->queue_depth = 0;
                   1665:                        break;
                   1666:                case ISTGT_LU_TYPE_DVD:
                   1667:                case ISTGT_LU_TYPE_TAPE:
                   1668:                default:
                   1669:                        lu->queue_depth = 0;
                   1670:                        break;
                   1671:                }
                   1672:        } else {
                   1673:                lu->queue_depth = (int) strtol(val, NULL, 10);
                   1674:        }
                   1675:        if (lu->queue_depth < 0 || lu->queue_depth >= MAX_LU_QUEUE_DEPTH) {
1.1.1.2 ! misho    1676:                ISTGT_ERRLOG("LU%d: queue depth range error\n", lu->num);
1.1       misho    1677:                goto error_return;
                   1678:        }
                   1679:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "QueueDepth %d\n",
                   1680:            lu->queue_depth);
                   1681: 
                   1682:        lu->maxlun = 0;
                   1683:        for (i = 0; i < MAX_LU_LUN; i++) {
                   1684:                lu->lun[i].type = ISTGT_LU_LUN_TYPE_NONE;
                   1685:                lu->lun[i].rotationrate = DEFAULT_LU_ROTATIONRATE;
                   1686:                lu->lun[i].formfactor = DEFAULT_LU_FORMFACTOR;
                   1687:                lu->lun[i].readcache = 1;
                   1688:                lu->lun[i].writecache = 1;
                   1689:                lu->lun[i].serial = NULL;
                   1690:                lu->lun[i].spec = NULL;
                   1691:                snprintf(buf, sizeof buf, "LUN%d", i);
                   1692:                val = istgt_get_val(sp, buf);
                   1693:                if (val == NULL)
                   1694:                        continue;
                   1695:                if (i != 0) {
                   1696:                        /* default LUN serial (except LUN0) */
                   1697:                        snprintf(buf2, sizeof buf2, "%sL%d", lu->inq_serial, i);
                   1698:                        lu->lun[i].serial = xstrdup(buf2);
                   1699:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d Serial %s (default)\n",
                   1700:                            i, buf2);
                   1701:                }
                   1702:                for (j = 0; ; j++) {
                   1703:                        val = istgt_get_nmval(sp, buf, j, 0);
                   1704:                        if (val == NULL)
                   1705:                                break;
                   1706:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d\n", i);
                   1707:                        if (strcasecmp(val, "Device") == 0) {
                   1708:                                if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
                   1709:                                        ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
                   1710:                                        goto error_return;
                   1711:                                }
                   1712:                                lu->lun[i].type = ISTGT_LU_LUN_TYPE_DEVICE;
                   1713: 
                   1714:                                file = istgt_get_nmval(sp, buf, j, 1);
                   1715:                                if (file == NULL) {
                   1716:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1717:                                        goto error_return;
                   1718:                                }
                   1719:                                lu->lun[i].u.device.file = xstrdup(file);
                   1720:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "Device file=%s\n",
                   1721:                                                           lu->lun[i].u.device.file);
                   1722:                        } else if (strcasecmp(val, "Storage") == 0) {
                   1723:                                if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
                   1724:                                        ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
                   1725:                                        goto error_return;
                   1726:                                }
                   1727:                                lu->lun[i].type = ISTGT_LU_LUN_TYPE_STORAGE;
                   1728: 
                   1729:                                file = istgt_get_nmval(sp, buf, j, 1);
                   1730:                                size = istgt_get_nmval(sp, buf, j, 2);
                   1731:                                if (file == NULL || size == NULL) {
                   1732:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1733:                                        goto error_return;
                   1734:                                }
                   1735:                                if (strcasecmp(size, "Auto") == 0
                   1736:                                    || strcasecmp(size, "Size") == 0) {
                   1737:                                        lu->lun[i].u.storage.size = istgt_lu_get_filesize(file);
                   1738:                                } else {
                   1739:                                        lu->lun[i].u.storage.size = istgt_lu_parse_size(size);
                   1740:                                }
                   1741:                                if (lu->lun[i].u.storage.size == 0) {
                   1742:                                        ISTGT_ERRLOG("LU%d: LUN%d: Auto size error (%s)\n", lu->num, i, file);
                   1743:                                        goto error_return;
                   1744:                                }
                   1745:                                lu->lun[i].u.storage.fd = -1;
                   1746:                                lu->lun[i].u.storage.file = xstrdup(file);
                   1747:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   1748:                                    "Storage file=%s, size=%"PRIu64"\n",
                   1749:                                    lu->lun[i].u.storage.file,
                   1750:                                    lu->lun[i].u.storage.size);
                   1751:                        } else if (strcasecmp(val, "Removable") == 0) {
                   1752:                                if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_NONE) {
                   1753:                                        ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
                   1754:                                        goto error_return;
                   1755:                                }
                   1756:                                lu->lun[i].type = ISTGT_LU_LUN_TYPE_REMOVABLE;
                   1757: 
                   1758:                                flags = istgt_get_nmval(sp, buf, j, 1);
                   1759:                                file = istgt_get_nmval(sp, buf, j, 2);
                   1760:                                size = istgt_get_nmval(sp, buf, j, 3);
                   1761:                                if (flags == NULL || file == NULL || size == NULL) {
                   1762:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1763:                                        goto error_return;
                   1764:                                }
                   1765:                                mflags = istgt_lu_parse_media_flags(flags);
                   1766:                                msize = istgt_lu_parse_media_size(file, size, &mflags);
                   1767:                                if (msize == 0 && strcasecmp(file, "/dev/null") == 0) {
                   1768:                                        /* empty media */
                   1769:                                } else if (msize == 0) {
                   1770:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1771:                                        goto error_return;
                   1772:                                }
                   1773:                                lu->lun[i].u.removable.type = 0;
                   1774:                                lu->lun[i].u.removable.id = 0;
                   1775:                                lu->lun[i].u.removable.fd = -1;
                   1776:                                lu->lun[i].u.removable.flags = mflags;
                   1777:                                lu->lun[i].u.removable.file = xstrdup(file);
                   1778:                                lu->lun[i].u.removable.size = msize;
                   1779:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   1780:                                    "Removable file=%s, size=%"PRIu64", flags=%x\n",
                   1781:                                    lu->lun[i].u.removable.file,
                   1782:                                    lu->lun[i].u.removable.size,
                   1783:                                    lu->lun[i].u.removable.flags);
                   1784:                        } else if (strncasecmp(val, "Slot", 4) == 0) {
                   1785:                                if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_NONE) {
                   1786:                                        lu->lun[i].u.slot.maxslot = 0;
                   1787:                                        for (k = 0; k < MAX_LU_LUN_SLOT; k++) {
                   1788:                                                lu->lun[i].u.slot.present[k] = 0;
                   1789:                                                lu->lun[i].u.slot.flags[k] = 0;
                   1790:                                                lu->lun[i].u.slot.file[k] = NULL;
                   1791:                                                lu->lun[i].u.slot.size[k] = 0;
                   1792:                                        }
                   1793:                                } else if (lu->lun[i].type != ISTGT_LU_LUN_TYPE_SLOT) {
                   1794:                                        ISTGT_ERRLOG("LU%d: duplicate LUN%d\n", lu->num, i);
                   1795:                                        goto error_return;
                   1796:                                }
                   1797:                                lu->lun[i].type = ISTGT_LU_LUN_TYPE_SLOT;
                   1798:                                if (sscanf(val, "%*[^0-9]%d", &slot) != 1) {
                   1799:                                        ISTGT_ERRLOG("LU%d: slot number error\n", lu->num);
                   1800:                                        goto error_return;
                   1801:                                }
                   1802:                                if (slot < 0 || slot >= MAX_LU_LUN_SLOT) {
                   1803:                                        ISTGT_ERRLOG("LU%d: slot number range error\n", lu->num);
                   1804:                                        goto error_return;
                   1805:                                }
                   1806:                                if (lu->lun[i].u.slot.present[slot]) {
                   1807:                                        ISTGT_ERRLOG("LU%d: duplicate slot %d\n", lu->num, slot);
                   1808:                                        goto error_return;
                   1809:                                }
                   1810:                                lu->lun[i].u.slot.present[slot] = 1;
                   1811:                                if (slot + 1 > lu->lun[i].u.slot.maxslot) {
                   1812:                                        lu->lun[i].u.slot.maxslot = slot + 1;
                   1813:                                }
                   1814: 
                   1815:                                flags = istgt_get_nmval(sp, buf, j, 1);
                   1816:                                file = istgt_get_nmval(sp, buf, j, 2);
                   1817:                                size = istgt_get_nmval(sp, buf, j, 3);
                   1818:                                if (flags == NULL || file == NULL || size == NULL) {
                   1819:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1820:                                        goto error_return;
                   1821:                                }
                   1822:                                mflags = istgt_lu_parse_media_flags(flags);
                   1823:                                msize = istgt_lu_parse_media_size(file, size, &mflags);
                   1824:                                if (msize == 0) {
                   1825:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1826:                                        goto error_return;
                   1827:                                }
                   1828:                                lu->lun[i].u.slot.flags[slot] = mflags;
                   1829:                                lu->lun[i].u.slot.file[slot] = xstrdup(file);
                   1830:                                lu->lun[i].u.slot.size[slot] = msize;
                   1831:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   1832:                                    "Slot%d file=%s, size=%"PRIu64", flags=%x\n",
                   1833:                                    slot,
                   1834:                                    lu->lun[i].u.slot.file[slot],
                   1835:                                    lu->lun[i].u.slot.size[slot],
                   1836:                                    lu->lun[i].u.slot.flags[slot]);
                   1837:                        } else if (strncasecmp(val, "Option", 6) == 0) {
                   1838:                                key = istgt_get_nmval(sp, buf, j, 1);
                   1839:                                val = istgt_get_nmval(sp, buf, j, 2);
                   1840:                                if (key == NULL || val == NULL) {
                   1841:                                        ISTGT_ERRLOG("LU%d: LUN%d: format error\n", lu->num, i);
                   1842:                                        goto error_return;
                   1843:                                }
                   1844:                                if (strcasecmp(key, "Serial") == 0) {
                   1845:                                        /* set LUN serial */
                   1846:                                        if (strlen(val) == 0) {
                   1847:                                                ISTGT_ERRLOG("LU%d: LUN%d: no serial\n",
                   1848:                                                    lu->num, i);
                   1849:                                                goto error_return;
                   1850:                                        }
                   1851:                                        xfree(lu->lun[i].serial);
                   1852:                                        lu->lun[i].serial = xstrdup(val);
                   1853:                                } else if (strcasecmp(key, "RPM") == 0) {
                   1854:                                        rpm = (int)strtol(val, NULL, 10);
                   1855:                                        if (rpm < 0) {
                   1856:                                                rpm = 0;
                   1857:                                        } else if (rpm > 0xfffe) {
                   1858:                                                rpm = 0xfffe;
                   1859:                                        }
                   1860:                                        lu->lun[i].rotationrate = rpm;
                   1861:                                } else if (strcasecmp(key, "FormFactor") == 0) {
                   1862:                                        formfactor = (int)strtol(val, NULL, 10);
                   1863:                                        if (formfactor < 0) {
                   1864:                                                formfactor = 0;
                   1865:                                        } else if (formfactor > 0x0f) {
                   1866:                                                formfactor = 0xf;
                   1867:                                        }
                   1868:                                        lu->lun[i].formfactor = formfactor;
                   1869:                                } else if (strcasecmp(key, "ReadCache") == 0) {
                   1870:                                        if (strcasecmp(val, "Enable") == 0) {
                   1871:                                                lu->lun[i].readcache = 1;
                   1872:                                        } else if (strcasecmp(val, "Disable") == 0) {
                   1873:                                                lu->lun[i].readcache = 0;
                   1874:                                        } else {
                   1875:                                                ISTGT_ERRLOG("LU%d: LUN%d: unknown val(%s)\n",
                   1876:                                                    lu->num, i, val);
                   1877:                                        }
                   1878:                                } else if (strcasecmp(key, "WriteCache") == 0) {
                   1879:                                        if (strcasecmp(val, "Enable") == 0) {
                   1880:                                                lu->lun[i].writecache = 1;
                   1881:                                        } else if (strcasecmp(val, "Disable") == 0) {
                   1882:                                                lu->lun[i].writecache = 0;
                   1883:                                        } else {
                   1884:                                                ISTGT_ERRLOG("LU%d: LUN%d: unknown val(%s)\n",
                   1885:                                                    lu->num, i, val);
                   1886:                                        }
                   1887:                                } else {
                   1888:                                        ISTGT_WARNLOG("LU%d: LUN%d: unknown key(%s)\n",
                   1889:                                            lu->num, i, key);
                   1890:                                        continue;
                   1891:                                }
                   1892:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LUN%d Option %s => %s\n",
                   1893:                                    i, key, val);
                   1894:                                continue;
                   1895:                        } else {
                   1896:                                ISTGT_ERRLOG("LU%d: unknown lun type\n", lu->num);
                   1897:                                goto error_return;
                   1898:                        }
                   1899:                }
                   1900:                if (lu->lun[i].type == ISTGT_LU_LUN_TYPE_SLOT) {
                   1901:                        if (lu->lun[i].u.slot.maxslot == 0) {
                   1902:                                ISTGT_ERRLOG("LU%d: no slot\n", lu->num);
                   1903:                                goto error_return;
                   1904:                        }
                   1905:                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "maxslot=%d\n",
                   1906:                            lu->lun[i].u.slot.maxslot);
                   1907:                }
                   1908:                lu->maxlun = i + 1;
                   1909:        }
                   1910:        if (lu->maxlun == 0) {
                   1911:                ISTGT_ERRLOG("LU%d: no LUN\n", lu->num);
                   1912:                goto error_return;
                   1913:        }
                   1914:        if (lu->lun[0].type == ISTGT_LU_LUN_TYPE_NONE) {
                   1915:                ISTGT_ERRLOG("LU%d: no LUN0\n", lu->num);
                   1916:                goto error_return;
                   1917:        }
                   1918: 
                   1919:        /* set local values if any */
                   1920:        rc = istgt_lu_set_local_settings(istgt, sp, lu);
                   1921:        if (rc < 0) {
                   1922:                ISTGT_ERRLOG("LU%d: local setting error\n", lu->num);
                   1923:                goto error_return;
                   1924:        }
                   1925: 
                   1926:        /* tsih 0 is reserved */
                   1927:        for (i = 0; i < MAX_LU_TSIH; i++) {
                   1928:                lu->tsih[i].tag = 0;
                   1929:                lu->tsih[i].tsih = 0;
                   1930:                lu->tsih[i].initiator_port = NULL;
                   1931:        }
                   1932:        lu->maxtsih = 1;
                   1933:        lu->last_tsih = 0;
                   1934: 
                   1935:        MTX_LOCK(&istgt->mutex);
                   1936:        istgt->nlogical_unit++;
                   1937:        istgt->logical_unit[lu->num] = lu;
                   1938:        MTX_UNLOCK(&istgt->mutex);
                   1939:        return 0;
                   1940: 
                   1941:  error_return:
                   1942:        xfree(lu->name);
                   1943:        xfree(lu->alias);
                   1944:        xfree(lu->inq_vendor);
                   1945:        xfree(lu->inq_product);
                   1946:        xfree(lu->inq_revision);
                   1947:        for (i = 0; i < MAX_LU_LUN; i++) {
                   1948:                switch (lu->lun[i].type) {
                   1949:                case ISTGT_LU_LUN_TYPE_DEVICE:
                   1950:                        xfree(lu->lun[i].u.device.file);
                   1951:                        break;
                   1952:                case ISTGT_LU_LUN_TYPE_STORAGE:
                   1953:                        xfree(lu->lun[i].u.storage.file);
                   1954:                        break;
                   1955:                case ISTGT_LU_LUN_TYPE_REMOVABLE:
                   1956:                        xfree(lu->lun[i].u.removable.file);
                   1957:                        break;
                   1958:                case ISTGT_LU_LUN_TYPE_SLOT:
                   1959:                        for (j = 0; j < lu->lun[i].u.slot.maxslot; j++) {
                   1960:                                xfree(lu->lun[i].u.slot.file[j]);
                   1961:                        }
                   1962:                        break;
                   1963:                case ISTGT_LU_LUN_TYPE_NONE:
                   1964:                default:
                   1965:                        break;
                   1966:                }
                   1967:        }
                   1968:        for (i = 0; i < MAX_LU_TSIH; i++) {
                   1969:                xfree(lu->tsih[i].initiator_port);
                   1970:        }
                   1971:        for (i = 0; i < lu->maxmap; i++) {
1.1.1.2 ! misho    1972:                pg_tag_i = lu->map[i].pg_tag;
        !          1973:                ig_tag_i = lu->map[i].ig_tag;
        !          1974:                MTX_LOCK(&istgt->mutex);
        !          1975:                pgp = istgt_lu_find_portalgroup(istgt, pg_tag_i);
        !          1976:                igp = istgt_lu_find_initiatorgroup(istgt, ig_tag_i);
        !          1977:                if (pgp != NULL && igp != NULL) {
        !          1978:                        pgp->ref--;
        !          1979:                        igp->ref--;
        !          1980:                }
        !          1981:                MTX_UNLOCK(&istgt->mutex);
1.1       misho    1982:        }
                   1983: 
                   1984:        xfree(lu);
                   1985:        return -1;
                   1986: }
                   1987: 
                   1988: static int
                   1989: istgt_lu_del_unit(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
                   1990: {
1.1.1.2 ! misho    1991:        PORTAL_GROUP *pgp;
        !          1992:        INITIATOR_GROUP *igp;
        !          1993:        int pg_tag_i, ig_tag_i;
1.1       misho    1994:        int i, j;
                   1995: 
                   1996:        if (lu ==NULL)
                   1997:                return 0;
                   1998:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "del unit %d\n", lu->num);
                   1999: 
1.1.1.2 ! misho    2000:        //MTX_LOCK(&istgt->mutex);
1.1       misho    2001:        istgt->nlogical_unit--;
                   2002:        istgt->logical_unit[lu->num] = NULL;
1.1.1.2 ! misho    2003:        //MTX_UNLOCK(&istgt->mutex);
1.1       misho    2004: 
                   2005:        xfree(lu->name);
                   2006:        xfree(lu->alias);
                   2007:        xfree(lu->inq_vendor);
                   2008:        xfree(lu->inq_product);
                   2009:        xfree(lu->inq_revision);
                   2010:        xfree(lu->inq_serial);
                   2011:        for (i = 0; i < MAX_LU_LUN; i++) {
                   2012:                xfree(lu->lun[i].serial);
                   2013:                switch (lu->lun[i].type) {
                   2014:                case ISTGT_LU_LUN_TYPE_DEVICE:
                   2015:                        xfree(lu->lun[i].u.device.file);
                   2016:                        break;
                   2017:                case ISTGT_LU_LUN_TYPE_STORAGE:
                   2018:                        xfree(lu->lun[i].u.storage.file);
                   2019:                        break;
                   2020:                case ISTGT_LU_LUN_TYPE_REMOVABLE:
                   2021:                        xfree(lu->lun[i].u.removable.file);
                   2022:                        break;
                   2023:                case ISTGT_LU_LUN_TYPE_SLOT:
                   2024:                        for (j = 0; j < lu->lun[i].u.slot.maxslot; j++) {
                   2025:                                xfree(lu->lun[i].u.slot.file[j]);
                   2026:                        }
                   2027:                        break;
                   2028:                case ISTGT_LU_LUN_TYPE_NONE:
                   2029:                default:
                   2030:                        break;
                   2031:                }
                   2032:        }
                   2033:        for (i = 0; i < MAX_LU_TSIH; i++) {
                   2034:                xfree(lu->tsih[i].initiator_port);
                   2035:        }
                   2036:        for (i = 0; i < lu->maxmap; i++) {
1.1.1.2 ! misho    2037:                pg_tag_i = lu->map[i].pg_tag;
        !          2038:                ig_tag_i = lu->map[i].ig_tag;
        !          2039:                //MTX_LOCK(&istgt->mutex);
        !          2040:                pgp = istgt_lu_find_portalgroup(istgt, pg_tag_i);
        !          2041:                igp = istgt_lu_find_initiatorgroup(istgt, ig_tag_i);
        !          2042:                if (pgp != NULL && igp != NULL) {
        !          2043:                        pgp->ref--;
        !          2044:                        igp->ref--;
        !          2045:                }
        !          2046:                //MTX_UNLOCK(&istgt->mutex);
1.1       misho    2047:        }
                   2048: 
                   2049:        return 0;
                   2050: }
                   2051: 
                   2052: static void *luworker(void *arg);
                   2053: 
1.1.1.2 ! misho    2054: static int istgt_lu_init_unit(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
        !          2055: {
        !          2056:        int rc;
        !          2057: 
        !          2058:        rc = pthread_mutex_init(&lu->mutex, NULL);
        !          2059:        if (rc != 0) {
        !          2060:                ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
        !          2061:                return -1;
        !          2062:        }
        !          2063:        rc = pthread_mutex_init(&lu->state_mutex, &istgt->mutex_attr);
        !          2064:        if (rc != 0) {
        !          2065:                ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
        !          2066:                return -1;
        !          2067:        }
        !          2068:        rc = pthread_mutex_init(&lu->queue_mutex, &istgt->mutex_attr);
        !          2069:        if (rc != 0) {
        !          2070:                ISTGT_ERRLOG("LU%d: mutex_init() failed\n", lu->num);
        !          2071:                return -1;
        !          2072:        }
        !          2073:        rc = pthread_cond_init(&lu->queue_cond, NULL);
        !          2074:        if (rc != 0) {
        !          2075:                ISTGT_ERRLOG("LU%d: cond_init() failed\n", lu->num);
        !          2076:                return -1;
        !          2077:        }
        !          2078: 
        !          2079:        switch (lu->type) {
        !          2080:        case ISTGT_LU_TYPE_PASS:
        !          2081:                rc = istgt_lu_pass_init(istgt, lu);
        !          2082:                if (rc < 0) {
        !          2083:                        ISTGT_ERRLOG("LU%d: lu_pass_init() failed\n", lu->num);
        !          2084:                        return -1;
        !          2085:                }
        !          2086:                break;
        !          2087: 
        !          2088:        case ISTGT_LU_TYPE_DISK:
        !          2089:                rc = istgt_lu_disk_init(istgt, lu);
        !          2090:                if (rc < 0) {
        !          2091:                        ISTGT_ERRLOG("LU%d: lu_disk_init() failed\n", lu->num);
        !          2092:                        return -1;
        !          2093:                }
        !          2094:                break;
        !          2095: 
        !          2096:        case ISTGT_LU_TYPE_DVD:
        !          2097:                rc = istgt_lu_dvd_init(istgt, lu);
        !          2098:                if (rc < 0) {
        !          2099:                        ISTGT_ERRLOG("LU%d: lu_dvd_init() failed\n", lu->num);
        !          2100:                        return -1;
        !          2101:                }
        !          2102:                break;
        !          2103: 
        !          2104:        case ISTGT_LU_TYPE_TAPE:
        !          2105:                rc = istgt_lu_tape_init(istgt, lu);
        !          2106:                if (rc < 0) {
        !          2107:                        ISTGT_ERRLOG("LU%d: lu_tape_init() failed\n", lu->num);
        !          2108:                        return -1;
        !          2109:                }
        !          2110:                break;
        !          2111: 
        !          2112:        case ISTGT_LU_TYPE_NONE:
        !          2113:                //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
        !          2114:                break;
        !          2115:        default:
        !          2116:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
        !          2117:                return -1;
        !          2118:        }
        !          2119: 
        !          2120:        return 0;
        !          2121: }
        !          2122: 
1.1       misho    2123: int
                   2124: istgt_lu_init(ISTGT_Ptr istgt)
                   2125: {
                   2126:        ISTGT_LU_Ptr lu;
                   2127:        CF_SECTION *sp;
                   2128:        int rc;
                   2129:        int i;
                   2130: 
                   2131:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_init\n");
                   2132:        sp = istgt_find_cf_section(istgt->config, "Global");
                   2133:        if (sp == NULL) {
                   2134:                ISTGT_ERRLOG("find_cf_section failed()\n");
                   2135:                return -1;
                   2136:        }
                   2137: 
                   2138:        sp = istgt->config->section;
                   2139:        while (sp != NULL) {
                   2140:                if (sp->type == ST_LOGICAL_UNIT) {
                   2141:                        if (sp->num == 0) {
                   2142:                                ISTGT_ERRLOG("Unit 0 is invalid\n");
                   2143:                                return -1;
                   2144:                        }
                   2145:                        if (sp->num > ISTGT_LU_TAG_MAX) {
                   2146:                                ISTGT_ERRLOG("tag %d is invalid\n", sp->num);
                   2147:                                return -1;
                   2148:                        }
                   2149:                        rc = istgt_lu_add_unit(istgt, sp);
                   2150:                        if (rc < 0) {
                   2151:                                ISTGT_ERRLOG("lu_add_unit() failed\n");
                   2152:                                return -1;
                   2153:                        }
                   2154:                }
                   2155:                sp = sp->next;
                   2156:        }
                   2157: 
1.1.1.2 ! misho    2158:        MTX_LOCK(&istgt->mutex);
1.1       misho    2159:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
                   2160:                lu = istgt->logical_unit[i];
                   2161:                if (lu == NULL)
                   2162:                        continue;
1.1.1.2 ! misho    2163:                rc = istgt_lu_init_unit(istgt, lu);
        !          2164:                if (rc < 0) {
        !          2165:                        MTX_UNLOCK(&istgt->mutex);
        !          2166:                        ISTGT_ERRLOG("LU%d: lu_init_unit() failed\n", lu->num);
1.1       misho    2167:                        return -1;
                   2168:                }
1.1.1.2 ! misho    2169:                istgt_lu_set_state(lu, ISTGT_STATE_INITIALIZED);
        !          2170:        }
        !          2171:        MTX_UNLOCK(&istgt->mutex);
1.1       misho    2172: 
1.1.1.2 ! misho    2173:        return 0;
        !          2174: }
        !          2175: 
        !          2176: static int
        !          2177: istgt_lu_exist_num(CONFIG *config, int num)
        !          2178: {
        !          2179:        CF_SECTION *sp;
        !          2180: 
        !          2181:        sp = config->section;
        !          2182:        while (sp != NULL) {
        !          2183:                if (sp->type == ST_LOGICAL_UNIT) {
        !          2184:                        if (sp->num == num) {
        !          2185:                                return 1;
1.1       misho    2186:                        }
1.1.1.2 ! misho    2187:                }
        !          2188:                sp = sp->next;
        !          2189:        }
        !          2190:        return -1;
        !          2191: }
1.1       misho    2192: 
1.1.1.2 ! misho    2193: static int istgt_lu_shutdown_unit(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu);
        !          2194: 
        !          2195: int
        !          2196: istgt_lu_reload_delete(ISTGT_Ptr istgt)
        !          2197: {
        !          2198:        ISTGT_LU_Ptr lu;
        !          2199:        int warn_num, warn_msg;
        !          2200:        int rc;
        !          2201:        int i;
        !          2202: 
        !          2203:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_reload_delete\n");
        !          2204:        warn_num = warn_msg = 0;
        !          2205: retry:
        !          2206:        MTX_LOCK(&istgt->mutex);
        !          2207:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
        !          2208:                lu = istgt->logical_unit[i];
        !          2209:                if (lu == NULL)
        !          2210:                        continue;
        !          2211:                rc = istgt_lu_exist_num(istgt->config, lu->num);
        !          2212:                if (rc < 0) {
        !          2213:                        istgt_lu_set_state(lu, ISTGT_STATE_SHUTDOWN);
        !          2214:                        MTX_LOCK(&lu->mutex);
        !          2215:                        if (lu->maxtsih > 1) {
        !          2216:                                if (!warn_msg) {
        !          2217:                                        warn_msg = 1;
        !          2218:                                        ISTGT_WARNLOG("It is recommended that you disconnect the target before deletion.\n");
        !          2219:                                }
        !          2220:                                if (warn_num != lu->num) {
        !          2221:                                        warn_num = lu->num;
        !          2222:                                        ISTGT_WARNLOG("delete request for active LU%d\n",
        !          2223:                                            lu->num);
        !          2224:                                }
        !          2225:                                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "reload retry for LU%d\n",
        !          2226:                                    lu->num);
        !          2227:                                MTX_UNLOCK(&lu->mutex);
        !          2228:                                MTX_UNLOCK(&istgt->mutex);
        !          2229:                                istgt_yield();
        !          2230:                                sleep(1);
        !          2231:                                goto retry;
        !          2232:                        }
        !          2233:                        MTX_UNLOCK(&lu->mutex);
        !          2234:                        rc = istgt_lu_shutdown_unit(istgt, lu);
1.1       misho    2235:                        if (rc < 0) {
1.1.1.2 ! misho    2236:                                ISTGT_ERRLOG("LU%d: lu_shutdown_unit() failed\n", lu->num);
        !          2237:                                /* ignore error */
1.1       misho    2238:                        }
1.1.1.2 ! misho    2239:                        ISTGT_NOTICELOG("delete LU%d: Name=%s\n", lu->num, lu->name);
        !          2240:                        xfree(lu);
        !          2241:                        istgt->logical_unit[i] = NULL;
        !          2242:                }
        !          2243:        }
        !          2244:        MTX_UNLOCK(&istgt->mutex);
        !          2245:        return 0;
        !          2246: }
1.1       misho    2247: 
1.1.1.2 ! misho    2248: static int
        !          2249: istgt_lu_match_all(CF_SECTION *sp, CONFIG *config_old)
        !          2250: {
        !          2251:        CF_ITEM *ip, *ip_old;
        !          2252:        CF_VALUE *vp, *vp_old;
        !          2253:        CF_SECTION *sp_old;
        !          2254: 
        !          2255:        sp_old = istgt_find_cf_section(config_old, sp->name);
        !          2256:        if (sp_old == NULL)
        !          2257:                return 0;
        !          2258: 
        !          2259:        ip = sp->item;
        !          2260:        ip_old = sp_old->item;
        !          2261:        while (ip != NULL && ip_old != NULL) {
        !          2262:                vp = ip->val;
        !          2263:                vp_old = ip_old->val;
        !          2264:                while (vp != NULL && vp_old != NULL) {
        !          2265:                        if (vp->value != NULL && vp_old->value != NULL) {
        !          2266:                                if (strcmp(vp->value, vp_old->value) != 0)
        !          2267:                                        return 0;
        !          2268:                        } else {
        !          2269:                                return 0;
1.1       misho    2270:                        }
1.1.1.2 ! misho    2271:                        vp = vp->next;
        !          2272:                        vp_old = vp_old->next;
        !          2273:                }
        !          2274:                if (vp != NULL || vp_old != NULL)
        !          2275:                        return 0;
        !          2276:                ip = ip->next;
        !          2277:                ip_old = ip_old->next;
        !          2278:        }
        !          2279:        if (ip != NULL || ip_old != NULL)
        !          2280:                return 0;
        !          2281:        return 1;
        !          2282: }
1.1       misho    2283: 
1.1.1.2 ! misho    2284: static int
        !          2285: istgt_lu_copy_sp(CF_SECTION *sp, CONFIG *config_old)
        !          2286: {
        !          2287:        CF_SECTION *sp_old;
        !          2288: 
        !          2289:        sp_old = istgt_find_cf_section(config_old, sp->name);
        !          2290:        if (sp_old == NULL)
        !          2291:                return -1;
        !          2292:        istgt_copy_cf_item(sp, sp_old);
        !          2293:        return 0;
        !          2294: }
        !          2295: 
        !          2296: static int istgt_lu_create_thread(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu);
        !          2297: 
        !          2298: int
        !          2299: istgt_lu_reload_update(ISTGT_Ptr istgt)
        !          2300: {
        !          2301:        ISTGT_LU_Ptr lu;
        !          2302:        ISTGT_LU_Ptr lu_old;
        !          2303:        CF_SECTION *sp;
        !          2304:        int rc;
        !          2305: 
        !          2306:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_reload_update\n");
        !          2307: 
        !          2308:        sp = istgt->config->section;
        !          2309:        while (sp != NULL) {
        !          2310:                if (sp->type == ST_LOGICAL_UNIT) {
        !          2311:                        if (sp->num == 0) {
        !          2312:                                ISTGT_ERRLOG("Unit 0 is invalid\n");
        !          2313:                                goto skip_lu;
1.1       misho    2314:                        }
1.1.1.2 ! misho    2315:                        if (sp->num > ISTGT_LU_TAG_MAX) {
        !          2316:                                ISTGT_ERRLOG("tag %d is invalid\n", sp->num);
        !          2317:                                goto skip_lu;
        !          2318:                        }
        !          2319: #if 0
        !          2320:                        rc = istgt_lu_exist_num(istgt->config_old, sp->num);
        !          2321: #else
        !          2322:                        rc = -1;
        !          2323:                        MTX_LOCK(&istgt->mutex);
        !          2324:                        lu = istgt->logical_unit[sp->num];
        !          2325:                        if (lu != NULL)
        !          2326:                                rc = 1;
        !          2327:                        MTX_UNLOCK(&istgt->mutex);
        !          2328: #endif
        !          2329:                        if (rc < 0) {
        !          2330:                                rc = istgt_lu_add_unit(istgt, sp);
        !          2331:                                if (rc < 0) {
        !          2332:                                        ISTGT_ERRLOG("lu_add_unit() failed\n");
        !          2333:                                        goto skip_lu;
        !          2334:                                }
        !          2335:                                MTX_LOCK(&istgt->mutex);
        !          2336:                                lu = istgt->logical_unit[sp->num];
        !          2337:                                if (lu == NULL) {
        !          2338:                                        MTX_UNLOCK(&istgt->mutex);
        !          2339:                                        ISTGT_ERRLOG("can't find new LU%d\n", sp->num);
        !          2340:                                        goto skip_lu;
        !          2341:                                }
        !          2342:                                rc = istgt_lu_init_unit(istgt, lu);
        !          2343:                                if (rc < 0) {
        !          2344:                                        MTX_UNLOCK(&istgt->mutex);
        !          2345:                                        ISTGT_ERRLOG("LU%d: lu_init_unit() failed\n", sp->num);
        !          2346:                                        goto skip_lu;
        !          2347:                                }
        !          2348:                                istgt_lu_set_state(lu, ISTGT_STATE_INITIALIZED);
        !          2349: 
        !          2350:                                rc = istgt_lu_create_thread(istgt, lu);
        !          2351:                                if (rc < 0) {
        !          2352:                                        MTX_UNLOCK(&istgt->mutex);
        !          2353:                                        ISTGT_ERRLOG("lu_create_thread() failed\n");
        !          2354:                                        goto skip_lu;
        !          2355:                                }
        !          2356:                                istgt_lu_set_state(lu, ISTGT_STATE_RUNNING);
        !          2357:                                ISTGT_NOTICELOG("add LU%d: Name=%s\n", lu->num, lu->name);
        !          2358:                                MTX_UNLOCK(&istgt->mutex);
        !          2359:                        } else {
        !          2360:                                if (istgt_lu_match_all(sp, istgt->config_old)) {
        !          2361:                                        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
        !          2362:                                            "skip LU%d: Name=%s\n", lu->num, lu->name);
        !          2363:                                } else {
        !          2364:                                        MTX_LOCK(&istgt->mutex);
        !          2365:                                        lu = istgt->logical_unit[sp->num];
        !          2366:                                        if (lu == NULL) {
        !          2367:                                                MTX_UNLOCK(&istgt->mutex);
        !          2368:                                                ISTGT_ERRLOG("can't find LU%d\n", sp->num);
        !          2369:                                                goto skip_lu;
        !          2370:                                        }
        !          2371:                                        MTX_LOCK(&lu->mutex);
        !          2372:                                        if (lu->maxtsih > 1) {
        !          2373:                                                ISTGT_ERRLOG("update active LU%d: Name=%s, "
        !          2374:                                                    "# of TSIH=%d\n",
        !          2375:                                                    lu->num, lu->name, lu->maxtsih - 1);
        !          2376:                                                rc = istgt_lu_copy_sp(sp, istgt->config_old);
        !          2377:                                                if (rc < 0) {
        !          2378:                                                        /* ignore error */
        !          2379:                                                }
        !          2380:                                                MTX_UNLOCK(&lu->mutex);
        !          2381:                                                MTX_UNLOCK(&istgt->mutex);
        !          2382:                                                goto skip_lu;
        !          2383:                                        } else {
        !          2384:                                                istgt->logical_unit[sp->num] = NULL;
        !          2385:                                                MTX_UNLOCK(&lu->mutex);
        !          2386:                                                MTX_UNLOCK(&istgt->mutex);
1.1       misho    2387: 
1.1.1.2 ! misho    2388:                                                /* add new LU */
        !          2389:                                                rc = istgt_lu_add_unit(istgt, sp);
        !          2390:                                                if (rc < 0) {
        !          2391:                                                        ISTGT_ERRLOG("lu_add_unit() failed\n");
        !          2392:                                                        MTX_LOCK(&istgt->mutex);
        !          2393:                                                        istgt->logical_unit[sp->num] = lu;
        !          2394:                                                        MTX_UNLOCK(&istgt->mutex);
        !          2395:                                                        goto skip_lu;
        !          2396:                                                } else {
        !          2397:                                                        /* delete old LU */
        !          2398:                                                        lu_old = lu;
        !          2399:                                                        MTX_LOCK(&istgt->mutex);
        !          2400:                                                        lu = istgt->logical_unit[sp->num];
        !          2401:                                                        istgt_lu_set_state(lu_old,
        !          2402:                                                            ISTGT_STATE_SHUTDOWN);
        !          2403:                                                        rc = istgt_lu_shutdown_unit(istgt,
        !          2404:                                                            lu_old);
        !          2405:                                                        if (rc < 0) {
        !          2406:                                                                ISTGT_ERRLOG(
        !          2407:                                                                        "LU%d: lu_shutdown_unit() "
        !          2408:                                                                        "failed\n", lu->num);
        !          2409:                                                                /* ignore error */
        !          2410:                                                        }
        !          2411:                                                        xfree(lu_old);
        !          2412:                                                        istgt->logical_unit[sp->num] = lu;
        !          2413:                                                        MTX_UNLOCK(&istgt->mutex);
        !          2414:                                                }
        !          2415:                                                MTX_LOCK(&istgt->mutex);
        !          2416:                                                lu = istgt->logical_unit[sp->num];
        !          2417:                                                if (lu == NULL) {
        !          2418:                                                        MTX_UNLOCK(&istgt->mutex);
        !          2419:                                                        ISTGT_ERRLOG("can't find new LU%d\n",
        !          2420:                                                            sp->num);
        !          2421:                                                        goto skip_lu;
        !          2422:                                                }
        !          2423:                                                rc = istgt_lu_init_unit(istgt, lu);
        !          2424:                                                if (rc < 0) {
        !          2425:                                                        MTX_UNLOCK(&istgt->mutex);
        !          2426:                                                        ISTGT_ERRLOG("LU%d: lu_init_unit() "
        !          2427:                                                            "failed\n", sp->num);
        !          2428:                                                        goto skip_lu;
        !          2429:                                                }
        !          2430:                                                istgt_lu_set_state(lu,
        !          2431:                                                    ISTGT_STATE_INITIALIZED);
1.1       misho    2432: 
1.1.1.2 ! misho    2433:                                                rc = istgt_lu_create_thread(istgt, lu);
        !          2434:                                                if (rc < 0) {
        !          2435:                                                        MTX_UNLOCK(&istgt->mutex);
        !          2436:                                                        ISTGT_ERRLOG("lu_create_thread "
        !          2437:                                                            "failed\n");
        !          2438:                                                        goto skip_lu;
        !          2439:                                                }
        !          2440:                                                istgt_lu_set_state(lu, ISTGT_STATE_RUNNING);
        !          2441:                                                ISTGT_NOTICELOG("update LU%d: Name=%s\n",
        !          2442:                                                    lu->num, lu->name);
        !          2443:                                        }
        !          2444:                                        MTX_UNLOCK(&istgt->mutex);
        !          2445:                                }
        !          2446:                        }
        !          2447:                }
        !          2448:        skip_lu:
        !          2449:                sp = sp->next;
1.1       misho    2450:        }
                   2451:        return 0;
                   2452: }
                   2453: 
                   2454: int
                   2455: istgt_lu_set_all_state(ISTGT_Ptr istgt, ISTGT_STATE state)
                   2456: {
                   2457:        ISTGT_LU_Ptr lu;
                   2458:        int i;
                   2459: 
                   2460:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
                   2461:                lu = istgt->logical_unit[i];
                   2462:                if (lu == NULL)
                   2463:                        continue;
                   2464: 
                   2465:                istgt_lu_set_state(lu, state);
                   2466:        }
                   2467: 
                   2468:        return 0;
                   2469: }
                   2470: 
1.1.1.2 ! misho    2471: static int
        !          2472: istgt_lu_create_thread(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
1.1       misho    2473: {
                   2474: #ifdef HAVE_PTHREAD_SET_NAME_NP
                   2475:        char buf[MAX_TMPBUF];
                   2476: #endif
                   2477:        int rc;
                   2478: 
1.1.1.2 ! misho    2479:        if (lu->queue_depth != 0) {
        !          2480:                ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "thread for LU%d\n", lu->num);
        !          2481:                /* create LU thread */
1.1       misho    2482: #ifdef ISTGT_STACKSIZE
1.1.1.2 ! misho    2483:                rc = pthread_create(&lu->thread, &istgt->attr, &luworker, (void *)lu);
1.1       misho    2484: #else
1.1.1.2 ! misho    2485:                rc = pthread_create(&lu->thread, NULL, &luworker, (void *)lu);
1.1       misho    2486: #endif
1.1.1.2 ! misho    2487:                if (rc != 0) {
        !          2488:                        ISTGT_ERRLOG("pthread_create() failed\n");
        !          2489:                        return -1;
        !          2490:                }
1.1       misho    2491: #if 0
1.1.1.2 ! misho    2492:                rc = pthread_detach(lu->thread);
        !          2493:                if (rc != 0) {
        !          2494:                        ISTGT_ERRLOG("pthread_detach() failed\n");
        !          2495:                        return -1;
        !          2496:                }
1.1       misho    2497: #endif
                   2498: #ifdef HAVE_PTHREAD_SET_NAME_NP
1.1.1.2 ! misho    2499:                snprintf(buf, sizeof buf, "luthread #%d", lu->num);
        !          2500:                pthread_set_name_np(lu->thread, buf);
1.1       misho    2501: #endif
                   2502:        }
                   2503: 
                   2504:        return 0;
                   2505: }
                   2506: 
                   2507: int
1.1.1.2 ! misho    2508: istgt_lu_create_threads(ISTGT_Ptr istgt)
1.1       misho    2509: {
                   2510:        ISTGT_LU_Ptr lu;
                   2511:        int rc;
                   2512:        int i;
                   2513: 
1.1.1.2 ! misho    2514:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_create_threads\n");
1.1       misho    2515: 
                   2516:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
                   2517:                lu = istgt->logical_unit[i];
                   2518:                if (lu == NULL)
                   2519:                        continue;
1.1.1.2 ! misho    2520:                rc = istgt_lu_create_thread(istgt, lu);
        !          2521:                if (rc < 0) {
        !          2522:                        ISTGT_ERRLOG("lu_create_thread() failed\n");
        !          2523:                        return -1;
        !          2524:                }
        !          2525:        }
1.1       misho    2526: 
1.1.1.2 ! misho    2527:        return 0;
        !          2528: }
1.1       misho    2529: 
1.1.1.2 ! misho    2530: static int
        !          2531: istgt_lu_shutdown_unit(ISTGT_Ptr istgt, ISTGT_LU_Ptr lu)
        !          2532: {
        !          2533:        int rc;
1.1       misho    2534: 
1.1.1.2 ! misho    2535:        switch (lu->type) {
        !          2536:        case ISTGT_LU_TYPE_PASS:
        !          2537:                rc = istgt_lu_pass_shutdown(istgt, lu);
        !          2538:                if (rc < 0) {
        !          2539:                        ISTGT_ERRLOG("LU%d: lu_pass_shutdown() failed\n", lu->num);
        !          2540:                        /* ignore error */
1.1       misho    2541:                }
1.1.1.2 ! misho    2542:                break;
1.1       misho    2543: 
1.1.1.2 ! misho    2544:        case ISTGT_LU_TYPE_DISK:
        !          2545:                rc = istgt_lu_disk_shutdown(istgt, lu);
1.1       misho    2546:                if (rc < 0) {
1.1.1.2 ! misho    2547:                        ISTGT_ERRLOG("LU%d: lu_disk_shutdown() failed\n", lu->num);
1.1       misho    2548:                        /* ignore error */
                   2549:                }
1.1.1.2 ! misho    2550:                break;
1.1       misho    2551: 
1.1.1.2 ! misho    2552:        case ISTGT_LU_TYPE_DVD:
        !          2553:                rc = istgt_lu_dvd_shutdown(istgt, lu);
        !          2554:                if (rc < 0) {
        !          2555:                        ISTGT_ERRLOG("LU%d: lu_dvd_shutdown() failed\n", lu->num);
1.1       misho    2556:                        /* ignore error */
                   2557:                }
1.1.1.2 ! misho    2558:                break;
        !          2559: 
        !          2560:        case ISTGT_LU_TYPE_TAPE:
        !          2561:                rc = istgt_lu_tape_shutdown(istgt, lu);
        !          2562:                if (rc < 0) {
        !          2563:                        ISTGT_ERRLOG("LU%d: lu_tape_shutdown() failed\n", lu->num);
1.1       misho    2564:                        /* ignore error */
                   2565:                }
1.1.1.2 ! misho    2566:                break;
        !          2567: 
        !          2568:        case ISTGT_LU_TYPE_NONE:
        !          2569:                //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
        !          2570:                break;
        !          2571:        default:
        !          2572:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
        !          2573:                return -1;
        !          2574:        }
        !          2575: 
        !          2576:        rc = istgt_lu_del_unit(istgt, lu);
        !          2577:        if (rc < 0) {
        !          2578:                ISTGT_ERRLOG("LU%d: lu_del_unit() failed\n", lu->num);
        !          2579:                /* ignore error */
        !          2580:        }
        !          2581: 
        !          2582:        if (lu->queue_depth != 0) {
        !          2583:                rc = pthread_cond_broadcast(&lu->queue_cond);
1.1       misho    2584:                if (rc != 0) {
1.1.1.2 ! misho    2585:                        ISTGT_ERRLOG("LU%d: cond_broadcast() failed\n", lu->num);
1.1       misho    2586:                }
1.1.1.2 ! misho    2587:                rc = pthread_join(lu->thread, NULL);
1.1       misho    2588:                if (rc != 0) {
1.1.1.2 ! misho    2589:                        ISTGT_ERRLOG("LU%d: pthread_join() failed\n", lu->num);
        !          2590:                }
        !          2591:        }
        !          2592:        rc = pthread_cond_destroy(&lu->queue_cond);
        !          2593:        if (rc != 0) {
        !          2594:                ISTGT_ERRLOG("LU%d: cond_destroy() failed\n", lu->num);
        !          2595:                /* ignore error */
        !          2596:        }
        !          2597:        rc = pthread_mutex_destroy(&lu->queue_mutex);
        !          2598:        if (rc != 0) {
        !          2599:                ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
        !          2600:                /* ignore error */
        !          2601:        }
        !          2602:        rc = pthread_mutex_destroy(&lu->state_mutex);
        !          2603:        if (rc != 0) {
        !          2604:                ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
        !          2605:                /* ignore error */
        !          2606:        }
        !          2607:        rc = pthread_mutex_destroy(&lu->mutex);
        !          2608:        if (rc != 0) {
        !          2609:                ISTGT_ERRLOG("LU%d: mutex_destroy() failed\n", lu->num);
        !          2610:                /* ignore error */
        !          2611:        }
        !          2612: 
        !          2613:        return 0;
        !          2614: }
        !          2615: 
        !          2616: int
        !          2617: istgt_lu_shutdown(ISTGT_Ptr istgt)
        !          2618: {
        !          2619:        ISTGT_LU_Ptr lu;
        !          2620:        int rc;
        !          2621:        int i;
        !          2622: 
        !          2623:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "istgt_lu_shutdown\n");
        !          2624:        MTX_LOCK(&istgt->mutex);
        !          2625:        for (i = 0; i < MAX_LOGICAL_UNIT; i++) {
        !          2626:                lu = istgt->logical_unit[i];
        !          2627:                if (lu == NULL)
        !          2628:                        continue;
        !          2629:                istgt_lu_set_state(lu, ISTGT_STATE_SHUTDOWN);
        !          2630:                rc = istgt_lu_shutdown_unit(istgt, lu);
        !          2631:                if (rc < 0) {
        !          2632:                        ISTGT_ERRLOG("LU%d: lu_shutdown_unit() failed\n", lu->num);
1.1       misho    2633:                        /* ignore error */
                   2634:                }
                   2635:                xfree(lu);
                   2636:                istgt->logical_unit[i] = NULL;
                   2637:        }
1.1.1.2 ! misho    2638:        MTX_UNLOCK(&istgt->mutex);
1.1       misho    2639: 
                   2640:        return 0;
                   2641: }
                   2642: 
                   2643: int
                   2644: istgt_lu_islun2lun(uint64_t islun)
                   2645: {
                   2646:        uint64_t fmt_lun;
                   2647:        uint64_t method;
                   2648:        int lun_i;
                   2649: 
                   2650:        fmt_lun = islun;
                   2651:        method = (fmt_lun >> 62) & 0x03U;
                   2652:        fmt_lun = fmt_lun >> 48;
                   2653:        if (method == 0x00U) {
                   2654:                lun_i = (int) (fmt_lun & 0x00ffU);
                   2655:        } else if (method == 0x01U) {
                   2656:                lun_i = (int) (fmt_lun & 0x3fffU);
                   2657:        } else {
                   2658:                lun_i = 0xffffU;
                   2659:        }
                   2660:        return lun_i;
                   2661: }
                   2662: 
                   2663: uint64_t
                   2664: istgt_lu_lun2islun(int lun, int maxlun)
                   2665: {
                   2666:        uint64_t fmt_lun;
                   2667:        uint64_t method;
                   2668:        uint64_t islun;
                   2669: 
                   2670:        islun = (uint64_t) lun;
                   2671:        if (maxlun <= 0x0100) {
                   2672:                /* below 256 */
                   2673:                method = 0x00U;
                   2674:                fmt_lun = (method & 0x03U) << 62;
                   2675:                fmt_lun |= (islun & 0x00ffU) << 48;
1.1.1.2 ! misho    2676:        } else if (maxlun <= 0x4000) {
1.1       misho    2677:                /* below 16384 */
                   2678:                method = 0x01U;
                   2679:                fmt_lun = (method & 0x03U) << 62;
                   2680:                fmt_lun |= (islun & 0x3fffU) << 48;
                   2681:        } else {
                   2682:                /* XXX */
                   2683:                fmt_lun = ~((uint64_t) 0);
                   2684:        }
                   2685:        return fmt_lun;
                   2686: }
                   2687: 
                   2688: int
                   2689: istgt_lu_reset(ISTGT_LU_Ptr lu, uint64_t lun)
                   2690: {
                   2691:        int lun_i;
                   2692:        int rc;
                   2693: 
                   2694:        if (lu == NULL)
                   2695:                return -1;
                   2696: 
                   2697:        lun_i = istgt_lu_islun2lun(lun);
                   2698: 
                   2699:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d: Name=%s, LUN=%d\n",
                   2700:            lu->num, lu->name, lun_i);
                   2701: 
                   2702:        switch (lu->type) {
                   2703:        case ISTGT_LU_TYPE_PASS:
                   2704:                MTX_LOCK(&lu->mutex);
                   2705:                rc = istgt_lu_pass_reset(lu, lun_i);
                   2706:                MTX_UNLOCK(&lu->mutex);
                   2707:                if (rc < 0) {
                   2708:                        ISTGT_ERRLOG("LU%d: lu_pass_reset() failed\n", lu->num);
                   2709:                        return -1;
                   2710:                }
                   2711:                break;
                   2712: 
                   2713:        case ISTGT_LU_TYPE_DISK:
                   2714:                MTX_LOCK(&lu->mutex);
                   2715:                rc = istgt_lu_disk_reset(lu, lun_i);
                   2716:                MTX_UNLOCK(&lu->mutex);
                   2717:                if (rc < 0) {
                   2718:                        ISTGT_ERRLOG("LU%d: lu_disk_reset() failed\n", lu->num);
                   2719:                        return -1;
                   2720:                }
                   2721:                break;
                   2722: 
                   2723:        case ISTGT_LU_TYPE_DVD:
                   2724:                MTX_LOCK(&lu->mutex);
                   2725:                rc = istgt_lu_dvd_reset(lu, lun_i);
                   2726:                MTX_UNLOCK(&lu->mutex);
                   2727:                if (rc < 0) {
                   2728:                        ISTGT_ERRLOG("LU%d: lu_dvd_reset() failed\n", lu->num);
                   2729:                        return -1;
                   2730:                }
                   2731:                break;
                   2732: 
                   2733:        case ISTGT_LU_TYPE_TAPE:
                   2734:                MTX_LOCK(&lu->mutex);
                   2735:                rc = istgt_lu_tape_reset(lu, lun_i);
                   2736:                MTX_UNLOCK(&lu->mutex);
                   2737:                if (rc < 0) {
                   2738:                        ISTGT_ERRLOG("LU%d: lu_tape_reset() failed\n", lu->num);
                   2739:                        return -1;
                   2740:                }
                   2741:                break;
                   2742: 
                   2743:        case ISTGT_LU_TYPE_NONE:
                   2744:                //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
                   2745:                break;
                   2746:        default:
                   2747:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   2748:                return -1;
                   2749:        }
                   2750: 
                   2751:        return 0;
                   2752: }
                   2753: 
                   2754: int
                   2755: istgt_lu_execute(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd)
                   2756: {
                   2757:        ISTGT_LU_Ptr lu;
                   2758:        int rc;
                   2759: 
                   2760:        if (lu_cmd == NULL)
                   2761:                return -1;
                   2762:        lu = lu_cmd->lu;
                   2763:        if (lu == NULL)
                   2764:                return -1;
                   2765: 
                   2766:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG,
                   2767:            "LU%d: PG=0x%4.4x, Name=%s, LUN=0x%16.16"PRIx64"\n",
                   2768:            lu->num, conn->portal.tag, lu->name, lu_cmd->lun);
                   2769: 
                   2770:        if (lu->online == 0) {
                   2771:                ISTGT_TRACELOG(ISTGT_TRACE_SCSI, "LU%d: offline\n", lu->num);
                   2772:                /* LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE */
                   2773:                lu_cmd->sense_data_len
                   2774:                        = istgt_lu_scsi_build_sense_data(lu_cmd->sense_data,
                   2775:                            ISTGT_SCSI_SENSE_NOT_READY,
                   2776:                            0x04, 0x00);
                   2777:                lu_cmd->status = ISTGT_SCSI_STATUS_CHECK_CONDITION;
                   2778:                return 0;
                   2779:        }
                   2780: 
                   2781:        rc = 0;
                   2782:        switch (lu->type) {
                   2783:        case ISTGT_LU_TYPE_PASS:
                   2784:                MTX_LOCK(&lu->mutex);
                   2785:                rc = istgt_lu_pass_execute(conn, lu_cmd);
                   2786:                MTX_UNLOCK(&lu->mutex);
                   2787:                if (rc < 0) {
                   2788:                        ISTGT_ERRLOG("LU%d: lu_pass_execute() failed\n",
                   2789:                            lu->num);
                   2790:                        return -1;
                   2791:                }
                   2792:                break;
                   2793: 
                   2794:        case ISTGT_LU_TYPE_DISK:
                   2795:                if (lu->queue_depth != 0) {
                   2796:                        rc = istgt_lu_disk_queue(conn, lu_cmd);
                   2797:                        if (rc < 0) {
                   2798:                                ISTGT_ERRLOG("LU%d: lu_disk_queue() failed\n",
                   2799:                                    lu->num);
                   2800:                                return -1;
                   2801:                        }
                   2802:                } else {
                   2803:                        MTX_LOCK(&lu->mutex);
                   2804:                        rc = istgt_lu_disk_execute(conn, lu_cmd);
                   2805:                        MTX_UNLOCK(&lu->mutex);
                   2806:                        if (rc < 0) {
                   2807:                                ISTGT_ERRLOG("LU%d: lu_disk_execute() failed\n",
                   2808:                                    lu->num);
                   2809:                                return -1;
                   2810:                        }
                   2811:                }
                   2812:                break;
                   2813: 
                   2814:        case ISTGT_LU_TYPE_DVD:
                   2815:                MTX_LOCK(&lu->mutex);
                   2816:                rc = istgt_lu_dvd_execute(conn, lu_cmd);
                   2817:                MTX_UNLOCK(&lu->mutex);
                   2818:                if (rc < 0) {
                   2819:                        ISTGT_ERRLOG("LU%d: lu_dvd_execute() failed\n",
                   2820:                            lu->num);
                   2821:                        return -1;
                   2822:                }
                   2823:                break;
                   2824: 
                   2825:        case ISTGT_LU_TYPE_TAPE:
                   2826:                MTX_LOCK(&lu->mutex);
                   2827:                rc = istgt_lu_tape_execute(conn, lu_cmd);
                   2828:                MTX_UNLOCK(&lu->mutex);
                   2829:                if (rc < 0) {
                   2830:                        ISTGT_ERRLOG("LU%d: lu_tape_execute() failed\n",
                   2831:                            lu->num);
                   2832:                        return -1;
                   2833:                }
                   2834:                break;
                   2835: 
                   2836:        case ISTGT_LU_TYPE_NONE:
                   2837:                //ISTGT_ERRLOG("LU%d: dummy type\n", lu->num);
                   2838:                break;
                   2839:        default:
                   2840:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   2841:                return -1;
                   2842:        }
                   2843: 
                   2844:        return rc;
                   2845: }
                   2846: 
                   2847: int
                   2848: istgt_lu_create_task(CONN_Ptr conn, ISTGT_LU_CMD_Ptr lu_cmd, ISTGT_LU_TASK_Ptr lu_task, int lun)
                   2849: {
                   2850:        ISCSI_PDU_Ptr dst_pdu, src_pdu;
                   2851:        uint8_t *cdb;
                   2852:        int alloc_len;
                   2853: #if 0
                   2854:        int rc;
                   2855: #endif
                   2856: 
                   2857:        if (lu_task == NULL)
                   2858:                return -1;
                   2859: 
                   2860:        lu_task->type = ISTGT_LU_TASK_RESPONSE;
                   2861:        lu_task->conn = conn;
                   2862:        strncpy(lu_task->initiator_name, conn->initiator_name,
                   2863:            sizeof lu_task->initiator_name);
                   2864:        strncpy(lu_task->initiator_port, conn->initiator_port,
                   2865:            sizeof lu_task->initiator_port);
                   2866: 
                   2867:        lu_task->lun = (int) lun;
                   2868:        lu_task->use_cond = 0;
                   2869:        lu_task->dup_iobuf = 0;
                   2870:        lu_task->iobuf = NULL;
                   2871:        lu_task->data = NULL;
                   2872:        lu_task->sense_data = NULL;
1.1.1.2 ! misho    2873:        lu_task->alloc_len = 0;
1.1       misho    2874:        lu_task->create_time = 0;
                   2875:        lu_task->condwait = 0;
                   2876:        lu_task->offset = 0;
                   2877:        lu_task->req_execute = 0;
                   2878:        lu_task->req_transfer_out = 0;
                   2879:        lu_task->error = 0;
                   2880:        lu_task->abort = 0;
                   2881:        lu_task->execute = 0;
                   2882:        lu_task->complete = 0;
                   2883:        lu_task->lock = 0;
                   2884: 
                   2885: #if 0
                   2886:        rc = pthread_mutex_init(&lu_task->trans_mutex, NULL);
                   2887:        if (rc != 0) {
                   2888:                ISTGT_ERRLOG("mutex_init() failed\n");
                   2889:                return -1;
                   2890:        }
                   2891:        rc = pthread_cond_init(&lu_task->trans_cond, NULL);
                   2892:        if (rc != 0) {
                   2893:                ISTGT_ERRLOG("cond_init() failed\n");
                   2894:                return -1;
                   2895:        }
                   2896:        rc = pthread_cond_init(&lu_task->exec_cond, NULL);
                   2897:        if (rc != 0) {
                   2898:                ISTGT_ERRLOG("cond_init() failed\n");
                   2899:                return -1;
                   2900:        }
                   2901: #endif
                   2902: 
                   2903:        lu_task->lu_cmd.pdu = xmalloc(sizeof *lu_task->lu_cmd.pdu);
                   2904:        memset(lu_task->lu_cmd.pdu, 0, sizeof *lu_task->lu_cmd.pdu);
                   2905: 
                   2906:        /* copy PDU */
                   2907:        dst_pdu = lu_task->lu_cmd.pdu;
                   2908:        src_pdu = lu_cmd->pdu;
                   2909:        memcpy(&dst_pdu->bhs, &src_pdu->bhs, ISCSI_BHS_LEN);
                   2910:        dst_pdu->ahs = src_pdu->ahs;
                   2911:        memcpy(dst_pdu->header_digest, src_pdu->header_digest, ISCSI_DIGEST_LEN);
                   2912:        if (src_pdu->data == src_pdu->shortdata) {
                   2913:                memcpy(dst_pdu->shortdata, src_pdu->shortdata,
                   2914:                    sizeof src_pdu->shortdata);
                   2915:                dst_pdu->data = dst_pdu->shortdata;
                   2916:        } else {
                   2917:                dst_pdu->data = src_pdu->data;
                   2918:        }
                   2919:        memcpy(dst_pdu->data_digest, src_pdu->data_digest, ISCSI_DIGEST_LEN);
                   2920:        dst_pdu->total_ahs_len = src_pdu->total_ahs_len;
                   2921:        dst_pdu->data_segment_len = src_pdu->data_segment_len;
                   2922:        dst_pdu->copy_pdu = 0;
                   2923:        src_pdu->copy_pdu = 1;
                   2924: 
                   2925:        /* copy other lu_cmd */
                   2926:        lu_task->lu_cmd.lu = lu_cmd->lu;
                   2927:        cdb = ((uint8_t *) &lu_task->lu_cmd.pdu->bhs) + 32;
                   2928:        lu_task->lu_cmd.I_bit = lu_cmd->I_bit;
                   2929:        lu_task->lu_cmd.F_bit = lu_cmd->F_bit;
                   2930:        lu_task->lu_cmd.R_bit = lu_cmd->R_bit;
                   2931:        lu_task->lu_cmd.W_bit = lu_cmd->W_bit;
                   2932:        lu_task->lu_cmd.Attr_bit = lu_cmd->Attr_bit;
                   2933:        lu_task->lu_cmd.lun = lu_cmd->lun;
                   2934:        lu_task->lu_cmd.task_tag = lu_cmd->task_tag;
                   2935:        lu_task->lu_cmd.transfer_len = lu_cmd->transfer_len;
                   2936:        //lu_task->lu_cmd.cdb = lu_cmd->cdb;
                   2937:        lu_task->lu_cmd.cdb = cdb;
                   2938:        lu_task->lu_cmd.CmdSN = lu_cmd->CmdSN;
                   2939: 
                   2940:        //lu_task->lu_cmd.iobuf = lu_cmd->iobuf;
                   2941:        lu_task->lu_cmd.iobuf = NULL;
                   2942:        lu_task->lu_cmd.iobufsize = lu_cmd->iobufsize;
                   2943:        lu_task->lu_cmd.data = lu_cmd->data;
                   2944:        lu_task->lu_cmd.data_len = lu_cmd->data_len;
                   2945:        lu_task->lu_cmd.alloc_len = lu_cmd->alloc_len;
                   2946: 
                   2947:        lu_task->lu_cmd.status = lu_cmd->status;
                   2948:        lu_task->lu_cmd.sense_data = lu_cmd->sense_data;
                   2949:        lu_task->lu_cmd.sense_data_len = lu_cmd->sense_data_len;
                   2950:        lu_task->lu_cmd.sense_alloc_len = lu_cmd->sense_alloc_len;
                   2951: 
                   2952:        /* pre allocate buffer */
                   2953:        lu_task->lu_cmd.iobufsize = lu_cmd->transfer_len + 65536;
                   2954: #if 0
                   2955:        lu_task->data = xmalloc(lu_cmd->alloc_len);
                   2956:        lu_task->sense_data = xmalloc(lu_cmd->sense_alloc_len);
                   2957:        lu_task->iobuf = xmalloc(lu_task->lu_cmd.iobufsize);
                   2958: #else
                   2959:        alloc_len = ISCSI_ALIGN(lu_cmd->alloc_len);
                   2960:        alloc_len += ISCSI_ALIGN(lu_cmd->sense_alloc_len);
                   2961:        alloc_len += ISCSI_ALIGN(lu_task->lu_cmd.iobufsize);
                   2962:        lu_task->data = xmalloc(alloc_len);
                   2963:        lu_task->sense_data = lu_task->data + ISCSI_ALIGN(lu_cmd->alloc_len);
                   2964:        lu_task->iobuf = lu_task->sense_data + ISCSI_ALIGN(lu_cmd->sense_alloc_len);
1.1.1.2 ! misho    2965:        lu_task->alloc_len = alloc_len;
1.1       misho    2966: #endif
                   2967: 
                   2968:        /* creation time */
                   2969:        lu_task->create_time = time(NULL);
                   2970:        /* wait time */
                   2971:        lu_task->condwait = conn->timeout * 1000;
                   2972:        if (lu_task->condwait < ISTGT_CONDWAIT_MIN) {
                   2973:                lu_task->condwait = ISTGT_CONDWAIT_MIN;
                   2974:        }
                   2975: 
                   2976:        return 0;
                   2977: }
                   2978: 
                   2979: int
                   2980: istgt_lu_destroy_task(ISTGT_LU_TASK_Ptr lu_task)
                   2981: {
                   2982:        int rc;
                   2983: 
                   2984:        if (lu_task == NULL)
                   2985:                return -1;
                   2986: 
                   2987:        if (lu_task->use_cond != 0) {
                   2988:                rc = pthread_mutex_destroy(&lu_task->trans_mutex);
                   2989:                if (rc != 0) {
                   2990:                        ISTGT_ERRLOG("mutex_destroy() failed\n");
                   2991:                        return -1;
                   2992:                }
                   2993:                rc = pthread_cond_destroy(&lu_task->trans_cond);
                   2994:                if (rc != 0) {
                   2995:                        ISTGT_ERRLOG("cond_destroy() failed\n");
                   2996:                        return -1;
                   2997:                }
                   2998:                rc = pthread_cond_destroy(&lu_task->exec_cond);
                   2999:                if (rc != 0) {
                   3000:                        ISTGT_ERRLOG("cond_destroy() failed\n");
                   3001:                        return -1;
                   3002:                }
                   3003:        }
                   3004:        if (lu_task->lu_cmd.pdu != NULL) {
                   3005:                if (lu_task->lu_cmd.pdu->copy_pdu == 0) {
                   3006:                        xfree(lu_task->lu_cmd.pdu->ahs);
                   3007:                        if (lu_task->lu_cmd.pdu->data
                   3008:                            != lu_task->lu_cmd.pdu->shortdata) {
                   3009:                                xfree(lu_task->lu_cmd.pdu->data);
                   3010:                        }
                   3011:                }
                   3012:                xfree(lu_task->lu_cmd.pdu);
                   3013:        }
                   3014: #if 0
                   3015:        if (lu_task->dup_iobuf == 0) {
                   3016:                xfree(lu_task->iobuf);
                   3017:        }
                   3018:        xfree(lu_task->data);
                   3019:        xfree(lu_task->sense_data);
                   3020: #else
                   3021:        xfree(lu_task->data);
                   3022: #endif
                   3023:        xfree(lu_task);
                   3024:        return 0;
                   3025: }
                   3026: 
                   3027: int
                   3028: istgt_lu_clear_task_IT(CONN_Ptr conn, ISTGT_LU_Ptr lu)
                   3029: {
                   3030:        int rc;
                   3031: 
                   3032:        if (lu == NULL)
                   3033:                return -1;
                   3034: 
                   3035:        if (lu->queue_depth == 0)
                   3036:                return 0;
                   3037: 
                   3038:        rc = 0;
                   3039:        switch (lu->type) {
                   3040:        case ISTGT_LU_TYPE_DISK:
                   3041:                MTX_LOCK(&lu->mutex);
                   3042:                rc = istgt_lu_disk_queue_clear_IT(conn, lu);
                   3043:                MTX_UNLOCK(&lu->mutex);
                   3044:                if (rc < 0) {
                   3045:                        ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_IT() failed\n", lu->num);
                   3046:                        return -1;
                   3047:                }
                   3048:                break;
                   3049: 
                   3050:        case ISTGT_LU_TYPE_DVD:
                   3051:        case ISTGT_LU_TYPE_TAPE:
                   3052:        case ISTGT_LU_TYPE_NONE:
                   3053:        default:
                   3054:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   3055:                return -1;
                   3056:        }
                   3057: 
                   3058:        return 0;
                   3059: }
                   3060: 
                   3061: int
                   3062: istgt_lu_clear_task_ITL(CONN_Ptr conn, ISTGT_LU_Ptr lu, uint64_t lun)
                   3063: {
                   3064:        int lun_i;
                   3065:        int rc;
                   3066: 
                   3067:        if (lu == NULL)
                   3068:                return -1;
                   3069: 
                   3070:        if (lu->queue_depth == 0)
                   3071:                return 0;
                   3072: 
                   3073:        lun_i = istgt_lu_islun2lun(lun);
                   3074: 
                   3075:        rc = 0;
                   3076:        switch (lu->type) {
                   3077:        case ISTGT_LU_TYPE_DISK:
                   3078:                MTX_LOCK(&lu->mutex);
                   3079:                rc = istgt_lu_disk_queue_clear_ITL(conn, lu, lun_i);
                   3080:                MTX_UNLOCK(&lu->mutex);
                   3081:                if (rc < 0) {
                   3082:                        ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_ITL() failed\n", lu->num);
                   3083:                        return -1;
                   3084:                }
                   3085:                break;
                   3086: 
                   3087:        case ISTGT_LU_TYPE_DVD:
                   3088:        case ISTGT_LU_TYPE_TAPE:
                   3089:        case ISTGT_LU_TYPE_NONE:
                   3090:        default:
                   3091:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   3092:                return -1;
                   3093:        }
                   3094: 
                   3095:        return 0;
                   3096: }
                   3097: 
                   3098: int
                   3099: istgt_lu_clear_task_ITLQ(CONN_Ptr conn, ISTGT_LU_Ptr lu, uint64_t lun, uint32_t CmdSN)
                   3100: {
                   3101:        int lun_i;
                   3102:        int rc;
                   3103: 
                   3104:        if (lu == NULL)
                   3105:                return -1;
                   3106: 
                   3107:        if (lu->queue_depth == 0)
                   3108:                return 0;
                   3109: 
                   3110:        lun_i = istgt_lu_islun2lun(lun);
                   3111: 
                   3112:        rc = 0;
                   3113:        switch (lu->type) {
                   3114:        case ISTGT_LU_TYPE_DISK:
                   3115:                MTX_LOCK(&lu->mutex);
                   3116:                rc = istgt_lu_disk_queue_clear_ITLQ(conn, lu, lun_i, CmdSN);
                   3117:                MTX_UNLOCK(&lu->mutex);
                   3118:                if (rc < 0) {
                   3119:                        ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_ITLQ() failed\n", lu->num);
                   3120:                        return -1;
                   3121:                }
                   3122:                break;
                   3123: 
                   3124:        case ISTGT_LU_TYPE_DVD:
                   3125:        case ISTGT_LU_TYPE_TAPE:
                   3126:        case ISTGT_LU_TYPE_NONE:
                   3127:        default:
                   3128:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   3129:                return -1;
                   3130:        }
                   3131: 
                   3132:        return 0;
                   3133: }
                   3134: 
                   3135: int
                   3136: istgt_lu_clear_all_task(ISTGT_LU_Ptr lu, uint64_t lun)
                   3137: {
                   3138:        int rc;
                   3139: 
                   3140:        if (lu == NULL)
                   3141:                return -1;
                   3142: 
                   3143:        if (lu->queue_depth == 0)
                   3144:                return 0;
                   3145: 
                   3146:        rc = 0;
                   3147:        switch (lu->type) {
                   3148:        case ISTGT_LU_TYPE_DISK:
                   3149:                MTX_LOCK(&lu->mutex);
                   3150:                rc = istgt_lu_disk_queue_clear_all(lu, lun);
                   3151:                MTX_UNLOCK(&lu->mutex);
                   3152:                if (rc < 0) {
                   3153:                        ISTGT_ERRLOG("LU%d: lu_disk_queue_clear_all() failed\n", lu->num);
                   3154:                        return -1;
                   3155:                }
                   3156:                break;
                   3157: 
                   3158:        case ISTGT_LU_TYPE_DVD:
                   3159:        case ISTGT_LU_TYPE_TAPE:
                   3160:        case ISTGT_LU_TYPE_NONE:
                   3161:        default:
                   3162:                ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   3163:                return -1;
                   3164:        }
                   3165: 
                   3166:        return 0;
                   3167: }
                   3168: 
                   3169: static void *
                   3170: luworker(void *arg)
                   3171: {
                   3172:        ISTGT_LU_Ptr lu = (ISTGT_LU_Ptr) arg;
                   3173:        sigset_t signew, sigold;
                   3174: #if 0
                   3175:        struct timespec abstime;
                   3176:        time_t now;
                   3177:        int timeout = 20; /* XXX */
                   3178: #endif
                   3179:        int qcnt;
                   3180:        int lun;
                   3181:        int rc;
                   3182: 
                   3183:        sigemptyset(&signew);
                   3184:        sigemptyset(&sigold);
                   3185:        sigaddset(&signew, ISTGT_SIGWAKEUP);
                   3186:        pthread_sigmask(SIG_UNBLOCK, &signew, &sigold);
                   3187: 
                   3188:        while (istgt_get_state(lu->istgt) != ISTGT_STATE_RUNNING) {
                   3189:                if (istgt_get_state(lu->istgt) == ISTGT_STATE_EXITING
                   3190:                    || istgt_get_state(lu->istgt) == ISTGT_STATE_SHUTDOWN) {
                   3191:                        ISTGT_ERRLOG("exit before running\n");
                   3192:                        return NULL;
                   3193:                }
                   3194:                //ISTGT_WARNLOG("Wait for running\n");
                   3195:                sleep(1);
                   3196:                continue;
                   3197:        }
                   3198: 
                   3199:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d loop start\n", lu->num);
                   3200:        lun = 0;
                   3201:        qcnt = 0;
                   3202: #if 0
                   3203:        memset(&abstime, 0, sizeof abstime);
                   3204: #endif
                   3205:        while (1) {
                   3206:                switch (lu->type) {
                   3207:                case ISTGT_LU_TYPE_DISK:
                   3208:                        while (1) {
                   3209:                                if (istgt_lu_get_state(lu) != ISTGT_STATE_RUNNING) {
                   3210:                                        goto loop_exit;
                   3211:                                }
                   3212:                                qcnt = istgt_lu_disk_queue_count(lu, &lun);
                   3213:                                if (qcnt == 0) {
1.1.1.2 ! misho    3214:                                        MTX_LOCK(&lu->queue_mutex);
        !          3215:                                        if (lu->queue_check != 0) {
        !          3216:                                                lu->queue_check = 0;
        !          3217:                                                MTX_UNLOCK(&lu->queue_mutex);
        !          3218:                                                continue;
        !          3219:                                        }
1.1       misho    3220: #if 0
                   3221:                                        now = time(NULL);
                   3222:                                        abstime.tv_sec = now + timeout;
                   3223:                                        abstime.tv_nsec = 0;
                   3224:                                        rc = pthread_cond_timedwait(&lu->queue_cond,
                   3225:                                            &lu->queue_mutex, &abstime);
                   3226:                                        if (rc == ETIMEDOUT) {
                   3227:                                                /* nothing */
                   3228:                                        }
                   3229: #else
                   3230:                                        pthread_cond_wait(&lu->queue_cond,
                   3231:                                            &lu->queue_mutex);
                   3232: #endif
1.1.1.2 ! misho    3233:                                        lu->queue_check = 0;
        !          3234:                                        MTX_UNLOCK(&lu->queue_mutex);
1.1       misho    3235:                                        qcnt = istgt_lu_disk_queue_count(lu, &lun);
                   3236:                                        if (qcnt == 0) {
                   3237:                                                continue;
                   3238:                                        }
                   3239:                                }
                   3240:                                break;
                   3241:                        }
                   3242:                        if (qcnt < 0) {
                   3243:                                ISTGT_ERRLOG("LU%d: lu_disk_queue_count() failed\n",
                   3244:                                    lu->num);
                   3245:                                break;
                   3246:                        }
                   3247:                        rc = istgt_lu_disk_queue_start(lu, lun);
1.1.1.2 ! misho    3248:                        if (rc == 0 && qcnt >= 2) {
        !          3249:                                qcnt--;
        !          3250:                                rc = istgt_lu_disk_queue_start(lu, lun);
        !          3251:                        }
1.1       misho    3252:                        lun++;
                   3253:                        if (rc == -2) {
                   3254:                                ISTGT_WARNLOG("LU%d: lu_disk_queue_start() aborted\n",
                   3255:                                    lu->num);
                   3256:                                break;
                   3257:                        }
                   3258:                        if (rc < 0) {
                   3259:                                ISTGT_ERRLOG("LU%d: lu_disk_queue_start() failed\n",
                   3260:                                    lu->num);
                   3261:                                break;
                   3262:                        }
                   3263:                        break;
                   3264: 
                   3265:                case ISTGT_LU_TYPE_DVD:
                   3266:                case ISTGT_LU_TYPE_TAPE:
                   3267:                case ISTGT_LU_TYPE_NONE:
                   3268:                default:
                   3269:                        ISTGT_ERRLOG("LU%d: unsupported type\n", lu->num);
                   3270:                        return NULL;
                   3271:                }
                   3272: 
                   3273: #if 0
                   3274:                /* still running? */
                   3275:                if (qcnt <= 1) {
                   3276:                        if (istgt_lu_get_state(lu) != ISTGT_STATE_RUNNING) {
                   3277:                                goto loop_exit;
                   3278:                        }
                   3279:                }
                   3280: #endif
                   3281:        }
                   3282:  loop_exit:
                   3283:        ISTGT_TRACELOG(ISTGT_TRACE_DEBUG, "LU%d loop ended\n", lu->num);
                   3284: 
                   3285:        return NULL;
                   3286: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>