123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /*
- * Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
- *
- * Network Block Device Common Code
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
- #include "qemu/osdep.h"
- #include "trace.h"
- #include "nbd-internal.h"
- /* Discard length bytes from channel. Return -errno on failure and 0 on
- * success */
- int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
- {
- ssize_t ret = 0;
- char small[1024];
- char *buffer;
- buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
- while (size > 0) {
- ssize_t count = MIN(65536, size);
- ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp);
- if (ret < 0) {
- goto cleanup;
- }
- size -= count;
- }
- cleanup:
- if (buffer != small) {
- g_free(buffer);
- }
- return ret;
- }
- void nbd_tls_handshake(QIOTask *task,
- void *opaque)
- {
- struct NBDTLSHandshakeData *data = opaque;
- qio_task_propagate_error(task, &data->error);
- data->complete = true;
- g_main_loop_quit(data->loop);
- }
- const char *nbd_opt_lookup(uint32_t opt)
- {
- switch (opt) {
- case NBD_OPT_EXPORT_NAME:
- return "export name";
- case NBD_OPT_ABORT:
- return "abort";
- case NBD_OPT_LIST:
- return "list";
- case NBD_OPT_STARTTLS:
- return "starttls";
- case NBD_OPT_INFO:
- return "info";
- case NBD_OPT_GO:
- return "go";
- case NBD_OPT_STRUCTURED_REPLY:
- return "structured reply";
- case NBD_OPT_LIST_META_CONTEXT:
- return "list meta context";
- case NBD_OPT_SET_META_CONTEXT:
- return "set meta context";
- default:
- return "<unknown>";
- }
- }
- const char *nbd_rep_lookup(uint32_t rep)
- {
- switch (rep) {
- case NBD_REP_ACK:
- return "ack";
- case NBD_REP_SERVER:
- return "server";
- case NBD_REP_INFO:
- return "info";
- case NBD_REP_META_CONTEXT:
- return "meta context";
- case NBD_REP_ERR_UNSUP:
- return "unsupported";
- case NBD_REP_ERR_POLICY:
- return "denied by policy";
- case NBD_REP_ERR_INVALID:
- return "invalid";
- case NBD_REP_ERR_PLATFORM:
- return "platform lacks support";
- case NBD_REP_ERR_TLS_REQD:
- return "TLS required";
- case NBD_REP_ERR_UNKNOWN:
- return "export unknown";
- case NBD_REP_ERR_SHUTDOWN:
- return "server shutting down";
- case NBD_REP_ERR_BLOCK_SIZE_REQD:
- return "block size required";
- default:
- return "<unknown>";
- }
- }
- const char *nbd_info_lookup(uint16_t info)
- {
- switch (info) {
- case NBD_INFO_EXPORT:
- return "export";
- case NBD_INFO_NAME:
- return "name";
- case NBD_INFO_DESCRIPTION:
- return "description";
- case NBD_INFO_BLOCK_SIZE:
- return "block size";
- default:
- return "<unknown>";
- }
- }
- const char *nbd_cmd_lookup(uint16_t cmd)
- {
- switch (cmd) {
- case NBD_CMD_READ:
- return "read";
- case NBD_CMD_WRITE:
- return "write";
- case NBD_CMD_DISC:
- return "disconnect";
- case NBD_CMD_FLUSH:
- return "flush";
- case NBD_CMD_TRIM:
- return "trim";
- case NBD_CMD_CACHE:
- return "cache";
- case NBD_CMD_WRITE_ZEROES:
- return "write zeroes";
- case NBD_CMD_BLOCK_STATUS:
- return "block status";
- default:
- return "<unknown>";
- }
- }
- const char *nbd_reply_type_lookup(uint16_t type)
- {
- switch (type) {
- case NBD_REPLY_TYPE_NONE:
- return "none";
- case NBD_REPLY_TYPE_OFFSET_DATA:
- return "data";
- case NBD_REPLY_TYPE_OFFSET_HOLE:
- return "hole";
- case NBD_REPLY_TYPE_BLOCK_STATUS:
- return "block status";
- case NBD_REPLY_TYPE_ERROR:
- return "generic error";
- case NBD_REPLY_TYPE_ERROR_OFFSET:
- return "error at offset";
- default:
- if (type & (1 << 15)) {
- return "<unknown error>";
- }
- return "<unknown>";
- }
- }
- const char *nbd_err_lookup(int err)
- {
- switch (err) {
- case NBD_SUCCESS:
- return "success";
- case NBD_EPERM:
- return "EPERM";
- case NBD_EIO:
- return "EIO";
- case NBD_ENOMEM:
- return "ENOMEM";
- case NBD_EINVAL:
- return "EINVAL";
- case NBD_ENOSPC:
- return "ENOSPC";
- case NBD_EOVERFLOW:
- return "EOVERFLOW";
- case NBD_ENOTSUP:
- return "ENOTSUP";
- case NBD_ESHUTDOWN:
- return "ESHUTDOWN";
- default:
- return "<unknown>";
- }
- }
- int nbd_errno_to_system_errno(int err)
- {
- int ret;
- switch (err) {
- case NBD_SUCCESS:
- ret = 0;
- break;
- case NBD_EPERM:
- ret = EPERM;
- break;
- case NBD_EIO:
- ret = EIO;
- break;
- case NBD_ENOMEM:
- ret = ENOMEM;
- break;
- case NBD_ENOSPC:
- ret = ENOSPC;
- break;
- case NBD_EOVERFLOW:
- ret = EOVERFLOW;
- break;
- case NBD_ENOTSUP:
- ret = ENOTSUP;
- break;
- case NBD_ESHUTDOWN:
- ret = ESHUTDOWN;
- break;
- default:
- trace_nbd_unknown_error(err);
- /* fallthrough */
- case NBD_EINVAL:
- ret = EINVAL;
- break;
- }
- return ret;
- }
|