dummy support for cm_fclken2_core register
[qemu] / block-nbd.c
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     .format_name        = "nbd",
181     .instance_size      = sizeof(BDRVNBDState),
182     .bdrv_open          = nbd_open,
183     .bdrv_read          = nbd_read,
184     .bdrv_write         = nbd_write,
185     .bdrv_close         = nbd_close,
186     .bdrv_getlength     = nbd_getlength,
187     .protocol_name      = "nbd",
188 };