1 /* $NetBSD: disk.c,v 1.9 2014/09/30 15:25:18 mlelstv Exp $ */ 2 3 /*- 4 * Copyright (c) 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Alistair Crooks (agc@netbsd.org) 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 33 * By downloading, copying, installing or using the software you agree 34 * to this license. If you do not agree to this license, do not 35 * download, install, copy or use the software. 36 * 37 * Intel License Agreement 38 * 39 * Copyright (c) 2000, Intel Corporation 40 * All rights reserved. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 46 * -Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 49 * -Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the 52 * distribution. 53 * 54 * -The name of Intel Corporation may not be used to endorse or 55 * promote products derived from this software without specific prior 56 * written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 59 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 60 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 61 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL 62 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 63 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 64 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 65 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 66 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 67 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 68 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 */ 71 #include "config.h" 72 73 #ifdef HAVE_INTTYPES_H 74 #include <inttypes.h> 75 #endif 76 77 #include <sys/types.h> 78 79 #ifdef HAVE_SYS_PARAM_H 80 #include <sys/param.h> 81 #endif 82 83 #ifdef HAVE_SYS_STAT_H 84 #include <sys/stat.h> 85 #endif 86 87 #ifdef HAVE_SYS_UIO_H 88 #include <sys/uio.h> 89 #endif 90 91 #ifdef HAVE_SYS_TIME_H 92 #include <sys/time.h> 93 #endif 94 95 #ifdef HAVE_SYS_MMAN_H 96 #include <sys/mman.h> 97 #endif 98 99 #ifdef HAVE_NETINET_IN_H 100 #include <netinet/in.h> 101 #endif 102 103 #include <assert.h> 104 105 #ifdef HAVE_ERRNO_H 106 #include <errno.h> 107 #endif 108 109 #ifdef HAVE_FCNTL_H 110 #include <fcntl.h> 111 #endif 112 113 #include <ctype.h> 114 #include <stdio.h> 115 #include <stdlib.h> 116 117 #ifdef HAVE_STRING_H 118 #include <string.h> 119 #endif 120 121 #include <unistd.h> 122 123 #include "scsi_cmd_codes.h" 124 125 #include "iscsiprotocol.h" 126 #include "compat.h" 127 #include "iscsiutil.h" 128 #include "device.h" 129 #include "target.h" 130 #include "defs.h" 131 #include "storage.h" 132 133 #define iSCSI_DEFAULT_LUNS 1 134 #define iSCSI_DEFAULT_BLOCKLEN 512 135 136 /* End disk configuration */ 137 138 /* 139 * Globals 140 */ 141 enum { 142 MAX_RESERVATIONS = 32, 143 144 ISCSI_FS = 0x03, 145 ISCSI_CONTROL = 0x04 146 }; 147 148 #define MB(x) ((x) * 1024 * 1024) 149 150 /* this struct describes an iscsi LUN */ 151 typedef struct iscsi_disk_t { 152 int type; /* type of disk - fs/mmap and fs */ 153 char filename[MAXPATHLEN]; /* filename for the disk */ 154 uint64_t blockc; /* # of blocks */ 155 uint64_t blocklen; /* block size */ 156 uint64_t luns; /* # of luns */ 157 uint64_t size; /* size of complete disk */ 158 nbuuid_t uuid; /* disk's uuid */ 159 char *uuid_string; /* uuid string */ 160 targv_t *lunv; /* the component devices and extents */ 161 uint32_t resc; /* # of reservation keys */ 162 uint64_t reskeys[MAX_RESERVATIONS]; /* reservation keys */ 163 } iscsi_disk_t; 164 165 DEFINE_ARRAY(disks_t, iscsi_disk_t); 166 167 static disks_t disks; 168 static iscsi_disk_t defaults; 169 170 #ifndef FDATASYNC 171 /* 172 this means that we probably don't have the fsync_range(2) system call, 173 but no matter - define this here to preserve the abstraction for the 174 disk/extent code 175 */ 176 #define FDATASYNC 0x0010 177 #endif 178 179 /* 180 * Private Interface 181 */ 182 static int disk_read(target_session_t *, iscsi_scsi_cmd_args_t *, 183 uint32_t, uint16_t, uint8_t); 184 static int disk_write(target_session_t *, iscsi_scsi_cmd_args_t *, 185 uint8_t, uint32_t, uint32_t); 186 187 /* return the de index and offset within the device for RAID0 */ 188 static int 189 raid0_getoff(disc_device_t *dp, uint64_t off, uint32_t *d, uint64_t *de_off) 190 { 191 uint64_t o; 192 193 for (o = 0, *d = 0 ; *d < dp->c ; o += dp->xv[*d].size, (*d)++) { 194 if (off >= o && off < o + dp->xv[*d].size) { 195 break; 196 } 197 } 198 *de_off = off - o; 199 return (*d < dp->c); 200 } 201 202 /* open the extent's device */ 203 static int 204 extent_open(disc_extent_t *xp, int mode, int flags) 205 { 206 return xp->fd = open(xp->dev, mode, flags); 207 } 208 209 /* (recursively) open the device's devices */ 210 static int 211 device_open(disc_device_t *dp, int flags, int mode) 212 { 213 int fd; 214 uint32_t i; 215 216 for (fd = -1, i = 0 ; i < dp->c ; i++) { 217 switch (dp->xv[i].type) { 218 case DE_DEVICE: 219 fd = device_open(dp->xv[i].u.dp, flags, mode); 220 if (fd < 0) { 221 return -1; 222 } 223 break; 224 case DE_EXTENT: 225 fd = extent_open(dp->xv[i].u.xp, flags, mode); 226 if (fd < 0) { 227 return -1; 228 } 229 break; 230 default: 231 break; 232 } 233 } 234 return fd; 235 } 236 237 /* and for the undecided... */ 238 static int 239 de_open(disc_de_t *dp, int flags, int mode) 240 { 241 switch(dp->type) { 242 case DE_DEVICE: 243 return device_open(dp->u.dp, flags, mode); 244 case DE_EXTENT: 245 return extent_open(dp->u.xp, flags, mode); 246 default: 247 return -1; 248 } 249 } 250 251 /* lseek on the extent */ 252 static off_t 253 extent_lseek(disc_extent_t *xp, off_t off, int whence) 254 { 255 return lseek(xp->fd, (long long)(xp->sacred + off), whence); 256 } 257 258 /* (recursively) lseek on the device's devices */ 259 static off_t 260 device_lseek(disc_device_t *dp, off_t off, int whence) 261 { 262 uint64_t suboff; 263 off_t ret; 264 uint32_t d; 265 266 ret = -1; 267 switch(dp->raid) { 268 case 0: 269 if (raid0_getoff(dp, (uint64_t) off, &d, &suboff)) { 270 switch (dp->xv[d].type) { 271 case DE_DEVICE: 272 ret = device_lseek(dp->xv[d].u.dp, 273 (off_t) suboff, whence); 274 if (ret < 0) { 275 return -1; 276 } 277 break; 278 case DE_EXTENT: 279 ret = extent_lseek(dp->xv[d].u.xp, 280 (off_t) suboff, whence); 281 if (ret < 0) { 282 return -1; 283 } 284 break; 285 default: 286 break; 287 } 288 } 289 break; 290 case 1: 291 for (d = 0 ; d < dp->c ; d++) { 292 switch (dp->xv[d].type) { 293 case DE_DEVICE: 294 ret = device_lseek(dp->xv[d].u.dp, (off_t)off, 295 whence); 296 if (ret < 0) { 297 return -1; 298 } 299 break; 300 case DE_EXTENT: 301 ret = extent_lseek(dp->xv[d].u.xp, (off_t)off, 302 whence); 303 if (ret < 0) { 304 return -1; 305 } 306 break; 307 default: 308 break; 309 } 310 } 311 break; 312 default: 313 break; 314 } 315 return dp->off = ret; 316 } 317 318 /* and for the undecided... */ 319 static off_t 320 de_lseek(disc_de_t *dp, off_t off, int whence) 321 { 322 switch(dp->type) { 323 case DE_DEVICE: 324 return device_lseek(dp->u.dp, off, whence); 325 case DE_EXTENT: 326 return extent_lseek(dp->u.xp, off, whence); 327 default: 328 return -1; 329 } 330 } 331 332 /* fsync_range on the extent */ 333 static int 334 extent_fsync_range(disc_extent_t *xp, int how, off_t from, off_t len) 335 { 336 #ifdef HAVE_FSYNC_RANGE 337 return fsync_range(xp->fd, how, (off_t)(xp->sacred + from), len); 338 #else 339 return fsync(xp->fd); 340 #endif 341 } 342 343 /* (recursively) fsync_range on the device's devices */ 344 static int 345 device_fsync_range(disc_device_t *dp, int how, off_t from, off_t len) 346 { 347 uint64_t suboff; 348 int ret; 349 uint32_t d; 350 351 ret = -1; 352 switch(dp->raid) { 353 case 0: 354 if (raid0_getoff(dp, (uint64_t) from, &d, &suboff)) { 355 switch (dp->xv[d].type) { 356 case DE_DEVICE: 357 ret = device_fsync_range(dp->xv[d].u.dp, how, 358 (off_t)suboff, len); 359 if (ret < 0) { 360 return -1; 361 } 362 break; 363 case DE_EXTENT: 364 ret = extent_fsync_range(dp->xv[d].u.xp, how, 365 (off_t)suboff, len); 366 if (ret < 0) { 367 return -1; 368 } 369 break; 370 default: 371 break; 372 } 373 } 374 break; 375 case 1: 376 for (d = 0 ; d < dp->c ; d++) { 377 switch (dp->xv[d].type) { 378 case DE_DEVICE: 379 ret = device_fsync_range(dp->xv[d].u.dp, how, 380 from, len); 381 if (ret < 0) { 382 return -1; 383 } 384 break; 385 case DE_EXTENT: 386 ret = extent_fsync_range(dp->xv[d].u.xp, how, 387 from, len); 388 if (ret < 0) { 389 return -1; 390 } 391 break; 392 default: 393 break; 394 } 395 } 396 break; 397 default: 398 break; 399 } 400 dp->off = (uint64_t) ret; 401 return ret; 402 } 403 404 /* and for the undecided... */ 405 static int 406 de_fsync_range(disc_de_t *dp, int how, off_t from, off_t len) 407 { 408 switch(dp->type) { 409 case DE_DEVICE: 410 return device_fsync_range(dp->u.dp, how, from, len); 411 case DE_EXTENT: 412 return extent_fsync_range(dp->u.xp, how, from, len); 413 default: 414 return -1; 415 } 416 } 417 418 /* read from the extent */ 419 static ssize_t 420 extent_read(disc_extent_t *xp, void *buf, size_t cc) 421 { 422 return read(xp->fd, buf, cc); 423 } 424 425 /* (recursively) read from the device's devices */ 426 static ssize_t 427 device_read(disc_device_t *dp, void *buf, size_t cc) 428 { 429 uint64_t suboff; 430 uint64_t got; 431 uint32_t d; 432 ssize_t ret; 433 size_t subcc; 434 char *cbuf; 435 436 ret = -1; 437 switch(dp->raid) { 438 case 0: 439 for (cbuf = (char *) buf, got = 0 ; got < cc ; got += ret) { 440 if (!raid0_getoff(dp, dp->off, &d, &suboff)) { 441 return -1; 442 } 443 if (device_lseek(dp, (off_t)dp->off, SEEK_SET) < 0) { 444 return -1; 445 } 446 subcc = MIN(cc - (size_t)got, 447 (size_t)(dp->len - (size_t)dp->off)); 448 switch (dp->xv[d].type) { 449 case DE_DEVICE: 450 ret = device_read(dp->xv[d].u.dp, 451 &cbuf[(int)got], subcc); 452 if (ret < 0) { 453 return -1; 454 } 455 break; 456 case DE_EXTENT: 457 ret = extent_read(dp->xv[d].u.xp, 458 &cbuf[(int)got], subcc); 459 if (ret < 0) { 460 return -1; 461 } 462 break; 463 default: 464 break; 465 } 466 dp->off += ret; 467 } 468 ret = (ssize_t)got; 469 break; 470 case 1: 471 for (d = 0 ; d < dp->c ; d++) { 472 switch (dp->xv[d].type) { 473 case DE_DEVICE: 474 ret = device_read(dp->xv[d].u.dp, buf, cc); 475 if (ret < 0) { 476 return -1; 477 } 478 break; 479 case DE_EXTENT: 480 ret = extent_read(dp->xv[d].u.xp, buf, cc); 481 if (ret < 0) { 482 return -1; 483 } 484 break; 485 default: 486 break; 487 } 488 } 489 dp->off += ret; 490 break; 491 default: 492 break; 493 } 494 return ret; 495 } 496 497 /* and for the undecided... */ 498 static ssize_t 499 de_read(disc_de_t *dp, void *buf, size_t cc) 500 { 501 switch(dp->type) { 502 case DE_DEVICE: 503 return device_read(dp->u.dp, buf, cc); 504 case DE_EXTENT: 505 return extent_read(dp->u.xp, buf, cc); 506 default: 507 return -1; 508 } 509 } 510 511 /* write to the extent */ 512 static ssize_t 513 extent_write(disc_extent_t *xp, void *buf, size_t cc) 514 { 515 return write(xp->fd, buf, cc); 516 } 517 518 /* (recursively) write to the device's devices */ 519 static ssize_t 520 device_write(disc_device_t *dp, void *buf, size_t cc) 521 { 522 uint64_t suboff; 523 uint64_t done; 524 uint32_t d; 525 ssize_t ret; 526 size_t subcc; 527 char *cbuf; 528 529 ret = -1; 530 switch(dp->raid) { 531 case 0: 532 for (cbuf = (char *) buf, done = 0 ; done < cc ; done += ret) { 533 if (!raid0_getoff(dp, dp->off, &d, &suboff)) { 534 return -1; 535 } 536 subcc = (size_t)MIN(cc - (size_t)done, 537 (size_t)(dp->len - dp->off)); 538 if (device_lseek(dp, (off_t)dp->off, SEEK_SET) < 0) { 539 return -1; 540 } 541 switch (dp->xv[d].type) { 542 case DE_DEVICE: 543 ret = device_write(dp->xv[d].u.dp, 544 &cbuf[(int)done], subcc); 545 if (ret < 0) { 546 return -1; 547 } 548 break; 549 case DE_EXTENT: 550 ret = extent_write(dp->xv[d].u.xp, 551 &cbuf[(int)done], subcc); 552 if (ret < 0) { 553 return -1; 554 } 555 break; 556 default: 557 break; 558 } 559 dp->off += ret; 560 } 561 ret = (ssize_t) done; 562 break; 563 case 1: 564 for (d = 0 ; d < dp->c ; d++) { 565 switch (dp->xv[d].type) { 566 case DE_DEVICE: 567 ret = device_write(dp->xv[d].u.dp, buf, cc); 568 if (ret < 0) { 569 iscsi_err(__FILE__, __LINE__, 570 "device_write RAID1 device " 571 "write failure\n"); 572 return -1; 573 } 574 break; 575 case DE_EXTENT: 576 ret = extent_write(dp->xv[d].u.xp, buf, cc); 577 if (ret < 0) { 578 iscsi_err(__FILE__, __LINE__, 579 "device_write RAID1 extent " 580 "write failure\n"); 581 return -1; 582 } 583 break; 584 default: 585 break; 586 } 587 } 588 dp->off += ret; 589 break; 590 default: 591 break; 592 } 593 return ret; 594 } 595 596 /* and for the undecided... */ 597 static ssize_t 598 de_write(disc_de_t *dp, void *buf, size_t cc) 599 { 600 switch(dp->type) { 601 case DE_DEVICE: 602 return device_write(dp->u.dp, buf, cc); 603 case DE_EXTENT: 604 return extent_write(dp->u.xp, buf, cc); 605 default: 606 return -1; 607 } 608 } 609 610 /* return non-zero if the target is writable */ 611 static int 612 target_writable(disc_target_t *tp) 613 { 614 return !(tp->flags & TARGET_READONLY); 615 } 616 617 /* return size of the extent */ 618 static uint64_t 619 extent_getsize(disc_extent_t *xp) 620 { 621 return xp->len; 622 } 623 624 /* (recursively) return the size of the device's devices */ 625 static uint64_t 626 device_getsize(disc_device_t *dp) 627 { 628 uint64_t size; 629 uint32_t d; 630 631 size = 0; 632 switch(dp->raid) { 633 case 0: 634 for (d = 0 ; d < dp->c ; d++) { 635 switch (dp->xv[d].type) { 636 case DE_DEVICE: 637 size += device_getsize(dp->xv[d].u.dp); 638 break; 639 case DE_EXTENT: 640 size += extent_getsize(dp->xv[d].u.xp); 641 break; 642 default: 643 break; 644 } 645 } 646 break; 647 case 1: 648 size = dp->len; 649 break; 650 default: 651 break; 652 } 653 return size; 654 } 655 656 /* and for the undecided... */ 657 static int64_t 658 de_getsize(disc_de_t *dp) 659 { 660 switch(dp->type) { 661 case DE_DEVICE: 662 return device_getsize(dp->u.dp); 663 case DE_EXTENT: 664 return extent_getsize(dp->u.xp); 665 default: 666 return -1; 667 } 668 } 669 670 /* return a filename for the device or extent */ 671 static char * 672 disc_get_filename(disc_de_t *de) 673 { 674 switch (de->type) { 675 case DE_EXTENT: 676 return de->u.xp->dev; 677 case DE_DEVICE: 678 return disc_get_filename(&de->u.dp->xv[0]); 679 default: 680 return NULL; 681 } 682 } 683 684 /* 685 * Public Interface (called by utarget and ktarket) 686 */ 687 688 /* set various global variables */ 689 void 690 device_set_var(const char *var, const char *arg) 691 { 692 if (strcmp(var, "blocklen") == 0) { 693 defaults.blocklen = strtoll(arg, (char **)NULL, 10); 694 } else if (strcmp(var, "blocks") == 0) { 695 defaults.blockc = strtoll(arg, (char **)NULL, 10); 696 } else if (strcmp(var, "luns") == 0) { 697 defaults.luns = strtoll(arg, (char **)NULL, 10); 698 } else { 699 (void) fprintf(stderr, "Unrecognised variable: `%s'\n", var); 700 } 701 } 702 703 /* allocate some space for a disk/extent, using an lseek, read and 704 * write combination */ 705 static int 706 de_allocate(disc_de_t *de, char *filename, uint64_t blocklen) 707 { 708 off_t size; 709 char *block; 710 711 block = malloc(blocklen); 712 size = de_getsize(de); 713 if (de_lseek(de, size - blocklen, SEEK_SET) == -1) { 714 iscsi_err(__FILE__, __LINE__, 715 "error seeking \"%s\"\n", filename); 716 free(block); 717 return 0; 718 } 719 if (de_read(de, block, blocklen) == -1) { 720 iscsi_err(__FILE__, __LINE__, 721 "error reading \"%s\"\n", filename); 722 free(block); 723 return 0; 724 } 725 if (de_write(de, block, blocklen) == -1) { 726 iscsi_err(__FILE__, __LINE__, 727 "error writing \"%s\"\n", filename); 728 free(block); 729 return 0; 730 } 731 free(block); 732 return 1; 733 } 734 735 /* allocate space as desired */ 736 static int 737 allocate_space(disc_target_t *tp, uint64_t blocklen) 738 { 739 uint32_t i; 740 741 /* Don't perform check for writability in the target here, as the 742 following write() in de_allocate is non-destructive */ 743 switch(tp->de.type) { 744 case DE_EXTENT: 745 return de_allocate(&tp->de, tp->target, blocklen); 746 case DE_DEVICE: 747 for (i = 0 ; i < tp->de.u.dp->c ; i++) { 748 if (!de_allocate(&tp->de.u.dp->xv[i], tp->target, blocklen)) { 749 return 0; 750 } 751 } 752 return 1; 753 default: 754 break; 755 } 756 return 0; 757 } 758 759 /* copy src to dst, of size `n' bytes, padding any extra with `pad' */ 760 static void 761 strpadcpy(uint8_t *dst, size_t dstlen, const char *src, const size_t srclen, 762 char pad) 763 { 764 if (srclen < dstlen) { 765 (void) memcpy(dst, src, srclen); 766 (void) memset(&dst[srclen], pad, dstlen - srclen); 767 } else { 768 (void) memcpy(dst, src, dstlen); 769 } 770 } 771 772 /* handle REPORT LUNs SCSI command */ 773 static int 774 report_luns(uint8_t *data, uint64_t luns) 775 { 776 uint64_t i; 777 uint32_t len; 778 779 len = 8; 780 for (i = 0; i < luns; i++) { 781 uint8_t *p = &data[len]; 782 783 if (i < 256) { 784 memset(p, 0, 8); 785 p[1] = (uint8_t)(i & 0xff); 786 len += 8; 787 } else if (i < 16384) { 788 memset(p, 0, 8); 789 p[0] = (uint8_t)(0x40 | ((i >> 8) & 0x3f)); 790 p[1] = (uint8_t)(i & 0xff); 791 len += 8; 792 } else { 793 /* XXX */ 794 } 795 } 796 *((uint32_t *)(void *)data) = ISCSI_HTONL(len - 8); 797 memset(&data[4], 0, 4); 798 return len; 799 } 800 801 /* handle persistent reserve in command */ 802 static int 803 persistent_reserve_in(uint8_t action, uint8_t *data) 804 { 805 uint64_t key; 806 807 switch(action) { 808 case PERSISTENT_RESERVE_IN_READ_KEYS: 809 key = 0; /* simulate "just powered on" */ 810 *((uint32_t *)(void *)data) = 811 (uint32_t)ISCSI_HTONL((uint32_t) 0); 812 *((uint32_t *) (void *)data + 4) = 813 (uint32_t) ISCSI_HTONL((uint32_t) sizeof(key)); 814 /* length in bytes of list of keys */ 815 *((uint64_t *) (void *)data + 8) = (uint64_t) ISCSI_HTONLL(key); 816 return 8 + sizeof(key); 817 case PERSISTENT_RESERVE_IN_REPORT_CAPABILITIES: 818 (void) memset(data, 0x0, 8); 819 /* length is fixed at 8 bytes */ 820 *((uint16_t *)(void *)data) = 821 (uint16_t)ISCSI_HTONS((uint16_t)8); 822 data[2] = PERSISTENT_RESERVE_IN_CRH; 823 /* also SIP_C, ATP_C and PTPL_C here */ 824 data[3] = 0; /* also TMV and PTPL_A here */ 825 data[4] = 0; 826 /* also WR_EX_AR, EX_AC_RD, WR_EX_RD, EX_AC, WR_EX */ 827 data[5] = 0; /* also EX_AC_AR here */ 828 return 8; 829 default: 830 iscsi_err(__FILE__, __LINE__, 831 "persistent_reserve_in: action %x unrecognised\n", 832 action); 833 return 0; 834 } 835 } 836 837 /* initialise the device */ 838 int 839 device_init(iscsi_target_t *tgt, targv_t *tvp, disc_target_t *tp) 840 { 841 iscsi_disk_t *idisk; 842 int mode; 843 844 ALLOC(iscsi_disk_t, disks.v, disks.size, disks.c, 10, 10, 845 "device_init", ;); 846 idisk = &disks.v[disks.c]; 847 idisk->lunv = tvp; 848 if ((idisk->luns = defaults.luns) == 0) { 849 idisk->luns = iSCSI_DEFAULT_LUNS; 850 } 851 idisk->blocklen = atoi(iscsi_target_getvar(tgt, "blocklen")); 852 switch(idisk->blocklen) { 853 case 512: 854 case 1024: 855 case 2048: 856 case 4096: 857 case 8192: 858 break; 859 default: 860 iscsi_err(__FILE__, __LINE__, 861 "Invalid block len %" PRIu64 862 ". Choose one of 512, 1024, 2048, 4096, or 8192.\n", 863 idisk->blocklen); 864 return -1; 865 } 866 idisk->size = de_getsize(&tp->de); 867 idisk->blockc = idisk->size / idisk->blocklen; 868 idisk->type = ISCSI_FS; 869 printf("DISK: %" PRIu64 " logical unit%s (%" PRIu64 " blocks, %" 870 PRIu64 " bytes/block), type %s\n", 871 idisk->luns, 872 (idisk->luns == 1) ? "" : "s", 873 idisk->blockc, idisk->blocklen, 874 (idisk->type == ISCSI_FS) ? "iscsi fs" : 875 "iscsi fs mmap"); 876 printf("DISK: LUN 0: "); 877 (void) strlcpy(idisk->filename, disc_get_filename(&tp->de), 878 sizeof(idisk->filename)); 879 mode = (tp->flags & TARGET_READONLY) ? O_RDONLY : (O_CREAT | O_RDWR); 880 if (de_open(&tp->de, mode, 0666) == -1) { 881 iscsi_err(__FILE__, __LINE__, 882 "error opening \"%s\"\n", idisk->filename); 883 return -1; 884 } 885 if (!(tp->flags & TARGET_READONLY) && !allocate_space(tp, idisk->blocklen)) { 886 iscsi_err(__FILE__, __LINE__, 887 "error allocating space for \"%s\"\n", tp->target); 888 return -1; 889 } 890 printf("%" PRIu64 " MB %sdisk storage for \"%s\"\n", 891 (de_getsize(&tp->de) / MB(1)), 892 (tp->flags & TARGET_READONLY) ? "readonly " : "", 893 tp->target); 894 return disks.c++; 895 } 896 897 static void 898 cdb2lba(uint32_t *lba, uint16_t *len, uint8_t *cdb) 899 { 900 /* Some platforms (like strongarm) aligns on */ 901 /* word boundaries. So HTONL and NTOHL won't */ 902 /* work here. */ 903 int little_endian = 1; 904 905 if (*(char *) (void *) &little_endian) { 906 /* little endian */ 907 ((uint8_t *) (void *) lba)[0] = cdb[5]; 908 ((uint8_t *) (void *) lba)[1] = cdb[4]; 909 ((uint8_t *) (void *) lba)[2] = cdb[3]; 910 ((uint8_t *) (void *) lba)[3] = cdb[2]; 911 ((uint8_t *) (void *) len)[0] = cdb[8]; 912 ((uint8_t *) (void *) len)[1] = cdb[7]; 913 } else { 914 ((uint8_t *) (void *) lba)[0] = cdb[2]; 915 ((uint8_t *) (void *) lba)[1] = cdb[3]; 916 ((uint8_t *) (void *) lba)[2] = cdb[4]; 917 ((uint8_t *) (void *) lba)[3] = cdb[5]; 918 ((uint8_t *) (void *) len)[0] = cdb[7]; 919 ((uint8_t *) (void *) len)[1] = cdb[8]; 920 } 921 } 922 923 /* handle MODE_SENSE_6 and MODE_SENSE_10 commands */ 924 static int 925 mode_sense(const int bytes, target_cmd_t *cmd) 926 { 927 iscsi_scsi_cmd_args_t *args = cmd->scsi_cmd; 928 uint16_t len; 929 uint8_t *cp; 930 uint8_t *cdb = args->cdb; 931 size_t mode_data_len; 932 933 switch(bytes) { 934 case 6: 935 cp = args->send_data; 936 len = ISCSI_MODE_SENSE_LEN; 937 mode_data_len = len + 3; 938 939 iscsi_trace(TRACE_SCSI_CMD, "MODE_SENSE_6\n"); 940 (void) memset(cp, 0x0, mode_data_len); 941 942 cp[0] = mode_data_len; 943 cp[1] = 0; 944 cp[2] = 0; 945 cp[3] = 8; /* block descriptor length */ 946 cp[10] = 2; /* density code and block length */ 947 948 args->input = 1; 949 args->length = (unsigned)len; 950 args->status = SCSI_SUCCESS; 951 return 1; 952 case 10: 953 cp = args->send_data; 954 len = ISCSI_MODE_SENSE_LEN; 955 mode_data_len = len + 3; 956 957 iscsi_trace(TRACE_SCSI_CMD, "MODE_SENSE_10\n"); 958 (void) memset(cp, 0x0, mode_data_len); 959 if (cdb[4] == 0) { 960 /* zero length cdb means just return success */ 961 args->input = 1; 962 args->length = (unsigned)(mode_data_len); 963 args->status = SCSI_SUCCESS; 964 return 1; 965 } 966 if ((cdb[2] & PAGE_CONTROL_MASK) == 967 PAGE_CONTROL_CHANGEABLE_VALUES) { 968 /* just send back a CHECK CONDITION */ 969 args->input = 1; 970 args->length = (unsigned)(len); 971 args->status = SCSI_CHECK_CONDITION; 972 cp[2] = SCSI_SKEY_ILLEGAL_REQUEST; 973 cp[12] = ASC_LUN_UNSUPPORTED; 974 cp[13] = ASCQ_LUN_UNSUPPORTED; 975 return 1; 976 } 977 iscsi_trace(TRACE_SCSI_CMD, "PC %02x\n", cdb[2]); 978 979 cp[0] = mode_data_len; 980 cp[1] = 0; 981 cp[2] = 0; 982 cp[3] = 8; /* block descriptor length */ 983 cp[10] = 2; /* density code and block length */ 984 985 args->input = 1; 986 args->length = (unsigned)(len); 987 args->status = SCSI_SUCCESS; 988 return 1; 989 } 990 return 0; 991 } 992 993 /* fill in the device serial number vital product data */ 994 static uint8_t 995 serial_vpd(uint8_t *data) 996 { 997 uint8_t len; 998 999 data[0] = DISK_PERIPHERAL_DEVICE; 1000 data[1] = INQUIRY_DEVICE_IDENTIFICATION_VPD; 1001 len = 16; 1002 /* add target device's Unit Serial Number */ 1003 /* section 7.6.10 of SPC-3 says that if there is no serial number, 1004 * use spaces */ 1005 strpadcpy(&data[4], (size_t)len, " ", strlen(" "), ' '); 1006 return len; 1007 } 1008 1009 /* fill in the device identification vital product data */ 1010 static void 1011 device_vpd(iscsi_target_t *tgt, uint8_t *data, uint8_t *rspc, 1012 uint8_t *cdbsize, uint8_t lun, char *uuid) 1013 { 1014 uint16_t len; 1015 uint8_t *cp; 1016 1017 data[0] = DISK_PERIPHERAL_DEVICE; 1018 data[1] = INQUIRY_DEVICE_IDENTIFICATION_VPD; 1019 *rspc = 0; 1020 cp = &data[4]; 1021 /* add target device's IQN */ 1022 cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | 1023 INQUIRY_DEVICE_CODESET_UTF8; 1024 cp[1] = (INQUIRY_DEVICE_PIV << 7) | 1025 (INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE << 4) | 1026 INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME; 1027 len = (uint8_t) snprintf((char *)&cp[4], 1028 (unsigned)(*cdbsize - (int)(cp - &data[4])), "%s", 1029 iscsi_target_getvar(tgt, "iqn")); 1030 cp[3] = len; 1031 *rspc += len + 4; 1032 cp += len + 4; 1033 /* add target port's IQN + LUN */ 1034 cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | 1035 INQUIRY_DEVICE_CODESET_UTF8; 1036 cp[1] = (INQUIRY_DEVICE_PIV << 7) | 1037 (INQUIRY_DEVICE_ASSOCIATION_TARGET_PORT << 4) | 1038 INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME; 1039 len = (uint8_t) snprintf((char *)&cp[4], 1040 (unsigned)(*cdbsize - (int)(cp - &data[4])), 1041 "%s,t,%#x", 1042 iscsi_target_getvar(tgt, "iqn"), 1043 lun); 1044 cp[3] = len; 1045 *rspc += len + 4; 1046 cp += len + 4; 1047 /* add target port's IQN + LUN extension */ 1048 cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | 1049 INQUIRY_DEVICE_CODESET_UTF8; 1050 cp[1] = (INQUIRY_DEVICE_PIV << 7) | 1051 (INQUIRY_DEVICE_ASSOCIATION_LOGICAL_UNIT << 4) | 1052 INQUIRY_DEVICE_IDENTIFIER_SCSI_NAME; 1053 len = (uint8_t) snprintf((char *)&cp[4], 1054 (unsigned) (*cdbsize - (int)(cp - &data[4])), 1055 "%s,L,0x%8.8s%4.4s%4.4s", 1056 iscsi_target_getvar(tgt, "iqn"), 1057 uuid, &uuid[9], &uuid[14]); 1058 cp[3] = len; 1059 *rspc += len + 4; 1060 cp += len + 4; 1061 /* add target's uuid as a T10 identifier */ 1062 cp[0] = (INQUIRY_DEVICE_ISCSI_PROTOCOL << 4) | 1063 INQUIRY_DEVICE_CODESET_UTF8; 1064 cp[1] = (INQUIRY_DEVICE_PIV << 7) | 1065 (INQUIRY_DEVICE_ASSOCIATION_TARGET_DEVICE << 4) | 1066 INQUIRY_IDENTIFIER_TYPE_T10; 1067 strpadcpy(&cp[4], 8, ISCSI_VENDOR, strlen(ISCSI_VENDOR), ' '); 1068 len = 8; 1069 len += (uint8_t) snprintf((char *)&cp[8 + 4], 1070 (unsigned)(*cdbsize - (int)(cp - &data[4])), 1071 "0x%8.8s%4.4s%4.4s", 1072 uuid, &uuid[9], &uuid[14]); 1073 cp[3] = len; 1074 *rspc += len + 4; 1075 } 1076 1077 static void 1078 version_inquiry(uint8_t *data, uint8_t *cdbsize) 1079 { 1080 char versionstr[8]; 1081 1082 data[0] = DISK_PERIPHERAL_DEVICE; 1083 data[2] = SCSI_VERSION_SPC; 1084 data[4] = *cdbsize - 4; /* Additional length */ 1085 data[7] |= (WIDE_BUS_32 | WIDE_BUS_16); 1086 strpadcpy(&data[8], 8, ISCSI_VENDOR, strlen(ISCSI_VENDOR), ' '); 1087 strpadcpy(&data[16], 16, ISCSI_PRODUCT, strlen(ISCSI_PRODUCT), ' '); 1088 (void) snprintf(versionstr, sizeof(versionstr), "%d", ISCSI_VERSION); 1089 strpadcpy(&data[32], 4, versionstr, strlen(versionstr), ' '); 1090 } 1091 1092 int 1093 device_command(target_session_t *sess, target_cmd_t *cmd) 1094 { 1095 iscsi_scsi_cmd_args_t *args = cmd->scsi_cmd; 1096 uint32_t status; 1097 uint32_t lba; 1098 uint16_t len; 1099 uint8_t *cdbsize; 1100 uint8_t *rspc; 1101 uint8_t *data; 1102 uint8_t *cdb; 1103 uint8_t lun; 1104 1105 cdb = args->cdb; 1106 lun = (uint8_t) (args->lun >> 48); 1107 cdbsize = &cdb[4]; 1108 1109 /* 1110 * added section to return no device equivalent for lun request 1111 * beyond available lun 1112 */ 1113 if (lun >= disks.v[sess->d].luns) { 1114 data = args->send_data; 1115 (void) memset(data, 0x0, (size_t) *cdbsize); 1116 /* 1117 * data[0] = 0x7F; means no device 1118 */ 1119 data[0] = 0x1F; /* device type */ 1120 data[0] |= 0x60;/* peripheral qualifier */ 1121 args->input = 1; 1122 args->length = cdb[4] + 1; 1123 args->status = SCSI_SUCCESS; 1124 return 0; 1125 } 1126 1127 lun = (uint8_t) sess->d; 1128 iscsi_trace(TRACE_SCSI_CMD, "SCSI op %#x (lun %d): \n", cdb[0], lun); 1129 1130 switch (cdb[0]) { 1131 case TEST_UNIT_READY: 1132 iscsi_trace(TRACE_SCSI_CMD, "TEST_UNIT_READY\n"); 1133 args->status = SCSI_SUCCESS; 1134 args->length = 0; 1135 break; 1136 1137 case INQUIRY: 1138 iscsi_trace(TRACE_SCSI_CMD, "INQUIRY%s\n", 1139 (cdb[1] & INQUIRY_EVPD_BIT) ? 1140 " for Vital Product Data" : ""); 1141 data = args->send_data; 1142 args->status = SCSI_SUCCESS; 1143 /* Clear allocated buffer */ 1144 (void) memset(data, 0x0, (unsigned) *cdbsize); 1145 if (cdb[1] & INQUIRY_EVPD_BIT) { 1146 rspc = &data[3]; 1147 switch(cdb[2]) { 1148 case INQUIRY_UNIT_SERIAL_NUMBER_VPD: 1149 *rspc = serial_vpd(data); 1150 args->length = 16; 1151 break; 1152 case INQUIRY_DEVICE_IDENTIFICATION_VPD: 1153 if (disks.v[sess->d].uuid_string == NULL) { 1154 nbuuid_create(&disks.v[sess->d].uuid, 1155 &status); 1156 nbuuid_to_string(&disks.v[sess->d].uuid, 1157 &disks.v[sess->d].uuid_string, 1158 &status); 1159 } 1160 device_vpd(sess->target, data, rspc, cdbsize, 1161 lun, disks.v[sess->d].uuid_string); 1162 args->length = *rspc + 6; 1163 break; 1164 case INQUIRY_SUPPORTED_VPD_PAGES: 1165 data[0] = DISK_PERIPHERAL_DEVICE; 1166 data[1] = INQUIRY_SUPPORTED_VPD_PAGES; 1167 *rspc = 3; /* # of supported pages */ 1168 data[4] = INQUIRY_SUPPORTED_VPD_PAGES; 1169 data[5] = INQUIRY_DEVICE_IDENTIFICATION_VPD; 1170 data[6] = EXTENDED_INQUIRY_DATA_VPD; 1171 args->length = *cdbsize + 1; 1172 break; 1173 case EXTENDED_INQUIRY_DATA_VPD: 1174 data[0] = DISK_PERIPHERAL_DEVICE; 1175 data[1] = EXTENDED_INQUIRY_DATA_VPD; 1176 data[3] = 0x3c; /* length is defined to be 60 */ 1177 data[4] = 0; 1178 data[5] = 0; 1179 args->length = 64; 1180 break; 1181 default: 1182 iscsi_err(__FILE__, __LINE__, 1183 "Unsupported INQUIRY VPD page %x\n", 1184 cdb[2]); 1185 args->status = SCSI_CHECK_CONDITION; 1186 break; 1187 } 1188 } else { 1189 version_inquiry(data, cdbsize); 1190 args->length = cdb[4] + 1; 1191 } 1192 if (args->status == SCSI_SUCCESS) { 1193 args->input = 1; 1194 } 1195 break; 1196 1197 case MODE_SELECT_6: 1198 iscsi_trace(TRACE_SCSI_CMD, "MODE_SELECT_6\n"); 1199 args->status = SCSI_SUCCESS; 1200 args->length = 0; 1201 break; 1202 1203 case STOP_START_UNIT: 1204 iscsi_trace(TRACE_SCSI_CMD, "STOP_START_UNIT\n"); 1205 args->status = SCSI_SUCCESS; 1206 args->length = 0; 1207 break; 1208 1209 case READ_CAPACITY: 1210 iscsi_trace(TRACE_SCSI_CMD, "READ_CAPACITY\n"); 1211 data = args->send_data; 1212 *((uint32_t *)(void *)data) = (uint32_t) ISCSI_HTONL( 1213 (uint32_t) disks.v[sess->d].blockc - 1); 1214 /* Max LBA */ 1215 *((uint32_t *)(void *)(data + 4)) = (uint32_t) ISCSI_HTONL( 1216 (uint32_t) disks.v[sess->d].blocklen); 1217 /* Block len */ 1218 args->input = 8; 1219 args->length = 8; 1220 args->status = SCSI_SUCCESS; 1221 break; 1222 1223 case WRITE_6: 1224 lba = ISCSI_NTOHL(*((uint32_t *) (void *)cdb)) & 0x001fffff; 1225 if ((len = *cdbsize) == 0) { 1226 len = 256; 1227 } 1228 iscsi_trace(TRACE_SCSI_CMD, 1229 "WRITE_6(lba %u, len %u blocks)\n", lba, len); 1230 if (disk_write(sess, args, lun, lba, (unsigned) len) != 0) { 1231 iscsi_err(__FILE__, __LINE__, 1232 "disk_write() failed\n"); 1233 args->status = SCSI_CHECK_CONDITION; 1234 } 1235 args->length = 0; 1236 break; 1237 1238 1239 case READ_6: 1240 lba = ISCSI_NTOHL(*((uint32_t *)(void *)cdb)) & 0x001fffff; 1241 if ((len = *cdbsize) == 0) { 1242 len = 256; 1243 } 1244 iscsi_trace(TRACE_SCSI_CMD, 1245 "READ_6(lba %u, len %u blocks)\n", lba, len); 1246 if (disk_read(sess, args, lba, len, lun) != 0) { 1247 iscsi_err(__FILE__, __LINE__, 1248 "disk_read() failed\n"); 1249 args->status = SCSI_CHECK_CONDITION; 1250 } 1251 args->input = 1; 1252 break; 1253 1254 case MODE_SENSE_6: 1255 mode_sense(6, cmd); 1256 break; 1257 1258 case WRITE_10: 1259 case WRITE_VERIFY: 1260 cdb2lba(&lba, &len, cdb); 1261 1262 iscsi_trace(TRACE_SCSI_CMD, 1263 "WRITE_10 | WRITE_VERIFY(lba %u, len %u blocks)\n", 1264 lba, len); 1265 if (disk_write(sess, args, lun, lba, (unsigned) len) != 0) { 1266 iscsi_err(__FILE__, __LINE__, 1267 "disk_write() failed\n"); 1268 args->status = SCSI_CHECK_CONDITION; 1269 } 1270 args->length = 0; 1271 break; 1272 1273 case READ_10: 1274 cdb2lba(&lba, &len, cdb); 1275 iscsi_trace(TRACE_SCSI_CMD, 1276 "READ_10(lba %u, len %u blocks)\n", lba, len); 1277 if (disk_read(sess, args, lba, len, lun) != 0) { 1278 iscsi_err(__FILE__, __LINE__, 1279 "disk_read() failed\n"); 1280 args->status = SCSI_CHECK_CONDITION; 1281 } 1282 args->input = 1; 1283 break; 1284 1285 case VERIFY: 1286 /* For now just set the status to success. */ 1287 args->status = SCSI_SUCCESS; 1288 break; 1289 1290 case SYNC_CACHE: 1291 cdb2lba(&lba, &len, cdb); 1292 iscsi_trace(TRACE_SCSI_CMD, 1293 "SYNC_CACHE (lba %u, len %u blocks)\n", lba, len); 1294 if (de_fsync_range(&disks.v[sess->d].lunv->v[lun].de, 1295 FDATASYNC, lba, 1296 (off_t)(len * disks.v[sess->d].blocklen)) < 0) { 1297 iscsi_err(__FILE__, __LINE__, 1298 "disk_read() failed\n"); 1299 args->status = SCSI_CHECK_CONDITION; 1300 } else { 1301 args->status = SCSI_SUCCESS; 1302 args->length = 0; 1303 } 1304 break; 1305 1306 case LOG_SENSE: 1307 iscsi_trace(TRACE_SCSI_CMD, "LOG_SENSE\n"); 1308 args->status = SCSI_SUCCESS; 1309 args->length = 0; 1310 break; 1311 1312 case MODE_SENSE_10: 1313 mode_sense(10, cmd); 1314 break; 1315 1316 case MODE_SELECT_10: 1317 /* XXX still to do */ 1318 iscsi_trace(TRACE_SCSI_CMD, "MODE_SELECT_10\n"); 1319 args->status = SCSI_SUCCESS; 1320 args->length = 0; 1321 break; 1322 1323 case PERSISTENT_RESERVE_IN: 1324 iscsi_trace(TRACE_SCSI_CMD, "PERSISTENT_RESERVE_IN\n"); 1325 args->length = persistent_reserve_in((cdb[1] & 1326 PERSISTENT_RESERVE_IN_SERVICE_ACTION_MASK), 1327 args->send_data); 1328 args->status = SCSI_SUCCESS; 1329 break; 1330 1331 case REPORT_LUNS: 1332 iscsi_trace(TRACE_SCSI_CMD, "REPORT LUNS\n"); 1333 args->length = report_luns(args->send_data, 1334 disks.v[sess->d].luns); 1335 args->input = 8; 1336 args->status = SCSI_SUCCESS; 1337 break; 1338 1339 case RESERVE_6: 1340 iscsi_trace(TRACE_SCSI_CMD, "RESERVE_6\n"); 1341 args->status = SCSI_SUCCESS; 1342 args->length = 0; 1343 break; 1344 1345 case RELEASE_6: 1346 iscsi_trace(TRACE_SCSI_CMD, "RELEASE_6\n"); 1347 args->status = SCSI_SUCCESS; 1348 args->length = 0; 1349 break; 1350 1351 case RESERVE_10: 1352 iscsi_trace(TRACE_SCSI_CMD, "RESERVE_10\n"); 1353 args->status = SCSI_SUCCESS; 1354 args->length = 0; 1355 break; 1356 1357 case RELEASE_10: 1358 iscsi_trace(TRACE_SCSI_CMD, "RELEASE_10\n"); 1359 args->status = SCSI_SUCCESS; 1360 args->length = 0; 1361 break; 1362 1363 default: 1364 iscsi_err(__FILE__, __LINE__, 1365 "UNKNOWN OPCODE %#x\n", cdb[0]); 1366 /* to not cause confusion with some initiators */ 1367 args->status = SCSI_CHECK_CONDITION; 1368 break; 1369 } 1370 iscsi_trace(TRACE_SCSI_DEBUG, 1371 "SCSI op %#x: done (status %#x)\n", cdb[0], args->status); 1372 return 0; 1373 } 1374 1375 int 1376 device_shutdown(target_session_t *sess) 1377 { 1378 USE_ARG(sess); 1379 return 1; 1380 } 1381 1382 /* 1383 * Private Interface 1384 */ 1385 1386 static int 1387 disk_write(target_session_t *sess, iscsi_scsi_cmd_args_t *args, uint8_t lun, 1388 uint32_t lba, uint32_t len) 1389 { 1390 struct iovec sg; 1391 uint64_t byte_offset; 1392 uint64_t bytec; 1393 uint8_t *ptr; 1394 int result; 1395 1396 byte_offset = lba * disks.v[sess->d].blocklen; 1397 bytec = len * disks.v[sess->d].blocklen; 1398 ptr = NULL; 1399 iscsi_trace(TRACE_SCSI_DATA, 1400 "writing %" PRIu64 1401 " bytes from socket into device at byte offset %" PRIu64 "\n", 1402 bytec, byte_offset); 1403 1404 if ((unsigned) bytec > MB(1)) { 1405 iscsi_err(__FILE__, __LINE__, "bytec > %" PRIu64 "m\n", bytec); 1406 NO_CLEANUP; 1407 return -1; 1408 } 1409 1410 /* Assign ptr for write data */ 1411 ptr = malloc(MB(1)); 1412 1413 /* Have target do data transfer */ 1414 sg.iov_base = ptr; 1415 sg.iov_len = (unsigned)bytec; 1416 if (target_transfer_data(sess, args, &sg, 1) != 0) { 1417 iscsi_err(__FILE__, __LINE__, 1418 "target_transfer_data() failed\n"); 1419 result = -1; 1420 goto out; 1421 } 1422 /* Finish up write */ 1423 if (de_lseek(&disks.v[sess->d].lunv->v[lun].de, (off_t)byte_offset, 1424 SEEK_SET) == -1) { 1425 iscsi_err(__FILE__, __LINE__, 1426 "lseek() to offset %" PRIu64 " failed\n", 1427 byte_offset); 1428 result = -1; 1429 goto out; 1430 } 1431 if (!target_writable(&disks.v[sess->d].lunv->v[lun])) { 1432 iscsi_err(__FILE__, __LINE__, 1433 "write() of %" PRIu64 " bytes failed at offset %" 1434 PRIu64 ", size %" PRIu64 "[READONLY TARGET]\n", 1435 bytec, byte_offset, 1436 de_getsize(&disks.v[sess->d].lunv->v[lun].de)); 1437 result = -1; 1438 goto out; 1439 } 1440 if ((uint64_t)de_write(&disks.v[sess->d].lunv->v[lun].de, ptr, 1441 (unsigned) bytec) != bytec) { 1442 iscsi_err(__FILE__, __LINE__, 1443 "write() of %" PRIu64 " bytes failed at offset %" 1444 PRIu64 ", size %" PRIu64 "\n", 1445 bytec, byte_offset, 1446 de_getsize(&disks.v[sess->d].lunv->v[lun].de)); 1447 result = -1; 1448 goto out; 1449 } 1450 iscsi_trace(TRACE_SCSI_DATA, 1451 "wrote %" PRIu64 " bytes to device OK\n", bytec); 1452 result = 0; 1453 out: 1454 free(ptr); 1455 return result; 1456 } 1457 1458 static int 1459 disk_read(target_session_t *sess, iscsi_scsi_cmd_args_t *args, uint32_t lba, 1460 uint16_t len, uint8_t lun) 1461 { 1462 uint64_t byte_offset; 1463 uint64_t bytec; 1464 uint64_t extra; 1465 uint8_t *ptr; 1466 uint32_t n; 1467 int rc; 1468 int result; 1469 1470 assert(args->send_buffer == NULL); 1471 byte_offset = lba * disks.v[sess->d].blocklen; 1472 bytec = len * disks.v[sess->d].blocklen; 1473 extra = 0; 1474 if (len == 0) { 1475 iscsi_err(__FILE__, __LINE__, "Zero \"len\"\n"); 1476 NO_CLEANUP; 1477 return -1; 1478 } 1479 if (lba > disks.v[sess->d].blockc - 1 || 1480 (lba + len) > disks.v[sess->d].blockc) { 1481 iscsi_err(__FILE__, __LINE__, 1482 "attempt to read beyond end of media\n" 1483 "max_lba = %" PRIu64 ", requested lba = %u, len = %u\n", 1484 disks.v[sess->d].blockc - 1, lba, len); 1485 return -1; 1486 } 1487 if ((unsigned) bytec > MB(1)) { 1488 iscsi_err(__FILE__, __LINE__, "bytec > %" PRIu64 "\n", bytec); 1489 NO_CLEANUP; 1490 return -1; 1491 } 1492 ptr = malloc(MB(1)); 1493 n = 0; 1494 do { 1495 if (de_lseek(&disks.v[sess->d].lunv->v[lun].de, 1496 (off_t)(n + byte_offset), SEEK_SET) == -1) { 1497 iscsi_err(__FILE__, __LINE__, "lseek failed\n"); 1498 result = -1; 1499 goto out; 1500 } 1501 rc = de_read(&disks.v[sess->d].lunv->v[lun].de, ptr + n, 1502 (size_t)(bytec - n)); 1503 if (rc <= 0) { 1504 iscsi_err(__FILE__, __LINE__, 1505 "read failed: rc %d errno %d\n", rc, errno); 1506 result = -1; 1507 goto out; 1508 } 1509 n += rc; 1510 if (n < bytec) { 1511 iscsi_err(__FILE__, __LINE__, 1512 "Got partial file read: %d bytes of %" PRIu64 1513 "\n", rc, bytec - n + rc); 1514 } 1515 } while (n < bytec); 1516 ((struct iovec *)(void *)args->send_data)[0].iov_base = 1517 ptr + (unsigned) extra; 1518 ((struct iovec *)(void *)args->send_data)[0].iov_len = 1519 (unsigned) bytec; 1520 args->length = (unsigned) bytec; 1521 args->send_sg_len = 1; 1522 args->status = SCSI_SUCCESS; 1523 args->send_buffer = ptr; 1524 return 0; 1525 out: 1526 free(ptr); 1527 return result; 1528 } 1529