xref: /openbmc/qemu/nbd/common.c (revision 623d7e3551a6fc5693c06ea938c60fe281b52e27)
1  /*
2   *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3   *
4   *  Network Block Device Common Code
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
8   *  the Free Software Foundation; under version 2 of the License.
9   *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  #include "qemu/osdep.h"
20  #include "trace.h"
21  #include "nbd-internal.h"
22  
23  /* Discard length bytes from channel.  Return -errno on failure and 0 on
24   * success */
25  int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
26  {
27      ssize_t ret = 0;
28      char small[1024];
29      char *buffer;
30  
31      buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
32      while (size > 0) {
33          ssize_t count = MIN(65536, size);
34          ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp);
35  
36          if (ret < 0) {
37              goto cleanup;
38          }
39          size -= count;
40      }
41  
42   cleanup:
43      if (buffer != small) {
44          g_free(buffer);
45      }
46      return ret;
47  }
48  
49  
50  void nbd_tls_handshake(QIOTask *task,
51                         void *opaque)
52  {
53      struct NBDTLSHandshakeData *data = opaque;
54  
55      qio_task_propagate_error(task, &data->error);
56      data->complete = true;
57      g_main_loop_quit(data->loop);
58  }
59  
60  
61  const char *nbd_opt_lookup(uint32_t opt)
62  {
63      switch (opt) {
64      case NBD_OPT_EXPORT_NAME:
65          return "export name";
66      case NBD_OPT_ABORT:
67          return "abort";
68      case NBD_OPT_LIST:
69          return "list";
70      case NBD_OPT_STARTTLS:
71          return "starttls";
72      case NBD_OPT_INFO:
73          return "info";
74      case NBD_OPT_GO:
75          return "go";
76      case NBD_OPT_STRUCTURED_REPLY:
77          return "structured reply";
78      case NBD_OPT_LIST_META_CONTEXT:
79          return "list meta context";
80      case NBD_OPT_SET_META_CONTEXT:
81          return "set meta context";
82      default:
83          return "<unknown>";
84      }
85  }
86  
87  
88  const char *nbd_rep_lookup(uint32_t rep)
89  {
90      switch (rep) {
91      case NBD_REP_ACK:
92          return "ack";
93      case NBD_REP_SERVER:
94          return "server";
95      case NBD_REP_INFO:
96          return "info";
97      case NBD_REP_META_CONTEXT:
98          return "meta context";
99      case NBD_REP_ERR_UNSUP:
100          return "unsupported";
101      case NBD_REP_ERR_POLICY:
102          return "denied by policy";
103      case NBD_REP_ERR_INVALID:
104          return "invalid";
105      case NBD_REP_ERR_PLATFORM:
106          return "platform lacks support";
107      case NBD_REP_ERR_TLS_REQD:
108          return "TLS required";
109      case NBD_REP_ERR_UNKNOWN:
110          return "export unknown";
111      case NBD_REP_ERR_SHUTDOWN:
112          return "server shutting down";
113      case NBD_REP_ERR_BLOCK_SIZE_REQD:
114          return "block size required";
115      default:
116          return "<unknown>";
117      }
118  }
119  
120  
121  const char *nbd_info_lookup(uint16_t info)
122  {
123      switch (info) {
124      case NBD_INFO_EXPORT:
125          return "export";
126      case NBD_INFO_NAME:
127          return "name";
128      case NBD_INFO_DESCRIPTION:
129          return "description";
130      case NBD_INFO_BLOCK_SIZE:
131          return "block size";
132      default:
133          return "<unknown>";
134      }
135  }
136  
137  
138  const char *nbd_cmd_lookup(uint16_t cmd)
139  {
140      switch (cmd) {
141      case NBD_CMD_READ:
142          return "read";
143      case NBD_CMD_WRITE:
144          return "write";
145      case NBD_CMD_DISC:
146          return "disconnect";
147      case NBD_CMD_FLUSH:
148          return "flush";
149      case NBD_CMD_TRIM:
150          return "trim";
151      case NBD_CMD_CACHE:
152          return "cache";
153      case NBD_CMD_WRITE_ZEROES:
154          return "write zeroes";
155      case NBD_CMD_BLOCK_STATUS:
156          return "block status";
157      default:
158          return "<unknown>";
159      }
160  }
161  
162  
163  const char *nbd_reply_type_lookup(uint16_t type)
164  {
165      switch (type) {
166      case NBD_REPLY_TYPE_NONE:
167          return "none";
168      case NBD_REPLY_TYPE_OFFSET_DATA:
169          return "data";
170      case NBD_REPLY_TYPE_OFFSET_HOLE:
171          return "hole";
172      case NBD_REPLY_TYPE_BLOCK_STATUS:
173          return "block status";
174      case NBD_REPLY_TYPE_ERROR:
175          return "generic error";
176      case NBD_REPLY_TYPE_ERROR_OFFSET:
177          return "error at offset";
178      default:
179          if (type & (1 << 15)) {
180              return "<unknown error>";
181          }
182          return "<unknown>";
183      }
184  }
185  
186  
187  const char *nbd_err_lookup(int err)
188  {
189      switch (err) {
190      case NBD_SUCCESS:
191          return "success";
192      case NBD_EPERM:
193          return "EPERM";
194      case NBD_EIO:
195          return "EIO";
196      case NBD_ENOMEM:
197          return "ENOMEM";
198      case NBD_EINVAL:
199          return "EINVAL";
200      case NBD_ENOSPC:
201          return "ENOSPC";
202      case NBD_EOVERFLOW:
203          return "EOVERFLOW";
204      case NBD_ENOTSUP:
205          return "ENOTSUP";
206      case NBD_ESHUTDOWN:
207          return "ESHUTDOWN";
208      default:
209          return "<unknown>";
210      }
211  }
212  
213  
214  int nbd_errno_to_system_errno(int err)
215  {
216      int ret;
217      switch (err) {
218      case NBD_SUCCESS:
219          ret = 0;
220          break;
221      case NBD_EPERM:
222          ret = EPERM;
223          break;
224      case NBD_EIO:
225          ret = EIO;
226          break;
227      case NBD_ENOMEM:
228          ret = ENOMEM;
229          break;
230      case NBD_ENOSPC:
231          ret = ENOSPC;
232          break;
233      case NBD_EOVERFLOW:
234          ret = EOVERFLOW;
235          break;
236      case NBD_ENOTSUP:
237          ret = ENOTSUP;
238          break;
239      case NBD_ESHUTDOWN:
240          ret = ESHUTDOWN;
241          break;
242      default:
243          trace_nbd_unknown_error(err);
244          /* fallthrough */
245      case NBD_EINVAL:
246          ret = EINVAL;
247          break;
248      }
249      return ret;
250  }
251