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