|
|
1.1 ! root 1: /* ! 2: * QEMU Block driver for NBD ! 3: * ! 4: * Copyright (C) 2008 Bull S.A.S. ! 5: * Author: Laurent Vivier <[email protected]> ! 6: * ! 7: * Some parts: ! 8: * Copyright (C) 2007 Anthony Liguori <[email protected]> ! 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: #include "module.h" ! 32: ! 33: #include <sys/types.h> ! 34: #include <unistd.h> ! 35: ! 36: typedef struct BDRVNBDState { ! 37: int sock; ! 38: off_t size; ! 39: size_t blocksize; ! 40: } BDRVNBDState; ! 41: ! 42: static int nbd_open(BlockDriverState *bs, const char* filename, int flags) ! 43: { ! 44: BDRVNBDState *s = bs->opaque; ! 45: const char *host; ! 46: const char *unixpath; ! 47: int sock; ! 48: off_t size; ! 49: size_t blocksize; ! 50: int ret; ! 51: ! 52: if ((flags & BDRV_O_CREAT)) ! 53: return -EINVAL; ! 54: ! 55: if (!strstart(filename, "nbd:", &host)) ! 56: return -EINVAL; ! 57: ! 58: if (strstart(host, "unix:", &unixpath)) { ! 59: ! 60: if (unixpath[0] != '/') ! 61: return -EINVAL; ! 62: ! 63: sock = unix_socket_outgoing(unixpath); ! 64: ! 65: } else { ! 66: uint16_t port; ! 67: char *p, *r; ! 68: char hostname[128]; ! 69: ! 70: pstrcpy(hostname, 128, host); ! 71: ! 72: p = strchr(hostname, ':'); ! 73: if (p == NULL) ! 74: return -EINVAL; ! 75: ! 76: *p = '\0'; ! 77: p++; ! 78: ! 79: port = strtol(p, &r, 0); ! 80: if (r == p) ! 81: return -EINVAL; ! 82: sock = tcp_socket_outgoing(hostname, port); ! 83: } ! 84: ! 85: if (sock == -1) ! 86: return -errno; ! 87: ! 88: ret = nbd_receive_negotiate(sock, &size, &blocksize); ! 89: if (ret == -1) ! 90: return -errno; ! 91: ! 92: s->sock = sock; ! 93: s->size = size; ! 94: s->blocksize = blocksize; ! 95: ! 96: return 0; ! 97: } ! 98: ! 99: static int nbd_read(BlockDriverState *bs, int64_t sector_num, ! 100: uint8_t *buf, int nb_sectors) ! 101: { ! 102: BDRVNBDState *s = bs->opaque; ! 103: struct nbd_request request; ! 104: struct nbd_reply reply; ! 105: ! 106: request.type = NBD_CMD_READ; ! 107: request.handle = (uint64_t)(intptr_t)bs; ! 108: request.from = sector_num * 512;; ! 109: request.len = nb_sectors * 512; ! 110: ! 111: if (nbd_send_request(s->sock, &request) == -1) ! 112: return -errno; ! 113: ! 114: if (nbd_receive_reply(s->sock, &reply) == -1) ! 115: return -errno; ! 116: ! 117: if (reply.error !=0) ! 118: return -reply.error; ! 119: ! 120: if (reply.handle != request.handle) ! 121: return -EIO; ! 122: ! 123: if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len) ! 124: return -EIO; ! 125: ! 126: return 0; ! 127: } ! 128: ! 129: static int nbd_write(BlockDriverState *bs, int64_t sector_num, ! 130: const uint8_t *buf, int nb_sectors) ! 131: { ! 132: BDRVNBDState *s = bs->opaque; ! 133: struct nbd_request request; ! 134: struct nbd_reply reply; ! 135: ! 136: request.type = NBD_CMD_WRITE; ! 137: request.handle = (uint64_t)(intptr_t)bs; ! 138: request.from = sector_num * 512;; ! 139: request.len = nb_sectors * 512; ! 140: ! 141: if (nbd_send_request(s->sock, &request) == -1) ! 142: return -errno; ! 143: ! 144: if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len) ! 145: return -EIO; ! 146: ! 147: if (nbd_receive_reply(s->sock, &reply) == -1) ! 148: return -errno; ! 149: ! 150: if (reply.error !=0) ! 151: return -reply.error; ! 152: ! 153: if (reply.handle != request.handle) ! 154: return -EIO; ! 155: ! 156: return 0; ! 157: } ! 158: ! 159: static void nbd_close(BlockDriverState *bs) ! 160: { ! 161: BDRVNBDState *s = bs->opaque; ! 162: struct nbd_request request; ! 163: ! 164: request.type = NBD_CMD_DISC; ! 165: request.handle = (uint64_t)(intptr_t)bs; ! 166: request.from = 0; ! 167: request.len = 0; ! 168: nbd_send_request(s->sock, &request); ! 169: ! 170: close(s->sock); ! 171: } ! 172: ! 173: static int64_t nbd_getlength(BlockDriverState *bs) ! 174: { ! 175: BDRVNBDState *s = bs->opaque; ! 176: ! 177: return s->size; ! 178: } ! 179: ! 180: static BlockDriver bdrv_nbd = { ! 181: .format_name = "nbd", ! 182: .instance_size = sizeof(BDRVNBDState), ! 183: .bdrv_open = nbd_open, ! 184: .bdrv_read = nbd_read, ! 185: .bdrv_write = nbd_write, ! 186: .bdrv_close = nbd_close, ! 187: .bdrv_getlength = nbd_getlength, ! 188: .protocol_name = "nbd", ! 189: }; ! 190: ! 191: static void bdrv_nbd_init(void) ! 192: { ! 193: bdrv_register(&bdrv_nbd); ! 194: } ! 195: ! 196: block_init(bdrv_nbd_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.