|
|
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:
1.1.1.3 ! root 36: #define EN_OPTSTR ":exportname="
! 37:
1.1 root 38: typedef struct BDRVNBDState {
39: int sock;
40: off_t size;
41: size_t blocksize;
42: } BDRVNBDState;
43:
44: static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
45: {
46: BDRVNBDState *s = bs->opaque;
1.1.1.3 ! root 47: uint32_t nbdflags;
! 48:
! 49: char *file;
! 50: char *name;
1.1 root 51: const char *host;
52: const char *unixpath;
53: int sock;
54: off_t size;
55: size_t blocksize;
56: int ret;
1.1.1.3 ! root 57: int err = -EINVAL;
! 58:
! 59: file = qemu_strdup(filename);
1.1 root 60:
1.1.1.3 ! root 61: name = strstr(file, EN_OPTSTR);
! 62: if (name) {
! 63: if (name[strlen(EN_OPTSTR)] == 0) {
! 64: goto out;
! 65: }
! 66: name[0] = 0;
! 67: name += strlen(EN_OPTSTR);
! 68: }
! 69:
! 70: if (!strstart(file, "nbd:", &host)) {
! 71: goto out;
! 72: }
1.1 root 73:
74: if (strstart(host, "unix:", &unixpath)) {
75:
1.1.1.3 ! root 76: if (unixpath[0] != '/') {
! 77: goto out;
! 78: }
1.1 root 79:
80: sock = unix_socket_outgoing(unixpath);
81:
82: } else {
1.1.1.3 ! root 83: uint16_t port = NBD_DEFAULT_PORT;
1.1 root 84: char *p, *r;
85: char hostname[128];
86:
87: pstrcpy(hostname, 128, host);
88:
89: p = strchr(hostname, ':');
1.1.1.3 ! root 90: if (p != NULL) {
! 91: *p = '\0';
! 92: p++;
! 93:
! 94: port = strtol(p, &r, 0);
! 95: if (r == p) {
! 96: goto out;
! 97: }
! 98: }
1.1 root 99:
100: sock = tcp_socket_outgoing(hostname, port);
101: }
102:
1.1.1.3 ! root 103: if (sock == -1) {
! 104: err = -errno;
! 105: goto out;
! 106: }
1.1 root 107:
1.1.1.3 ! root 108: ret = nbd_receive_negotiate(sock, name, &nbdflags, &size, &blocksize);
! 109: if (ret == -1) {
! 110: err = -errno;
! 111: goto out;
! 112: }
1.1 root 113:
114: s->sock = sock;
115: s->size = size;
116: s->blocksize = blocksize;
1.1.1.3 ! root 117: err = 0;
1.1 root 118:
1.1.1.3 ! root 119: out:
! 120: qemu_free(file);
! 121: return err;
1.1 root 122: }
123:
124: static int nbd_read(BlockDriverState *bs, int64_t sector_num,
125: uint8_t *buf, int nb_sectors)
126: {
127: BDRVNBDState *s = bs->opaque;
128: struct nbd_request request;
129: struct nbd_reply reply;
130:
131: request.type = NBD_CMD_READ;
132: request.handle = (uint64_t)(intptr_t)bs;
133: request.from = sector_num * 512;;
134: request.len = nb_sectors * 512;
135:
136: if (nbd_send_request(s->sock, &request) == -1)
137: return -errno;
138:
139: if (nbd_receive_reply(s->sock, &reply) == -1)
140: return -errno;
141:
142: if (reply.error !=0)
143: return -reply.error;
144:
145: if (reply.handle != request.handle)
146: return -EIO;
147:
148: if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len)
149: return -EIO;
150:
151: return 0;
152: }
153:
154: static int nbd_write(BlockDriverState *bs, int64_t sector_num,
155: const uint8_t *buf, int nb_sectors)
156: {
157: BDRVNBDState *s = bs->opaque;
158: struct nbd_request request;
159: struct nbd_reply reply;
160:
161: request.type = NBD_CMD_WRITE;
162: request.handle = (uint64_t)(intptr_t)bs;
163: request.from = sector_num * 512;;
164: request.len = nb_sectors * 512;
165:
166: if (nbd_send_request(s->sock, &request) == -1)
167: return -errno;
168:
169: if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len)
170: return -EIO;
171:
172: if (nbd_receive_reply(s->sock, &reply) == -1)
173: return -errno;
174:
175: if (reply.error !=0)
176: return -reply.error;
177:
178: if (reply.handle != request.handle)
179: return -EIO;
180:
181: return 0;
182: }
183:
184: static void nbd_close(BlockDriverState *bs)
185: {
186: BDRVNBDState *s = bs->opaque;
187: struct nbd_request request;
188:
189: request.type = NBD_CMD_DISC;
190: request.handle = (uint64_t)(intptr_t)bs;
191: request.from = 0;
192: request.len = 0;
193: nbd_send_request(s->sock, &request);
194:
195: close(s->sock);
196: }
197:
198: static int64_t nbd_getlength(BlockDriverState *bs)
199: {
200: BDRVNBDState *s = bs->opaque;
201:
202: return s->size;
203: }
204:
205: static BlockDriver bdrv_nbd = {
206: .format_name = "nbd",
207: .instance_size = sizeof(BDRVNBDState),
1.1.1.2 root 208: .bdrv_file_open = nbd_open,
1.1 root 209: .bdrv_read = nbd_read,
210: .bdrv_write = nbd_write,
211: .bdrv_close = nbd_close,
212: .bdrv_getlength = nbd_getlength,
213: .protocol_name = "nbd",
214: };
215:
216: static void bdrv_nbd_init(void)
217: {
218: bdrv_register(&bdrv_nbd);
219: }
220:
221: block_init(bdrv_nbd_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.