Statistics
| Branch: | Revision:

root / block / nbd.c @ e685b4eb

History | View | Annotate | Download (5.2 kB)

1 75818250 ths
/*
2 75818250 ths
 * QEMU Block driver for  NBD
3 75818250 ths
 *
4 75818250 ths
 * Copyright (C) 2008 Bull S.A.S.
5 bd5921b4 malc
 *     Author: Laurent Vivier <Laurent.Vivier@bull.net>
6 75818250 ths
 *
7 75818250 ths
 * Some parts:
8 75818250 ths
 *    Copyright (C) 2007 Anthony Liguori <anthony@codemonkey.ws>
9 75818250 ths
 *
10 75818250 ths
 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 75818250 ths
 * of this software and associated documentation files (the "Software"), to deal
12 75818250 ths
 * in the Software without restriction, including without limitation the rights
13 75818250 ths
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 75818250 ths
 * copies of the Software, and to permit persons to whom the Software is
15 75818250 ths
 * furnished to do so, subject to the following conditions:
16 75818250 ths
 *
17 75818250 ths
 * The above copyright notice and this permission notice shall be included in
18 75818250 ths
 * all copies or substantial portions of the Software.
19 75818250 ths
 *
20 75818250 ths
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 75818250 ths
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 75818250 ths
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 75818250 ths
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 75818250 ths
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 75818250 ths
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 75818250 ths
 * THE SOFTWARE.
27 75818250 ths
 */
28 75818250 ths
29 75818250 ths
#include "qemu-common.h"
30 75818250 ths
#include "nbd.h"
31 5efa9d5a Anthony Liguori
#include "module.h"
32 75818250 ths
33 75818250 ths
#include <sys/types.h>
34 75818250 ths
#include <unistd.h>
35 75818250 ths
36 1d45f8b5 Laurent Vivier
#define EN_OPTSTR ":exportname="
37 1d45f8b5 Laurent Vivier
38 75818250 ths
typedef struct BDRVNBDState {
39 75818250 ths
    int sock;
40 75818250 ths
    off_t size;
41 75818250 ths
    size_t blocksize;
42 75818250 ths
} BDRVNBDState;
43 75818250 ths
44 75818250 ths
static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
45 75818250 ths
{
46 75818250 ths
    BDRVNBDState *s = bs->opaque;
47 1d45f8b5 Laurent Vivier
    uint32_t nbdflags;
48 1d45f8b5 Laurent Vivier
49 1d45f8b5 Laurent Vivier
    char *file;
50 1d45f8b5 Laurent Vivier
    char *name;
51 75818250 ths
    const char *host;
52 75818250 ths
    const char *unixpath;
53 75818250 ths
    int sock;
54 75818250 ths
    off_t size;
55 75818250 ths
    size_t blocksize;
56 75818250 ths
    int ret;
57 1d45f8b5 Laurent Vivier
    int err = -EINVAL;
58 75818250 ths
59 1d45f8b5 Laurent Vivier
    file = qemu_strdup(filename);
60 1d45f8b5 Laurent Vivier
61 1d45f8b5 Laurent Vivier
    name = strstr(file, EN_OPTSTR);
62 1d45f8b5 Laurent Vivier
    if (name) {
63 1d45f8b5 Laurent Vivier
        if (name[strlen(EN_OPTSTR)] == 0) {
64 1d45f8b5 Laurent Vivier
            goto out;
65 1d45f8b5 Laurent Vivier
        }
66 1d45f8b5 Laurent Vivier
        name[0] = 0;
67 1d45f8b5 Laurent Vivier
        name += strlen(EN_OPTSTR);
68 1d45f8b5 Laurent Vivier
    }
69 1d45f8b5 Laurent Vivier
70 1d45f8b5 Laurent Vivier
    if (!strstart(file, "nbd:", &host)) {
71 1d45f8b5 Laurent Vivier
        goto out;
72 1d45f8b5 Laurent Vivier
    }
73 75818250 ths
74 75818250 ths
    if (strstart(host, "unix:", &unixpath)) {
75 75818250 ths
76 1d45f8b5 Laurent Vivier
        if (unixpath[0] != '/') {
77 1d45f8b5 Laurent Vivier
            goto out;
78 1d45f8b5 Laurent Vivier
        }
79 75818250 ths
80 75818250 ths
        sock = unix_socket_outgoing(unixpath);
81 75818250 ths
82 75818250 ths
    } else {
83 1d45f8b5 Laurent Vivier
        uint16_t port = NBD_DEFAULT_PORT;
84 75818250 ths
        char *p, *r;
85 75818250 ths
        char hostname[128];
86 75818250 ths
87 75818250 ths
        pstrcpy(hostname, 128, host);
88 75818250 ths
89 75818250 ths
        p = strchr(hostname, ':');
90 1d45f8b5 Laurent Vivier
        if (p != NULL) {
91 1d45f8b5 Laurent Vivier
            *p = '\0';
92 1d45f8b5 Laurent Vivier
            p++;
93 1d45f8b5 Laurent Vivier
94 1d45f8b5 Laurent Vivier
            port = strtol(p, &r, 0);
95 1d45f8b5 Laurent Vivier
            if (r == p) {
96 1d45f8b5 Laurent Vivier
                goto out;
97 1d45f8b5 Laurent Vivier
            }
98 1d45f8b5 Laurent Vivier
        }
99 75818250 ths
100 75818250 ths
        sock = tcp_socket_outgoing(hostname, port);
101 75818250 ths
    }
102 75818250 ths
103 1d45f8b5 Laurent Vivier
    if (sock == -1) {
104 1d45f8b5 Laurent Vivier
        err = -errno;
105 1d45f8b5 Laurent Vivier
        goto out;
106 1d45f8b5 Laurent Vivier
    }
107 75818250 ths
108 1d45f8b5 Laurent Vivier
    ret = nbd_receive_negotiate(sock, name, &nbdflags, &size, &blocksize);
109 1d45f8b5 Laurent Vivier
    if (ret == -1) {
110 1d45f8b5 Laurent Vivier
        err = -errno;
111 1d45f8b5 Laurent Vivier
        goto out;
112 1d45f8b5 Laurent Vivier
    }
113 75818250 ths
114 75818250 ths
    s->sock = sock;
115 75818250 ths
    s->size = size;
116 75818250 ths
    s->blocksize = blocksize;
117 1d45f8b5 Laurent Vivier
    err = 0;
118 75818250 ths
119 1d45f8b5 Laurent Vivier
out:
120 1d45f8b5 Laurent Vivier
    qemu_free(file);
121 1d45f8b5 Laurent Vivier
    return err;
122 75818250 ths
}
123 75818250 ths
124 75818250 ths
static int nbd_read(BlockDriverState *bs, int64_t sector_num,
125 75818250 ths
                    uint8_t *buf, int nb_sectors)
126 75818250 ths
{
127 75818250 ths
    BDRVNBDState *s = bs->opaque;
128 75818250 ths
    struct nbd_request request;
129 75818250 ths
    struct nbd_reply reply;
130 75818250 ths
131 75818250 ths
    request.type = NBD_CMD_READ;
132 75818250 ths
    request.handle = (uint64_t)(intptr_t)bs;
133 75818250 ths
    request.from = sector_num * 512;;
134 75818250 ths
    request.len = nb_sectors * 512;
135 75818250 ths
136 75818250 ths
    if (nbd_send_request(s->sock, &request) == -1)
137 75818250 ths
        return -errno;
138 75818250 ths
139 75818250 ths
    if (nbd_receive_reply(s->sock, &reply) == -1)
140 75818250 ths
        return -errno;
141 75818250 ths
142 75818250 ths
    if (reply.error !=0)
143 75818250 ths
        return -reply.error;
144 75818250 ths
145 75818250 ths
    if (reply.handle != request.handle)
146 75818250 ths
        return -EIO;
147 75818250 ths
148 75818250 ths
    if (nbd_wr_sync(s->sock, buf, request.len, 1) != request.len)
149 75818250 ths
        return -EIO;
150 75818250 ths
151 75818250 ths
    return 0;
152 75818250 ths
}
153 75818250 ths
154 75818250 ths
static int nbd_write(BlockDriverState *bs, int64_t sector_num,
155 75818250 ths
                     const uint8_t *buf, int nb_sectors)
156 75818250 ths
{
157 75818250 ths
    BDRVNBDState *s = bs->opaque;
158 75818250 ths
    struct nbd_request request;
159 75818250 ths
    struct nbd_reply reply;
160 75818250 ths
161 75818250 ths
    request.type = NBD_CMD_WRITE;
162 75818250 ths
    request.handle = (uint64_t)(intptr_t)bs;
163 75818250 ths
    request.from = sector_num * 512;;
164 75818250 ths
    request.len = nb_sectors * 512;
165 75818250 ths
166 75818250 ths
    if (nbd_send_request(s->sock, &request) == -1)
167 75818250 ths
        return -errno;
168 75818250 ths
169 75818250 ths
    if (nbd_wr_sync(s->sock, (uint8_t*)buf, request.len, 0) != request.len)
170 75818250 ths
        return -EIO;
171 75818250 ths
172 75818250 ths
    if (nbd_receive_reply(s->sock, &reply) == -1)
173 75818250 ths
        return -errno;
174 75818250 ths
175 75818250 ths
    if (reply.error !=0)
176 75818250 ths
        return -reply.error;
177 75818250 ths
178 75818250 ths
    if (reply.handle != request.handle)
179 75818250 ths
        return -EIO;
180 75818250 ths
181 75818250 ths
    return 0;
182 75818250 ths
}
183 75818250 ths
184 75818250 ths
static void nbd_close(BlockDriverState *bs)
185 75818250 ths
{
186 75818250 ths
    BDRVNBDState *s = bs->opaque;
187 75818250 ths
    struct nbd_request request;
188 75818250 ths
189 75818250 ths
    request.type = NBD_CMD_DISC;
190 75818250 ths
    request.handle = (uint64_t)(intptr_t)bs;
191 75818250 ths
    request.from = 0;
192 75818250 ths
    request.len = 0;
193 75818250 ths
    nbd_send_request(s->sock, &request);
194 75818250 ths
195 75818250 ths
    close(s->sock);
196 75818250 ths
}
197 75818250 ths
198 75818250 ths
static int64_t nbd_getlength(BlockDriverState *bs)
199 75818250 ths
{
200 75818250 ths
    BDRVNBDState *s = bs->opaque;
201 75818250 ths
202 75818250 ths
    return s->size;
203 75818250 ths
}
204 75818250 ths
205 5efa9d5a Anthony Liguori
static BlockDriver bdrv_nbd = {
206 e60f469c aurel32
    .format_name        = "nbd",
207 e60f469c aurel32
    .instance_size        = sizeof(BDRVNBDState),
208 66f82cee Kevin Wolf
    .bdrv_file_open        = nbd_open,
209 e60f469c aurel32
    .bdrv_read                = nbd_read,
210 e60f469c aurel32
    .bdrv_write                = nbd_write,
211 e60f469c aurel32
    .bdrv_close                = nbd_close,
212 e60f469c aurel32
    .bdrv_getlength        = nbd_getlength,
213 e60f469c aurel32
    .protocol_name        = "nbd",
214 75818250 ths
};
215 5efa9d5a Anthony Liguori
216 5efa9d5a Anthony Liguori
static void bdrv_nbd_init(void)
217 5efa9d5a Anthony Liguori
{
218 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_nbd);
219 5efa9d5a Anthony Liguori
}
220 5efa9d5a Anthony Liguori
221 5efa9d5a Anthony Liguori
block_init(bdrv_nbd_init);