Exemple #1
0
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);
    }
}
Exemple #2
0
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);
}
Exemple #3
0
/* 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;
}
Exemple #4
0
/* 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;
}
Exemple #5
0
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));
}
Exemple #6
0
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(&paramp, 0, sizeof(paramp));
    memcpy(&paramp.key, &param[0], 8);
    memcpy(&paramp.sa_key, &param[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(&param[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, &param[i + 8], 8);
                j += offsetof(struct transportid, n_port_name[8]);
                i += 24;
                break;
            case 5:
            case 0x45:
                /* iSCSI transport.  */
                len = lduw_be_p(&param[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(&param[i + 4], 0, len) == NULL) {
                    goto illegal_req;
                }
                memcpy(id->iscsi_name, &param[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, &param[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;
        }
    }