static void nbd_trip(void *opaque)

{

    NBDClient *client = opaque;

    NBDExport *exp = client->exp;

    NBDRequest *req;

    struct nbd_request request;

    struct nbd_reply reply;

    ssize_t ret;

    uint32_t command;



    TRACE("Reading request.");

    if (client->closing) {

        return;

    }



    req = nbd_request_get(client);

    ret = nbd_co_receive_request(req, &request);

    if (ret == -EAGAIN) {

        goto done;

    }

    if (ret == -EIO) {

        goto out;

    }



    reply.handle = request.handle;

    reply.error = 0;



    if (ret < 0) {

        reply.error = -ret;

        goto error_reply;

    }

    command = request.type & NBD_CMD_MASK_COMMAND;

    if (command != NBD_CMD_DISC && (request.from + request.len) > exp->size) {

            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64

            ", Offset: %" PRIu64 "\n",

                    request.from, request.len,

                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);

        LOG("requested operation past EOF--bad client?");

        goto invalid_request;

    }



    if (client->closing) {

        /*

         * The client may be closed when we are blocked in

         * nbd_co_receive_request()

         */

        goto done;

    }



    switch (command) {

    case NBD_CMD_READ:

        TRACE("Request type is READ");



        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }



        ret = blk_pread(exp->blk, request.from + exp->dev_offset,

                        req->data, request.len);

        if (ret < 0) {

            LOG("reading from file failed");

            reply.error = -ret;

            goto error_reply;

        }



        TRACE("Read %u byte(s)", request.len);

        if (nbd_co_send_reply(req, &reply, request.len) < 0)

            goto out;

        break;

    case NBD_CMD_WRITE:

        TRACE("Request type is WRITE");



        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {

            TRACE("Server is read-only, return error");

            reply.error = EROFS;

            goto error_reply;

        }



        TRACE("Writing to device");



        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,

                         req->data, request.len, 0);

        if (ret < 0) {

            LOG("writing to file failed");

            reply.error = -ret;

            goto error_reply;

        }



        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }



        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_DISC:

        TRACE("Request type is DISCONNECT");

        errno = 0;

        goto out;

    case NBD_CMD_FLUSH:

        TRACE("Request type is FLUSH");



        ret = blk_co_flush(exp->blk);

        if (ret < 0) {

            LOG("flush failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_TRIM:

        TRACE("Request type is TRIM");

        ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset)

                                       / BDRV_SECTOR_SIZE,

                             request.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("discard failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    default:

        LOG("invalid request type (%u) received", request.type);

    invalid_request:

        reply.error = EINVAL;

    error_reply:

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    }



    TRACE("Request/Reply complete");



done:

    nbd_request_put(req);

    return;



out:

    nbd_request_put(req);

    client_close(client);

}

static void nbd_trip(void *opaque)

{

    NBDClient *client = opaque;

    NBDExport *exp = client->exp;

    NBDRequest *req;

    struct nbd_request request;

    struct nbd_reply reply;

    ssize_t ret;

    uint32_t command;



    TRACE("Reading request.");

    if (client->closing) {

        return;

    }



    req = nbd_request_get(client);

    ret = nbd_co_receive_request(req, &request);

    if (ret == -EAGAIN) {

        goto done;

    }

    if (ret == -EIO) {

        goto out;

    }



    reply.handle = request.handle;

    reply.error = 0;



    if (ret < 0) {

        reply.error = -ret;

        goto error_reply;

    }

    command = request.type & NBD_CMD_MASK_COMMAND;

    if (command != NBD_CMD_DISC && (request.from + request.len) > exp->size) {

            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64

            ", Offset: %" PRIu64 "\n",

                    request.from, request.len,

                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);

        LOG("requested operation past EOF--bad client?");

        goto invalid_request;

    }



    if (client->closing) {

        







        goto done;

    }



    switch (command) {

    case NBD_CMD_READ:

        TRACE("Request type is READ");



        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }



        ret = blk_pread(exp->blk, request.from + exp->dev_offset,

                        req->data, request.len);

        if (ret < 0) {

            LOG("reading from file failed");

            reply.error = -ret;

            goto error_reply;

        }



        TRACE("Read %u byte(s)", request.len);

        if (nbd_co_send_reply(req, &reply, request.len) < 0)

            goto out;

        break;

    case NBD_CMD_WRITE:

        TRACE("Request type is WRITE");



        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {

            TRACE("Server is read-only, return error");

            reply.error = EROFS;

            goto error_reply;

        }



        TRACE("Writing to device");



        ret = blk_pwrite(exp->blk, request.from + exp->dev_offset,

                         req->data, request.len, 0);

        if (ret < 0) {

            LOG("writing to file failed");

            reply.error = -ret;

            goto error_reply;

        }



        if (request.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                reply.error = -ret;

                goto error_reply;

            }

        }



        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_DISC:

        TRACE("Request type is DISCONNECT");

        errno = 0;

        goto out;

    case NBD_CMD_FLUSH:

        TRACE("Request type is FLUSH");



        ret = blk_co_flush(exp->blk);

        if (ret < 0) {

            LOG("flush failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_TRIM:

        TRACE("Request type is TRIM");

        ret = blk_co_discard(exp->blk, (request.from + exp->dev_offset)

                                       / BDRV_SECTOR_SIZE,

                             request.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("discard failed");

            reply.error = -ret;

        }

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    default:

        LOG("invalid request type (%u) received", request.type);

    invalid_request:

        reply.error = EINVAL;

    error_reply:

        if (nbd_co_send_reply(req, &reply, 0) < 0) {

            goto out;

        }

        break;

    }



    TRACE("Request/Reply complete");



done:

    nbd_request_put(req);

    return;



out:

    nbd_request_put(req);

    client_close(client);

}

static void FUNC_0(void *VAR_0)

{

    NBDClient *client = VAR_0;

    NBDExport *exp = client->exp;

    NBDRequest *req;

    struct nbd_request VAR_1;

    struct nbd_reply VAR_2;

    ssize_t ret;

    uint32_t command;



    TRACE("Reading VAR_1.");

    if (client->closing) {

        return;

    }



    req = nbd_request_get(client);

    ret = nbd_co_receive_request(req, &VAR_1);

    if (ret == -EAGAIN) {

        goto done;

    }

    if (ret == -EIO) {

        goto out;

    }



    VAR_2.handle = VAR_1.handle;

    VAR_2.error = 0;



    if (ret < 0) {

        VAR_2.error = -ret;

        goto error_reply;

    }

    command = VAR_1.type & NBD_CMD_MASK_COMMAND;

    if (command != NBD_CMD_DISC && (VAR_1.from + VAR_1.len) > exp->size) {

            LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64

            ", Offset: %" PRIu64 "\n",

                    VAR_1.from, VAR_1.len,

                    (uint64_t)exp->size, (uint64_t)exp->dev_offset);

        LOG("requested operation past EOF--bad client?");

        goto invalid_request;

    }



    if (client->closing) {

        







        goto done;

    }



    switch (command) {

    case NBD_CMD_READ:

        TRACE("Request type is READ");



        if (VAR_1.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                VAR_2.error = -ret;

                goto error_reply;

            }

        }



        ret = blk_pread(exp->blk, VAR_1.from + exp->dev_offset,

                        req->data, VAR_1.len);

        if (ret < 0) {

            LOG("reading from file failed");

            VAR_2.error = -ret;

            goto error_reply;

        }



        TRACE("Read %u byte(s)", VAR_1.len);

        if (nbd_co_send_reply(req, &VAR_2, VAR_1.len) < 0)

            goto out;

        break;

    case NBD_CMD_WRITE:

        TRACE("Request type is WRITE");



        if (exp->nbdflags & NBD_FLAG_READ_ONLY) {

            TRACE("Server is read-only, return error");

            VAR_2.error = EROFS;

            goto error_reply;

        }



        TRACE("Writing to device");



        ret = blk_pwrite(exp->blk, VAR_1.from + exp->dev_offset,

                         req->data, VAR_1.len, 0);

        if (ret < 0) {

            LOG("writing to file failed");

            VAR_2.error = -ret;

            goto error_reply;

        }



        if (VAR_1.type & NBD_CMD_FLAG_FUA) {

            ret = blk_co_flush(exp->blk);

            if (ret < 0) {

                LOG("flush failed");

                VAR_2.error = -ret;

                goto error_reply;

            }

        }



        if (nbd_co_send_reply(req, &VAR_2, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_DISC:

        TRACE("Request type is DISCONNECT");

        errno = 0;

        goto out;

    case NBD_CMD_FLUSH:

        TRACE("Request type is FLUSH");



        ret = blk_co_flush(exp->blk);

        if (ret < 0) {

            LOG("flush failed");

            VAR_2.error = -ret;

        }

        if (nbd_co_send_reply(req, &VAR_2, 0) < 0) {

            goto out;

        }

        break;

    case NBD_CMD_TRIM:

        TRACE("Request type is TRIM");

        ret = blk_co_discard(exp->blk, (VAR_1.from + exp->dev_offset)

                                       / BDRV_SECTOR_SIZE,

                             VAR_1.len / BDRV_SECTOR_SIZE);

        if (ret < 0) {

            LOG("discard failed");

            VAR_2.error = -ret;

        }

        if (nbd_co_send_reply(req, &VAR_2, 0) < 0) {

            goto out;

        }

        break;

    default:

        LOG("invalid VAR_1 type (%u) received", VAR_1.type);

    invalid_request:

        VAR_2.error = EINVAL;

    error_reply:

        if (nbd_co_send_reply(req, &VAR_2, 0) < 0) {

            goto out;

        }

        break;

    }



    TRACE("Request/Reply complete");



done:

    nbd_request_put(req);

    return;



out:

    nbd_request_put(req);

    client_close(client);

}

static void FUNC_0(void *VAR_0)
{ NBDClient *client = VAR_0; NBDExport *exp = client->exp; NBDRequest *req; struct nbd_request VAR_1; struct nbd_reply VAR_2; ssize_t ret; uint32_t command; TRACE("Reading VAR_1."); if (client->closing) { return; } req = nbd_request_get(client); ret = nbd_co_receive_request(req, &VAR_1); if (ret == -EAGAIN) { goto done; } if (ret == -EIO) { goto out; } VAR_2.handle = VAR_1.handle; VAR_2.error = 0; if (ret < 0) { VAR_2.error = -ret; goto error_reply; } command = VAR_1.type & NBD_CMD_MASK_COMMAND; if (command != NBD_CMD_DISC && (VAR_1.from + VAR_1.len) > exp->size) { LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64
", Offset: %" PRIu64 "\n",
VAR_1.from, VAR_1.len,
(uint64_t)exp->size, (uint64_t)exp->dev_offset); LOG("requested operation past EOF--bad client?"); goto invalid_request; } if (client->closing) { goto done; } switch (command) { case NBD_CMD_READ:
TRACE("Request type is READ"); if (VAR_1.type & NBD_CMD_FLAG_FUA) { ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); VAR_2.error = -ret; goto error_reply; } } ret = blk_pread(exp->blk, VAR_1.from + exp->dev_offset,
req->data, VAR_1.len); if (ret < 0) { LOG("reading from file failed"); VAR_2.error = -ret; goto error_reply; } TRACE("Read %u byte(s)", VAR_1.len); if (nbd_co_send_reply(req, &VAR_2, VAR_1.len) < 0)
goto out; break; case NBD_CMD_WRITE:
TRACE("Request type is WRITE"); if (exp->nbdflags & NBD_FLAG_READ_ONLY) { TRACE("Server is read-only, return error"); VAR_2.error = EROFS; goto error_reply; } TRACE("Writing to device"); ret = blk_pwrite(exp->blk, VAR_1.from + exp->dev_offset,
req->data, VAR_1.len, 0); if (ret < 0) { LOG("writing to file failed"); VAR_2.error = -ret; goto error_reply; } if (VAR_1.type & NBD_CMD_FLAG_FUA) { ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); VAR_2.error = -ret; goto error_reply; } } if (nbd_co_send_reply(req, &VAR_2, 0) < 0) { goto out; } break; case NBD_CMD_DISC:
TRACE("Request type is DISCONNECT"); errno = 0; goto out; case NBD_CMD_FLUSH:
TRACE("Request type is FLUSH"); ret = blk_co_flush(exp->blk); if (ret < 0) { LOG("flush failed"); VAR_2.error = -ret; } if (nbd_co_send_reply(req, &VAR_2, 0) < 0) { goto out; } break; case NBD_CMD_TRIM:
TRACE("Request type is TRIM"); ret = blk_co_discard(exp->blk, (VAR_1.from + exp->dev_offset)
/ BDRV_SECTOR_SIZE,
VAR_1.len / BDRV_SECTOR_SIZE); if (ret < 0) { LOG("discard failed"); VAR_2.error = -ret; } if (nbd_co_send_reply(req, &VAR_2, 0) < 0) { goto out; } break; default:
LOG("invalid VAR_1 type (%u) received", VAR_1.type); invalid_request:
VAR_2.error = EINVAL; error_reply:
if (nbd_co_send_reply(req, &VAR_2, 0) < 0) { goto out; } break; } TRACE("Request/Reply complete"); done:
nbd_request_put(req); return; out:
nbd_request_put(req); client_close(client); }