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