|
|
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.