Annotation of qemu/block-nbd.c, revision 1.1

1.1     ! root        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