static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; r->req.aiocb = NULL; if (ret || r->req.io_canceled) { scsi_command_complete(r, ret); return; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete(r, 0); } else { /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); scsi_req_data(&r->req, len); scsi_req_unref(&r->req); } }
static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; assert(r->req.aiocb != NULL); r->req.aiocb = NULL; if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); return; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete_noio(r, 0); return; } /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); /* Patch MODE SENSE device specific parameters if the BDS is opened * readonly. */ if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) && blk_is_read_only(s->conf.blk) && (r->req.cmd.buf[0] == MODE_SENSE || r->req.cmd.buf[0] == MODE_SENSE_10) && (r->req.cmd.buf[1] & 0x8) == 0) { if (r->req.cmd.buf[0] == MODE_SENSE) { r->buf[2] |= 0x80; } else { r->buf[3] |= 0x80; } } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); }
/* warning: addr must be aligned */ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, hwaddr addr, MemTxAttrs attrs, MemTxResult *result, enum device_endian endian) { uint8_t *ptr; uint64_t val; MemoryRegion *mr; hwaddr l = 4; hwaddr addr1; MemTxResult r; bool release_lock = false; RCU_READ_LOCK(); mr = TRANSLATE(addr, &addr1, &l, false); if (l < 4 || !IS_DIRECT(mr, false)) { release_lock |= prepare_mmio_access(mr); /* I/O case */ r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs); #if defined(TARGET_WORDS_BIGENDIAN) if (endian == DEVICE_LITTLE_ENDIAN) { val = bswap32(val); } #else if (endian == DEVICE_BIG_ENDIAN) { val = bswap32(val); } #endif } else { /* RAM case */ ptr = MAP_RAM(mr, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = ldl_le_p(ptr); break; case DEVICE_BIG_ENDIAN: val = ldl_be_p(ptr); break; default: val = ldl_p(ptr); break; } r = MEMTX_OK; } if (result) { *result = r; } if (release_lock) { qemu_mutex_unlock_iothread(); } RCU_READ_UNLOCK(); return val; }
/* nbd_receive_reply * Returns 1 on success * 0 on eof, when no data was read (errp is not set) * negative errno on failure (errp is set) */ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp) { uint8_t buf[NBD_REPLY_SIZE]; uint32_t magic; int ret; ret = nbd_read_eof(ioc, buf, sizeof(buf), errp); if (ret <= 0) { return ret; } /* Reply [ 0 .. 3] magic (NBD_REPLY_MAGIC) [ 4 .. 7] error (0 == no error) [ 7 .. 15] handle */ magic = ldl_be_p(buf); reply->error = ldl_be_p(buf + 4); reply->handle = ldq_be_p(buf + 8); reply->error = nbd_errno_to_system_errno(reply->error); if (reply->error == ESHUTDOWN) { /* This works even on mingw which lacks a native ESHUTDOWN */ error_setg(errp, "server shutting down"); return -EINVAL; } trace_nbd_receive_reply(magic, reply->error, reply->handle); if (magic != NBD_REPLY_MAGIC) { error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic); return -EINVAL; } return 1; }
static void scsi_read_complete(void * opaque, int ret) { SCSIGenericReq *r = (SCSIGenericReq *)opaque; SCSIDevice *s = r->req.dev; int len; assert(r->req.aiocb != NULL); r->req.aiocb = NULL; aio_context_acquire(blk_get_aio_context(s->conf.blk)); if (ret || r->req.io_canceled) { scsi_command_complete_noio(r, ret); goto done; } len = r->io_header.dxfer_len - r->io_header.resid; DPRINTF("Data ready tag=0x%x len=%d\n", r->req.tag, len); r->len = -1; if (len == 0) { scsi_command_complete_noio(r, 0); goto done; } /* Snoop READ CAPACITY output to set the blocksize. */ if (r->req.cmd.buf[0] == READ_CAPACITY_10 && (ldl_be_p(&r->buf[0]) != 0xffffffffU || s->max_lba == 0)) { s->blocksize = ldl_be_p(&r->buf[4]); s->max_lba = ldl_be_p(&r->buf[0]) & 0xffffffffULL; } else if (r->req.cmd.buf[0] == SERVICE_ACTION_IN_16 && (r->req.cmd.buf[1] & 31) == SAI_READ_CAPACITY_16) { s->blocksize = ldl_be_p(&r->buf[8]); s->max_lba = ldq_be_p(&r->buf[0]); } blk_set_guest_block_size(s->conf.blk, s->blocksize); /* Patch MODE SENSE device specific parameters if the BDS is opened * readonly. */ if ((s->type == TYPE_DISK || s->type == TYPE_TAPE) && blk_is_read_only(s->conf.blk) && (r->req.cmd.buf[0] == MODE_SENSE || r->req.cmd.buf[0] == MODE_SENSE_10) && (r->req.cmd.buf[1] & 0x8) == 0) { if (r->req.cmd.buf[0] == MODE_SENSE) { r->buf[2] |= 0x80; } else { r->buf[3] |= 0x80; } } if (s->type == TYPE_DISK && r->req.cmd.buf[0] == INQUIRY && r->req.cmd.buf[2] == 0xb0) { uint32_t max_transfer = blk_get_max_transfer(s->conf.blk) / s->blocksize; assert(max_transfer); stl_be_p(&r->buf[8], max_transfer); /* Also take care of the opt xfer len. */ stl_be_p(&r->buf[12], MIN_NON_ZERO(max_transfer, ldl_be_p(&r->buf[12]))); } scsi_req_data(&r->req, len); scsi_req_unref(&r->req); done: aio_context_release(blk_get_aio_context(s->conf.blk)); }
static int multipath_pr_out(int fd, const uint8_t *cdb, uint8_t *sense, const uint8_t *param, int sz) { int rq_servact = cdb[1]; int rq_scope = cdb[2] >> 4; int rq_type = cdb[2] & 0xf; struct prout_param_descriptor paramp; char transportids[PR_HELPER_DATA_SIZE]; int r; if (sz < PR_OUT_FIXED_PARAM_SIZE) { /* Illegal request, Parameter list length error. This isn't fatal; * we have read the data, send an error without closing the socket. */ scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM_LEN)); return CHECK_CONDITION; } switch (rq_servact) { case MPATH_PROUT_REG_SA: case MPATH_PROUT_RES_SA: case MPATH_PROUT_REL_SA: case MPATH_PROUT_CLEAR_SA: case MPATH_PROUT_PREE_SA: case MPATH_PROUT_PREE_AB_SA: case MPATH_PROUT_REG_IGN_SA: break; case MPATH_PROUT_REG_MOV_SA: /* Not supported by struct prout_param_descriptor. */ default: /* Cannot parse any other input. */ scsi_build_sense(sense, SENSE_CODE(INVALID_FIELD)); return CHECK_CONDITION; } /* Convert input data, especially transport IDs, to the structs * used by libmpathpersist (which, of course, will immediately * do the opposite). */ memset(¶mp, 0, sizeof(paramp)); memcpy(¶mp.key, ¶m[0], 8); memcpy(¶mp.sa_key, ¶m[8], 8); paramp.sa_flags = param[20]; if (sz > PR_OUT_FIXED_PARAM_SIZE) { size_t transportid_len; int i, j; if (sz < PR_OUT_FIXED_PARAM_SIZE + 4) { scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM_LEN)); return CHECK_CONDITION; } transportid_len = ldl_be_p(¶m[24]) + PR_OUT_FIXED_PARAM_SIZE + 4; if (transportid_len > sz) { scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM)); return CHECK_CONDITION; } for (i = PR_OUT_FIXED_PARAM_SIZE + 4, j = 0; i < transportid_len; ) { struct transportid *id = (struct transportid *) &transportids[j]; int len; id->format_code = param[i] & 0xc0; id->protocol_id = param[i] & 0x0f; switch (param[i] & 0xcf) { case 0: /* FC transport. */ if (i + 24 > transportid_len) { goto illegal_req; } memcpy(id->n_port_name, ¶m[i + 8], 8); j += offsetof(struct transportid, n_port_name[8]); i += 24; break; case 5: case 0x45: /* iSCSI transport. */ len = lduw_be_p(¶m[i + 2]); if (len > 252 || (len & 3) || i + len + 4 > transportid_len) { /* For format code 00, the standard says the maximum is 223 * plus the NUL terminator. For format code 01 there is no * maximum length, but libmpathpersist ignores the first * byte of id->iscsi_name so our maximum is 252. */ goto illegal_req; } if (memchr(¶m[i + 4], 0, len) == NULL) { goto illegal_req; } memcpy(id->iscsi_name, ¶m[i + 2], len + 2); j += offsetof(struct transportid, iscsi_name[len + 2]); i += len + 4; break; case 6: /* SAS transport. */ if (i + 24 > transportid_len) { goto illegal_req; } memcpy(id->sas_address, ¶m[i + 4], 8); j += offsetof(struct transportid, sas_address[8]); i += 24; break; default: illegal_req: scsi_build_sense(sense, SENSE_CODE(INVALID_PARAM)); return CHECK_CONDITION; } paramp.trnptid_list[paramp.num_transportid++] = id; } }