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>