static int coroutine_fn raw_co_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors) { return bdrv_co_discard(bs->file->bs, sector_num, nb_sectors); }
static void nbd_trip(void *opaque) { NBDClient *client = opaque; NBDRequest *req = nbd_request_get(client); NBDExport *exp = client->exp; struct nbd_request request; struct nbd_reply reply; ssize_t ret; TRACE("Reading request."); 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; } if ((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; } switch (request.type & NBD_CMD_MASK_COMMAND) { case NBD_CMD_READ: TRACE("Request type is READ"); if (request.type & NBD_CMD_FLAG_FUA) { ret = bdrv_co_flush(exp->bs); if (ret < 0) { LOG("flush failed"); reply.error = -ret; goto error_reply; } } ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, req->data, request.len / 512); 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 = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512, req->data, request.len / 512); if (ret < 0) { LOG("writing to file failed"); reply.error = -ret; goto error_reply; } if (request.type & NBD_CMD_FLAG_FUA) { ret = bdrv_co_flush(exp->bs); 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 = bdrv_co_flush(exp->bs); 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 = bdrv_co_discard(exp->bs, (request.from + exp->dev_offset) / 512, request.len / 512); 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); nbd_client_close(client); }