File:  [Qemu by Fabrice Bellard] / qemu / block-nbd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:57 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    1: /*
    2:  * QEMU Block driver for  NBD
    3:  *
    4:  * Copyright (C) 2008 Bull S.A.S.
    5:  *     Author: Laurent Vivier <Laurent.Vivier@bull.net>
    6:  *
    7:  * Some parts:
    8:  *    Copyright (C) 2007 Anthony Liguori <anthony@codemonkey.ws>
    9:  *
   10:  * Permission is hereby granted, free of charge, to any person obtaining a copy
   11:  * of this software and associated documentation files (the "Software"), to deal
   12:  * in the Software without restriction, including without limitation the rights
   13:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   14:  * copies of the Software, and to permit persons to whom the Software is
   15:  * furnished to do so, subject to the following conditions:
   16:  *
   17:  * The above copyright notice and this permission notice shall be included in
   18:  * all copies or substantial portions of the Software.
   19:  *
   20:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   22:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   23:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   24:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   25:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   26:  * THE SOFTWARE.
   27:  */
   28: 
   29: #include "qemu-common.h"
   30: #include "nbd.h"
   31: 
   32: #include <sys/types.h>
   33: #include <unistd.h>
   34: 
   35: typedef struct BDRVNBDState {
   36:     int sock;
   37:     off_t size;
   38:     size_t blocksize;
   39: } BDRVNBDState;
   40: 
   41: static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
   42: {
   43:     BDRVNBDState *s = bs->opaque;
   44:     const char *host;
   45:     const char *unixpath;
   46:     int sock;
   47:     off_t size;
   48:     size_t blocksize;
   49:     int ret;
   50: 
   51:     if ((flags & BDRV_O_CREAT))
   52:         return -EINVAL;
   53: 
   54:     if (!strstart(filename, "nbd:", &host))
   55:         return -EINVAL;
   56: 
   57:     if (strstart(host, "unix:", &unixpath)) {
   58: 
   59:         if (unixpath[0] != '/')
   60:             return -EINVAL;
   61: 
   62:         sock = unix_socket_outgoing(unixpath);
   63: 
   64:     } else {
   65:         uint16_t port;
   66:         char *p, *r;
   67:         char hostname[128];
   68: 
   69:         pstrcpy(hostname, 128, host);
   70: 
   71:         p = strchr(hostname, ':');
   72:         if (p == NULL)
   73:             return -EINVAL;
   74: 
   75:         *p = '\0';
   76:         p++;
   77: 
   78:         port = strtol(p, &r, 0);
   79:         if (r == p)
   80:             return -EINVAL;
   81:         sock = tcp_socket_outgoing(hostname, port);
   82:     }
   83: 
   84:     if (sock == -1)
   85:         return -errno;
   86: 
   87:     ret = nbd_receive_negotiate(sock, &size, &blocksize);
   88:     if (ret == -1)
   89:         return -errno;
   90: 
   91:     s->sock = sock;
   92:     s->size = size;
   93:     s->blocksize = blocksize;
   94: 
   95:     return 0;
   96: }
   97: 
   98: static int nbd_read(BlockDriverState *bs, int64_t sector_num,
   99:                     uint8_t *buf, int nb_sectors)
  100: {
  101:     BDRVNBDState *s = bs->opaque;
  102:     struct nbd_request request;
  103:     struct nbd_reply reply;
  104: 
  105:     request.type = NBD_CMD_READ;
  106:     request.handle = (uint64_t)(intptr_t)bs;
  107:     request.from = sector_num * 512;;
  108:     request.len = nb_sectors * 512;
  109: 
  110:     if (nbd_send_request(s->sock, &request) == -1)
  111:         return -errno;
  112: 
  113:     if (nbd_receive_reply(s->sock, &reply) == -1)
  114:         return -errno;
  115: 
  116:     if (reply.error !=0)
  117:         return -reply.error;
  118: 
  119:     if (reply.handle != request.handle)
  120:         return -EIO;
  121: 
  122:     if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len)
  123:         return -EIO;
  124: 
  125:     return 0;
  126: }
  127: 
  128: static int nbd_write(BlockDriverState *bs, int64_t sector_num,
  129:                      const uint8_t *buf, int nb_sectors)
  130: {
  131:     BDRVNBDState *s = bs->opaque;
  132:     struct nbd_request request;
  133:     struct nbd_reply reply;
  134: 
  135:     request.type = NBD_CMD_WRITE;
  136:     request.handle = (uint64_t)(intptr_t)bs;
  137:     request.from = sector_num * 512;;
  138:     request.len = nb_sectors * 512;
  139: 
  140:     if (nbd_send_request(s->sock, &request) == -1)
  141:         return -errno;
  142: 
  143:     if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len)
  144:         return -EIO;
  145: 
  146:     if (nbd_receive_reply(s->sock, &reply) == -1)
  147:         return -errno;
  148: 
  149:     if (reply.error !=0)
  150:         return -reply.error;
  151: 
  152:     if (reply.handle != request.handle)
  153:         return -EIO;
  154: 
  155:     return 0;
  156: }
  157: 
  158: static void nbd_close(BlockDriverState *bs)
  159: {
  160:     BDRVNBDState *s = bs->opaque;
  161:     struct nbd_request request;
  162: 
  163:     request.type = NBD_CMD_DISC;
  164:     request.handle = (uint64_t)(intptr_t)bs;
  165:     request.from = 0;
  166:     request.len = 0;
  167:     nbd_send_request(s->sock, &request);
  168: 
  169:     close(s->sock);
  170: }
  171: 
  172: static int64_t nbd_getlength(BlockDriverState *bs)
  173: {
  174:     BDRVNBDState *s = bs->opaque;
  175: 
  176:     return s->size;
  177: }
  178: 
  179: BlockDriver bdrv_nbd = {
  180:     "nbd",
  181:     sizeof(BDRVNBDState),
  182:     NULL, /* no probe for protocols */
  183:     nbd_open,
  184:     nbd_read,
  185:     nbd_write,
  186:     nbd_close,
  187:     .bdrv_getlength = nbd_getlength,
  188:     .protocol_name = "nbd",
  189: };

unix.superglobalmegacorp.com