1 /* $NetBSD: disk.c,v 1.6 2010/03/03 00:44:51 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 #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) 707 { 708 off_t size; 709 char block[DEFAULT_TARGET_BLOCK_LEN]; 710 711 size = de_getsize(de); 712 if (de_lseek(de, size - sizeof(block), SEEK_SET) == -1) { 713 iscsi_err(__FILE__, __LINE__, 714 "error seeking \"%s\"\n", filename); 715 return 0; 716 } 717 if (de_read(de, block, sizeof(block)) == -1) { 718 iscsi_err(__FILE__, __LINE__, 719 "error reading \"%s\"\n", filename); 720 return 0; 721 } 722 if (de_write(de, block, sizeof(block)) == -1) { 723 iscsi_err(__FILE__, __LINE__, 724 "error writing \"%s\"\n", filename); 725 return 0; 726 } 727 return 1; 728 } 729 730 /* allocate space as desired */ 731 static int 732 allocate_space(disc_target_t *tp) 733 { 734 uint32_t i; 735 736 /* Don't perform check for writability in the target here, as the 737 following write() in de_allocate is non-destructive */ 738 switch(tp->de.type) { 739 case DE_EXTENT: 740 return de_allocate(&tp->de, tp->target); 741 case DE_DEVICE: 742 for (i = 0 ; i < tp->de.u.dp->c ; i++) { 743 if (!de_allocate(&tp->de.u.dp->xv[i], tp->target)) { 744 return 0; 745 } 746 } 747 return 1; 748 default: 749 break; 750 } 751 return 0; 752 } 753 754 /* copy src to dst, of size `n' bytes, padding any extra with `pad' */ 755 static void 756 strpadcpy(uint8_t *dst, size_t dstlen, const char *src, const size_t srclen, 757 char pad) 758 { 759 if (srclen < dstlen) { 760 (void) memcpy(dst, src, srclen); 761 (void) memset(&dst[srclen], pad, dstlen - srclen); 762 } else { 763 (void) memcpy(dst, src, dstlen); 764 } 765 } 766 767 /* handle REPORT LUNs SCSI command */ 768 static int 769 report_luns(uint8_t *data, uint64_t luns) 770 { 771 uint64_t i; 772 uint32_t len; 773 774 len = 8; 775 for (i = 0; i < luns; i++) { 776 uint8_t *p = &data[len]; 777 778 if (i < 256) { 779 memset(p, 0, 8); 780 p[1] = (uint8_t)(i & 0xff); 781 len += 8; 782 } else if (i < 16384) { 783 memset(p, 0, 8); 784 p[0] = (uint8_t)(0x40 | ((i >> 8) & 0x3f)); 785 p[1] = (uint8_t)(i & 0xff); 786 len += 8; 787 } else { 788 /* XXX */ 789 } 790 } 791 *((uint32_t *)(void *)data) = ISCSI_HTONL(len - 8); 792 memset(&data[4], 0, 4); 793 return len; 794 } 795 796 /* handle persistent reserve in command */ 797 static int 798 persistent_reserve_in(uint8_t action, uint8_t *data) 799 { 800 uint64_t key; 801 802 switch(action) { 803 case PERSISTENT_RESERVE_IN_READ_KEYS: 804 key = 0; /* simulate "just powered on" */ 805 *((uint32_t *)(void *)data) = 806 (uint32_t)ISCSI_HTONL((uint32_t) 0); 807 *((uint32_t *) (void *)data + 4) = 808 (uint32_t) ISCSI_HTONL((uint32_t) sizeof(key)); 809 /* length in bytes of list of keys */ 810 *((uint64_t *) (void *)data + 8) = (uint64_t) ISCSI_HTONLL(key); 811 return 8 + sizeof(key); 812 case PERSISTENT_RESERVE_IN_REPORT_CAPABILITIES: 813 (void) memset(data, 0x0, 8); 814 /* length is fixed at 8 bytes */ 815 *((uint16_t *)(void *)data) = 816 (uint16_t)ISCSI_HTONS((uint16_t)8); 817 data[2] = PERSISTENT_RESERVE_IN_CRH; 818 /* also SIP_C, ATP_C and PTPL_C here */ 819 data[3] = 0; /* also TMV and PTPL_A here */ 820 data[4] = 0; 821 /* also WR_EX_AR, EX_AC_RD, WR_EX_RD, EX_AC, WR_EX */ 822 data[5] = 0; /* also EX_AC_AR here */ 823 return 8; 824 default: 825 iscsi_err(__FILE__, __LINE__, 826 "persistent_reserve_in: action %x unrecognised\n", 827 action); 828 return 0; 829 } 830 } 831 832 /* initialise the device */ 833 int 834 device_init(iscsi_target_t *tgt, targv_t *tvp, disc_target_t *tp) 835 { 836 iscsi_disk_t *idisk; 837 int mode; 838 839 ALLOC(iscsi_disk_t, disks.v, disks.size, disks.c, 10, 10, 840 "device_init", ;); 841 idisk = &disks.v[disks.c]; 842 idisk->lunv = tvp; 843 if ((idisk->luns = defaults.luns) == 0) { 844 idisk->luns = iSCSI_DEFAULT_LUNS; 845 } 846 idisk->blocklen = atoi(iscsi_target_getvar(tgt, "blocklen")); 847 switch(idisk->blocklen) { 848 case 512: 849 case 1024: 850 case 2048: 851 case 4096: 852 case 8192: 853 break; 854 default: 855 iscsi_err(__FILE__, __LINE__, 856 "Invalid block len %" PRIu64 857 ". Choose one of 512, 1024, 2048, 4096, or 8192.\n", 858 idisk->blocklen); 859 return -1; 860 } 861 idisk->size = de_getsize(&tp->de); 862 idisk->blockc = idisk->size / idisk->blocklen; 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 int result; 1390 1391 byte_offset = lba * disks.v[sess->d].blocklen; 1392 bytec = len * disks.v[sess->d].blocklen; 1393 ptr = NULL; 1394 iscsi_trace(TRACE_SCSI_DATA, 1395 "writing %" PRIu64 1396 " bytes from socket into device at byte offset %" PRIu64 "\n", 1397 bytec, byte_offset); 1398 1399 if ((unsigned) bytec > MB(1)) { 1400 iscsi_err(__FILE__, __LINE__, "bytec > %u\n", bytec); 1401 NO_CLEANUP; 1402 return -1; 1403 } 1404 1405 /* Assign ptr for write data */ 1406 ptr = malloc(MB(1)); 1407 1408 /* Have target do data transfer */ 1409 sg.iov_base = ptr; 1410 sg.iov_len = (unsigned)bytec; 1411 if (target_transfer_data(sess, args, &sg, 1) != 0) { 1412 iscsi_err(__FILE__, __LINE__, 1413 "target_transfer_data() failed\n"); 1414 result = -1; 1415 goto out; 1416 } 1417 /* Finish up write */ 1418 if (de_lseek(&disks.v[sess->d].lunv->v[lun].de, (off_t)byte_offset, 1419 SEEK_SET) == -1) { 1420 iscsi_err(__FILE__, __LINE__, 1421 "lseek() to offset %" PRIu64 " failed\n", 1422 byte_offset); 1423 result = -1; 1424 goto out; 1425 } 1426 if (!target_writable(&disks.v[sess->d].lunv->v[lun])) { 1427 iscsi_err(__FILE__, __LINE__, 1428 "write() of %" PRIu64 " bytes failed at offset %" 1429 PRIu64 ", size %" PRIu64 "[READONLY TARGET]\n", 1430 bytec, byte_offset, 1431 de_getsize(&disks.v[sess->d].lunv->v[lun].de)); 1432 result = -1; 1433 goto out; 1434 } 1435 if ((uint64_t)de_write(&disks.v[sess->d].lunv->v[lun].de, ptr, 1436 (unsigned) bytec) != bytec) { 1437 iscsi_err(__FILE__, __LINE__, 1438 "write() of %" PRIu64 " bytes failed at offset %" 1439 PRIu64 ", size %" PRIu64 "\n", 1440 bytec, byte_offset, 1441 de_getsize(&disks.v[sess->d].lunv->v[lun].de)); 1442 result = -1; 1443 goto out; 1444 } 1445 iscsi_trace(TRACE_SCSI_DATA, 1446 "wrote %" PRIu64 " bytes to device OK\n", bytec); 1447 result = 0; 1448 out: 1449 free(ptr); 1450 return result; 1451 } 1452 1453 static int 1454 disk_read(target_session_t *sess, iscsi_scsi_cmd_args_t *args, uint32_t lba, 1455 uint16_t len, uint8_t lun) 1456 { 1457 uint64_t byte_offset; 1458 uint64_t bytec; 1459 uint64_t extra; 1460 uint8_t *ptr; 1461 uint32_t n; 1462 int rc; 1463 int result; 1464 1465 assert(args->send_buffer == NULL); 1466 byte_offset = lba * disks.v[sess->d].blocklen; 1467 bytec = len * disks.v[sess->d].blocklen; 1468 extra = 0; 1469 if (len == 0) { 1470 iscsi_err(__FILE__, __LINE__, "Zero \"len\"\n"); 1471 NO_CLEANUP; 1472 return -1; 1473 } 1474 if (lba > disks.v[sess->d].blockc - 1 || 1475 (lba + len) > disks.v[sess->d].blockc) { 1476 iscsi_err(__FILE__, __LINE__, 1477 "attempt to read beyond end of media\n" 1478 "max_lba = %" PRIu64 ", requested lba = %u, len = %u\n", 1479 disks.v[sess->d].blockc - 1, lba, len); 1480 return -1; 1481 } 1482 if ((unsigned) bytec > MB(1)) { 1483 iscsi_err(__FILE__, __LINE__, "bytec > %u\n", bytec); 1484 NO_CLEANUP; 1485 return -1; 1486 } 1487 ptr = malloc(MB(1)); 1488 n = 0; 1489 do { 1490 if (de_lseek(&disks.v[sess->d].lunv->v[lun].de, 1491 (off_t)(n + byte_offset), SEEK_SET) == -1) { 1492 iscsi_err(__FILE__, __LINE__, "lseek failed\n"); 1493 result = -1; 1494 goto out; 1495 } 1496 rc = de_read(&disks.v[sess->d].lunv->v[lun].de, ptr + n, 1497 (size_t)(bytec - n)); 1498 if (rc <= 0) { 1499 iscsi_err(__FILE__, __LINE__, 1500 "read failed: rc %d errno %d\n", rc, errno); 1501 result = -1; 1502 goto out; 1503 } 1504 n += rc; 1505 if (n < bytec) { 1506 iscsi_err(__FILE__, __LINE__, 1507 "Got partial file read: %d bytes of %" PRIu64 1508 "\n", rc, bytec - n + rc); 1509 } 1510 } while (n < bytec); 1511 ((struct iovec *)(void *)args->send_data)[0].iov_base = 1512 ptr + (unsigned) extra; 1513 ((struct iovec *)(void *)args->send_data)[0].iov_len = 1514 (unsigned) bytec; 1515 args->length = (unsigned) bytec; 1516 args->send_sg_len = 1; 1517 args->status = 0; 1518 args->send_buffer = ptr; 1519 return 0; 1520 out: 1521 free(ptr); 1522 return result; 1523 } 1524