xref: /openbmc/qemu/nbd/common.c (revision 77bcaf5f222fb19667738dc2ca7dec6172d69db7)
1798bfe00SFam Zheng /*
2798bfe00SFam Zheng  *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
3798bfe00SFam Zheng  *
4798bfe00SFam Zheng  *  Network Block Device Common Code
5798bfe00SFam Zheng  *
6798bfe00SFam Zheng  *  This program is free software; you can redistribute it and/or modify
7798bfe00SFam Zheng  *  it under the terms of the GNU General Public License as published by
8798bfe00SFam Zheng  *  the Free Software Foundation; under version 2 of the License.
9798bfe00SFam Zheng  *
10798bfe00SFam Zheng  *  This program is distributed in the hope that it will be useful,
11798bfe00SFam Zheng  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12798bfe00SFam Zheng  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13798bfe00SFam Zheng  *  GNU General Public License for more details.
14798bfe00SFam Zheng  *
15798bfe00SFam Zheng  *  You should have received a copy of the GNU General Public License
16798bfe00SFam Zheng  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
17798bfe00SFam Zheng  */
18798bfe00SFam Zheng 
19d38ea87aSPeter Maydell #include "qemu/osdep.h"
20dd689440SEric Blake #include "trace.h"
21798bfe00SFam Zheng #include "nbd-internal.h"
22798bfe00SFam Zheng 
2344298024SVladimir Sementsov-Ogievskiy /* Discard length bytes from channel.  Return -errno on failure and 0 on
2444298024SVladimir Sementsov-Ogievskiy  * success */
nbd_drop(QIOChannel * ioc,size_t size,Error ** errp)2544298024SVladimir Sementsov-Ogievskiy int nbd_drop(QIOChannel *ioc, size_t size, Error **errp)
2644298024SVladimir Sementsov-Ogievskiy {
2744298024SVladimir Sementsov-Ogievskiy     ssize_t ret = 0;
2844298024SVladimir Sementsov-Ogievskiy     char small[1024];
2944298024SVladimir Sementsov-Ogievskiy     char *buffer;
3044298024SVladimir Sementsov-Ogievskiy 
3144298024SVladimir Sementsov-Ogievskiy     buffer = sizeof(small) >= size ? small : g_malloc(MIN(65536, size));
3244298024SVladimir Sementsov-Ogievskiy     while (size > 0) {
3344298024SVladimir Sementsov-Ogievskiy         ssize_t count = MIN(65536, size);
34e6798f06SVladimir Sementsov-Ogievskiy         ret = nbd_read(ioc, buffer, MIN(65536, size), NULL, errp);
3544298024SVladimir Sementsov-Ogievskiy 
3644298024SVladimir Sementsov-Ogievskiy         if (ret < 0) {
3744298024SVladimir Sementsov-Ogievskiy             goto cleanup;
3844298024SVladimir Sementsov-Ogievskiy         }
3944298024SVladimir Sementsov-Ogievskiy         size -= count;
4044298024SVladimir Sementsov-Ogievskiy     }
4144298024SVladimir Sementsov-Ogievskiy 
4244298024SVladimir Sementsov-Ogievskiy  cleanup:
4344298024SVladimir Sementsov-Ogievskiy     if (buffer != small) {
4444298024SVladimir Sementsov-Ogievskiy         g_free(buffer);
4544298024SVladimir Sementsov-Ogievskiy     }
4644298024SVladimir Sementsov-Ogievskiy     return ret;
4744298024SVladimir Sementsov-Ogievskiy }
4844298024SVladimir Sementsov-Ogievskiy 
49f95910feSDaniel P. Berrange 
nbd_opt_lookup(uint32_t opt)503736cc5bSEric Blake const char *nbd_opt_lookup(uint32_t opt)
513736cc5bSEric Blake {
523736cc5bSEric Blake     switch (opt) {
533736cc5bSEric Blake     case NBD_OPT_EXPORT_NAME:
543736cc5bSEric Blake         return "export name";
553736cc5bSEric Blake     case NBD_OPT_ABORT:
563736cc5bSEric Blake         return "abort";
573736cc5bSEric Blake     case NBD_OPT_LIST:
583736cc5bSEric Blake         return "list";
593736cc5bSEric Blake     case NBD_OPT_STARTTLS:
603736cc5bSEric Blake         return "starttls";
613736cc5bSEric Blake     case NBD_OPT_INFO:
623736cc5bSEric Blake         return "info";
633736cc5bSEric Blake     case NBD_OPT_GO:
643736cc5bSEric Blake         return "go";
653736cc5bSEric Blake     case NBD_OPT_STRUCTURED_REPLY:
663736cc5bSEric Blake         return "structured reply";
6725c14678SVladimir Sementsov-Ogievskiy     case NBD_OPT_LIST_META_CONTEXT:
6825c14678SVladimir Sementsov-Ogievskiy         return "list meta context";
6925c14678SVladimir Sementsov-Ogievskiy     case NBD_OPT_SET_META_CONTEXT:
7025c14678SVladimir Sementsov-Ogievskiy         return "set meta context";
71*d95ffb6fSEric Blake     case NBD_OPT_EXTENDED_HEADERS:
72*d95ffb6fSEric Blake         return "extended headers";
733736cc5bSEric Blake     default:
743736cc5bSEric Blake         return "<unknown>";
753736cc5bSEric Blake     }
763736cc5bSEric Blake }
773736cc5bSEric Blake 
783736cc5bSEric Blake 
nbd_rep_lookup(uint32_t rep)793736cc5bSEric Blake const char *nbd_rep_lookup(uint32_t rep)
803736cc5bSEric Blake {
813736cc5bSEric Blake     switch (rep) {
823736cc5bSEric Blake     case NBD_REP_ACK:
833736cc5bSEric Blake         return "ack";
843736cc5bSEric Blake     case NBD_REP_SERVER:
853736cc5bSEric Blake         return "server";
863736cc5bSEric Blake     case NBD_REP_INFO:
873736cc5bSEric Blake         return "info";
8825c14678SVladimir Sementsov-Ogievskiy     case NBD_REP_META_CONTEXT:
8925c14678SVladimir Sementsov-Ogievskiy         return "meta context";
903736cc5bSEric Blake     case NBD_REP_ERR_UNSUP:
913736cc5bSEric Blake         return "unsupported";
923736cc5bSEric Blake     case NBD_REP_ERR_POLICY:
933736cc5bSEric Blake         return "denied by policy";
943736cc5bSEric Blake     case NBD_REP_ERR_INVALID:
953736cc5bSEric Blake         return "invalid";
963736cc5bSEric Blake     case NBD_REP_ERR_PLATFORM:
973736cc5bSEric Blake         return "platform lacks support";
983736cc5bSEric Blake     case NBD_REP_ERR_TLS_REQD:
993736cc5bSEric Blake         return "TLS required";
1003736cc5bSEric Blake     case NBD_REP_ERR_UNKNOWN:
1013736cc5bSEric Blake         return "export unknown";
1023736cc5bSEric Blake     case NBD_REP_ERR_SHUTDOWN:
1033736cc5bSEric Blake         return "server shutting down";
1043736cc5bSEric Blake     case NBD_REP_ERR_BLOCK_SIZE_REQD:
1053736cc5bSEric Blake         return "block size required";
106*d95ffb6fSEric Blake     case NBD_REP_ERR_TOO_BIG:
107*d95ffb6fSEric Blake         return "option payload too big";
108*d95ffb6fSEric Blake     case NBD_REP_ERR_EXT_HEADER_REQD:
109*d95ffb6fSEric Blake         return "extended headers required";
1103736cc5bSEric Blake     default:
1113736cc5bSEric Blake         return "<unknown>";
1123736cc5bSEric Blake     }
1133736cc5bSEric Blake }
1143736cc5bSEric Blake 
1153736cc5bSEric Blake 
nbd_info_lookup(uint16_t info)1163736cc5bSEric Blake const char *nbd_info_lookup(uint16_t info)
1173736cc5bSEric Blake {
1183736cc5bSEric Blake     switch (info) {
1193736cc5bSEric Blake     case NBD_INFO_EXPORT:
1203736cc5bSEric Blake         return "export";
1213736cc5bSEric Blake     case NBD_INFO_NAME:
1223736cc5bSEric Blake         return "name";
1233736cc5bSEric Blake     case NBD_INFO_DESCRIPTION:
1243736cc5bSEric Blake         return "description";
1253736cc5bSEric Blake     case NBD_INFO_BLOCK_SIZE:
1263736cc5bSEric Blake         return "block size";
1273736cc5bSEric Blake     default:
1283736cc5bSEric Blake         return "<unknown>";
1293736cc5bSEric Blake     }
1303736cc5bSEric Blake }
1313736cc5bSEric Blake 
1323736cc5bSEric Blake 
nbd_cmd_lookup(uint16_t cmd)1333736cc5bSEric Blake const char *nbd_cmd_lookup(uint16_t cmd)
1343736cc5bSEric Blake {
1353736cc5bSEric Blake     switch (cmd) {
1363736cc5bSEric Blake     case NBD_CMD_READ:
1373736cc5bSEric Blake         return "read";
1383736cc5bSEric Blake     case NBD_CMD_WRITE:
1393736cc5bSEric Blake         return "write";
1403736cc5bSEric Blake     case NBD_CMD_DISC:
141dad3946eSEric Blake         return "disconnect";
1423736cc5bSEric Blake     case NBD_CMD_FLUSH:
1433736cc5bSEric Blake         return "flush";
1443736cc5bSEric Blake     case NBD_CMD_TRIM:
1453736cc5bSEric Blake         return "trim";
146bc37b06aSVladimir Sementsov-Ogievskiy     case NBD_CMD_CACHE:
147bc37b06aSVladimir Sementsov-Ogievskiy         return "cache";
1483736cc5bSEric Blake     case NBD_CMD_WRITE_ZEROES:
1493736cc5bSEric Blake         return "write zeroes";
15025c14678SVladimir Sementsov-Ogievskiy     case NBD_CMD_BLOCK_STATUS:
15125c14678SVladimir Sementsov-Ogievskiy         return "block status";
1523736cc5bSEric Blake     default:
1533736cc5bSEric Blake         return "<unknown>";
1543736cc5bSEric Blake     }
1553736cc5bSEric Blake }
156e7a78d0eSEric Blake 
157e7a78d0eSEric Blake 
nbd_reply_type_lookup(uint16_t type)158bae245d1SEric Blake const char *nbd_reply_type_lookup(uint16_t type)
159bae245d1SEric Blake {
160bae245d1SEric Blake     switch (type) {
161bae245d1SEric Blake     case NBD_REPLY_TYPE_NONE:
162bae245d1SEric Blake         return "none";
163bae245d1SEric Blake     case NBD_REPLY_TYPE_OFFSET_DATA:
164bae245d1SEric Blake         return "data";
165bae245d1SEric Blake     case NBD_REPLY_TYPE_OFFSET_HOLE:
166bae245d1SEric Blake         return "hole";
16725c14678SVladimir Sementsov-Ogievskiy     case NBD_REPLY_TYPE_BLOCK_STATUS:
168*d95ffb6fSEric Blake         return "block status (32-bit)";
169*d95ffb6fSEric Blake     case NBD_REPLY_TYPE_BLOCK_STATUS_EXT:
170*d95ffb6fSEric Blake         return "block status (64-bit)";
171bae245d1SEric Blake     case NBD_REPLY_TYPE_ERROR:
172bae245d1SEric Blake         return "generic error";
173bae245d1SEric Blake     case NBD_REPLY_TYPE_ERROR_OFFSET:
174bae245d1SEric Blake         return "error at offset";
175bae245d1SEric Blake     default:
176bae245d1SEric Blake         if (type & (1 << 15)) {
177bae245d1SEric Blake             return "<unknown error>";
178bae245d1SEric Blake         }
179bae245d1SEric Blake         return "<unknown>";
180bae245d1SEric Blake     }
181bae245d1SEric Blake }
182bae245d1SEric Blake 
183bae245d1SEric Blake 
nbd_err_lookup(int err)184e7a78d0eSEric Blake const char *nbd_err_lookup(int err)
185e7a78d0eSEric Blake {
186e7a78d0eSEric Blake     switch (err) {
187e7a78d0eSEric Blake     case NBD_SUCCESS:
188e7a78d0eSEric Blake         return "success";
189e7a78d0eSEric Blake     case NBD_EPERM:
190e7a78d0eSEric Blake         return "EPERM";
191e7a78d0eSEric Blake     case NBD_EIO:
192e7a78d0eSEric Blake         return "EIO";
193e7a78d0eSEric Blake     case NBD_ENOMEM:
194e7a78d0eSEric Blake         return "ENOMEM";
195e7a78d0eSEric Blake     case NBD_EINVAL:
196e7a78d0eSEric Blake         return "EINVAL";
197e7a78d0eSEric Blake     case NBD_ENOSPC:
198e7a78d0eSEric Blake         return "ENOSPC";
199bae245d1SEric Blake     case NBD_EOVERFLOW:
200bae245d1SEric Blake         return "EOVERFLOW";
2010a479545SEric Blake     case NBD_ENOTSUP:
2020a479545SEric Blake         return "ENOTSUP";
203e7a78d0eSEric Blake     case NBD_ESHUTDOWN:
204e7a78d0eSEric Blake         return "ESHUTDOWN";
205e7a78d0eSEric Blake     default:
206e7a78d0eSEric Blake         return "<unknown>";
207e7a78d0eSEric Blake     }
208e7a78d0eSEric Blake }
209dd689440SEric Blake 
210dd689440SEric Blake 
nbd_errno_to_system_errno(int err)211dd689440SEric Blake int nbd_errno_to_system_errno(int err)
212dd689440SEric Blake {
213dd689440SEric Blake     int ret;
214dd689440SEric Blake     switch (err) {
215dd689440SEric Blake     case NBD_SUCCESS:
216dd689440SEric Blake         ret = 0;
217dd689440SEric Blake         break;
218dd689440SEric Blake     case NBD_EPERM:
219dd689440SEric Blake         ret = EPERM;
220dd689440SEric Blake         break;
221dd689440SEric Blake     case NBD_EIO:
222dd689440SEric Blake         ret = EIO;
223dd689440SEric Blake         break;
224dd689440SEric Blake     case NBD_ENOMEM:
225dd689440SEric Blake         ret = ENOMEM;
226dd689440SEric Blake         break;
227dd689440SEric Blake     case NBD_ENOSPC:
228dd689440SEric Blake         ret = ENOSPC;
229dd689440SEric Blake         break;
230bae245d1SEric Blake     case NBD_EOVERFLOW:
231bae245d1SEric Blake         ret = EOVERFLOW;
232bae245d1SEric Blake         break;
2330a479545SEric Blake     case NBD_ENOTSUP:
2340a479545SEric Blake         ret = ENOTSUP;
2350a479545SEric Blake         break;
236dd689440SEric Blake     case NBD_ESHUTDOWN:
237dd689440SEric Blake         ret = ESHUTDOWN;
238dd689440SEric Blake         break;
239dd689440SEric Blake     default:
240dd689440SEric Blake         trace_nbd_unknown_error(err);
241dd689440SEric Blake         /* fallthrough */
242dd689440SEric Blake     case NBD_EINVAL:
243dd689440SEric Blake         ret = EINVAL;
244dd689440SEric Blake         break;
245dd689440SEric Blake     }
246dd689440SEric Blake     return ret;
247dd689440SEric Blake }
248bfe04d0aSEric Blake 
249bfe04d0aSEric Blake 
nbd_mode_lookup(NBDMode mode)250bfe04d0aSEric Blake const char *nbd_mode_lookup(NBDMode mode)
251bfe04d0aSEric Blake {
252bfe04d0aSEric Blake     switch (mode) {
253bfe04d0aSEric Blake     case NBD_MODE_OLDSTYLE:
254bfe04d0aSEric Blake         return "oldstyle";
255bfe04d0aSEric Blake     case NBD_MODE_EXPORT_NAME:
256bfe04d0aSEric Blake         return "export name only";
257bfe04d0aSEric Blake     case NBD_MODE_SIMPLE:
258bfe04d0aSEric Blake         return "simple headers";
259bfe04d0aSEric Blake     case NBD_MODE_STRUCTURED:
260bfe04d0aSEric Blake         return "structured replies";
261*d95ffb6fSEric Blake     case NBD_MODE_EXTENDED:
262*d95ffb6fSEric Blake         return "extended headers";
263bfe04d0aSEric Blake     default:
264bfe04d0aSEric Blake         return "<unknown>";
265bfe04d0aSEric Blake     }
266bfe04d0aSEric Blake }
267