~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to block/nbd.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include "block/block_int.h"
33
33
#include "qemu/module.h"
34
34
#include "qemu/sockets.h"
 
35
#include "qapi/qmp/qjson.h"
 
36
#include "qapi/qmp/qint.h"
35
37
 
36
38
#include <sys/types.h>
37
39
#include <unistd.h>
65
67
    Coroutine *recv_coroutine[MAX_NBD_REQUESTS];
66
68
    struct nbd_reply reply;
67
69
 
68
 
    int is_unix;
69
 
    char *host_spec;
 
70
    bool is_unix;
 
71
    QemuOpts *socket_opts;
 
72
 
70
73
    char *export_name; /* An NBD server may export several devices */
71
74
} BDRVNBDState;
72
75
 
73
 
static int nbd_parse_uri(BDRVNBDState *s, const char *filename)
 
76
static int nbd_parse_uri(const char *filename, QDict *options)
74
77
{
75
78
    URI *uri;
76
79
    const char *p;
77
80
    QueryParams *qp = NULL;
78
81
    int ret = 0;
 
82
    bool is_unix;
79
83
 
80
84
    uri = uri_parse(filename);
81
85
    if (!uri) {
84
88
 
85
89
    /* transport */
86
90
    if (!strcmp(uri->scheme, "nbd")) {
87
 
        s->is_unix = false;
 
91
        is_unix = false;
88
92
    } else if (!strcmp(uri->scheme, "nbd+tcp")) {
89
 
        s->is_unix = false;
 
93
        is_unix = false;
90
94
    } else if (!strcmp(uri->scheme, "nbd+unix")) {
91
 
        s->is_unix = true;
 
95
        is_unix = true;
92
96
    } else {
93
97
        ret = -EINVAL;
94
98
        goto out;
97
101
    p = uri->path ? uri->path : "/";
98
102
    p += strspn(p, "/");
99
103
    if (p[0]) {
100
 
        s->export_name = g_strdup(p);
 
104
        qdict_put(options, "export", qstring_from_str(p));
101
105
    }
102
106
 
103
107
    qp = query_params_parse(uri->query);
104
 
    if (qp->n > 1 || (s->is_unix && !qp->n) || (!s->is_unix && qp->n)) {
 
108
    if (qp->n > 1 || (is_unix && !qp->n) || (!is_unix && qp->n)) {
105
109
        ret = -EINVAL;
106
110
        goto out;
107
111
    }
108
112
 
109
 
    if (s->is_unix) {
 
113
    if (is_unix) {
110
114
        /* nbd+unix:///export?socket=path */
111
115
        if (uri->server || uri->port || strcmp(qp->p[0].name, "socket")) {
112
116
            ret = -EINVAL;
113
117
            goto out;
114
118
        }
115
 
        s->host_spec = g_strdup(qp->p[0].value);
 
119
        qdict_put(options, "path", qstring_from_str(qp->p[0].value));
116
120
    } else {
117
 
        /* nbd[+tcp]://host:port/export */
 
121
        /* nbd[+tcp]://host[:port]/export */
118
122
        if (!uri->server) {
119
123
            ret = -EINVAL;
120
124
            goto out;
121
125
        }
122
 
        if (!uri->port) {
123
 
            uri->port = NBD_DEFAULT_PORT;
 
126
 
 
127
        qdict_put(options, "host", qstring_from_str(uri->server));
 
128
        if (uri->port) {
 
129
            char* port_str = g_strdup_printf("%d", uri->port);
 
130
            qdict_put(options, "port", qstring_from_str(port_str));
 
131
            g_free(port_str);
124
132
        }
125
 
        s->host_spec = g_strdup_printf("%s:%d", uri->server, uri->port);
126
133
    }
127
134
 
128
135
out:
133
140
    return ret;
134
141
}
135
142
 
136
 
static int nbd_config(BDRVNBDState *s, const char *filename)
 
143
static void nbd_parse_filename(const char *filename, QDict *options,
 
144
                               Error **errp)
137
145
{
138
146
    char *file;
139
147
    char *export_name;
140
148
    const char *host_spec;
141
149
    const char *unixpath;
142
 
    int err = -EINVAL;
 
150
 
 
151
    if (qdict_haskey(options, "host")
 
152
        || qdict_haskey(options, "port")
 
153
        || qdict_haskey(options, "path"))
 
154
    {
 
155
        error_setg(errp, "host/port/path and a file name may not be specified "
 
156
                         "at the same time");
 
157
        return;
 
158
    }
143
159
 
144
160
    if (strstr(filename, "://")) {
145
 
        return nbd_parse_uri(s, filename);
 
161
        int ret = nbd_parse_uri(filename, options);
 
162
        if (ret < 0) {
 
163
            error_setg(errp, "No valid URL specified");
 
164
        }
 
165
        return;
146
166
    }
147
167
 
148
168
    file = g_strdup(filename);
154
174
        }
155
175
        export_name[0] = 0; /* truncate 'file' */
156
176
        export_name += strlen(EN_OPTSTR);
157
 
        s->export_name = g_strdup(export_name);
 
177
 
 
178
        qdict_put(options, "export", qstring_from_str(export_name));
158
179
    }
159
180
 
160
181
    /* extract the host_spec - fail if it's not nbd:... */
161
182
    if (!strstart(file, "nbd:", &host_spec)) {
 
183
        error_setg(errp, "File name string for NBD must start with 'nbd:'");
 
184
        goto out;
 
185
    }
 
186
 
 
187
    if (!*host_spec) {
162
188
        goto out;
163
189
    }
164
190
 
165
191
    /* are we a UNIX or TCP socket? */
166
192
    if (strstart(host_spec, "unix:", &unixpath)) {
167
 
        s->is_unix = true;
168
 
        s->host_spec = g_strdup(unixpath);
 
193
        qdict_put(options, "path", qstring_from_str(unixpath));
169
194
    } else {
170
 
        s->is_unix = false;
171
 
        s->host_spec = g_strdup(host_spec);
 
195
        InetSocketAddress *addr = NULL;
 
196
 
 
197
        addr = inet_parse(host_spec, errp);
 
198
        if (error_is_set(errp)) {
 
199
            goto out;
 
200
        }
 
201
 
 
202
        qdict_put(options, "host", qstring_from_str(addr->host));
 
203
        qdict_put(options, "port", qstring_from_str(addr->port));
 
204
        qapi_free_InetSocketAddress(addr);
172
205
    }
173
206
 
174
 
    err = 0;
175
 
 
176
207
out:
177
208
    g_free(file);
178
 
    if (err != 0) {
179
 
        g_free(s->export_name);
180
 
        g_free(s->host_spec);
181
 
    }
182
 
    return err;
183
 
}
 
209
}
 
210
 
 
211
static int nbd_config(BDRVNBDState *s, QDict *options)
 
212
{
 
213
    Error *local_err = NULL;
 
214
 
 
215
    if (qdict_haskey(options, "path")) {
 
216
        if (qdict_haskey(options, "host")) {
 
217
            qerror_report(ERROR_CLASS_GENERIC_ERROR, "path and host may not "
 
218
                          "be used at the same time.");
 
219
            return -EINVAL;
 
220
        }
 
221
        s->is_unix = true;
 
222
    } else if (qdict_haskey(options, "host")) {
 
223
        s->is_unix = false;
 
224
    } else {
 
225
        return -EINVAL;
 
226
    }
 
227
 
 
228
    s->socket_opts = qemu_opts_create_nofail(&socket_optslist);
 
229
 
 
230
    qemu_opts_absorb_qdict(s->socket_opts, options, &local_err);
 
231
    if (error_is_set(&local_err)) {
 
232
        qerror_report_err(local_err);
 
233
        error_free(local_err);
 
234
        return -EINVAL;
 
235
    }
 
236
 
 
237
    if (!qemu_opt_get(s->socket_opts, "port")) {
 
238
        qemu_opt_set_number(s->socket_opts, "port", NBD_DEFAULT_PORT);
 
239
    }
 
240
 
 
241
    s->export_name = g_strdup(qdict_get_try_str(options, "export"));
 
242
    if (s->export_name) {
 
243
        qdict_del(options, "export");
 
244
    }
 
245
 
 
246
    return 0;
 
247
}
 
248
 
184
249
 
185
250
static void nbd_coroutine_start(BDRVNBDState *s, struct nbd_request *request)
186
251
{
269
334
    s->send_coroutine = qemu_coroutine_self();
270
335
    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write,
271
336
                            nbd_have_request, s);
272
 
    rc = nbd_send_request(s->sock, request);
273
 
    if (rc >= 0 && qiov) {
274
 
        ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov,
275
 
                            offset, request->len);
276
 
        if (ret != request->len) {
277
 
            return -EIO;
278
 
        }
 
337
    if (qiov) {
 
338
        if (!s->is_unix) {
 
339
            socket_set_cork(s->sock, 1);
 
340
        }
 
341
        rc = nbd_send_request(s->sock, request);
 
342
        if (rc >= 0) {
 
343
            ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov,
 
344
                                offset, request->len);
 
345
            if (ret != request->len) {
 
346
                rc = -EIO;
 
347
            }
 
348
        }
 
349
        if (!s->is_unix) {
 
350
            socket_set_cork(s->sock, 0);
 
351
        }
 
352
    } else {
 
353
        rc = nbd_send_request(s->sock, request);
279
354
    }
280
355
    qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL,
281
356
                            nbd_have_request, s);
328
403
    size_t blocksize;
329
404
 
330
405
    if (s->is_unix) {
331
 
        sock = unix_socket_outgoing(s->host_spec);
 
406
        sock = unix_socket_outgoing(qemu_opt_get(s->socket_opts, "path"));
332
407
    } else {
333
 
        sock = tcp_socket_outgoing_spec(s->host_spec);
 
408
        sock = tcp_socket_outgoing_opts(s->socket_opts);
 
409
        if (sock >= 0) {
 
410
            socket_set_nodelay(sock);
 
411
        }
334
412
    }
335
413
 
336
414
    /* Failed to establish connection */
350
428
 
351
429
    /* Now that we're connected, set the socket to be non-blocking and
352
430
     * kick the reply mechanism.  */
353
 
    socket_set_nonblock(sock);
 
431
    qemu_set_nonblock(sock);
354
432
    qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL,
355
433
                            nbd_have_request, s);
356
434
 
376
454
    closesocket(s->sock);
377
455
}
378
456
 
379
 
static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
 
457
static int nbd_open(BlockDriverState *bs, QDict *options, int flags)
380
458
{
381
459
    BDRVNBDState *s = bs->opaque;
382
460
    int result;
385
463
    qemu_co_mutex_init(&s->free_sema);
386
464
 
387
465
    /* Pop the config into our state object. Exit if invalid. */
388
 
    result = nbd_config(s, filename);
 
466
    result = nbd_config(s, options);
389
467
    if (result != 0) {
390
468
        return result;
391
469
    }
531
609
        return 0;
532
610
    }
533
611
    request.type = NBD_CMD_TRIM;
534
 
    request.from = sector_num * 512;;
 
612
    request.from = sector_num * 512;
535
613
    request.len = nb_sectors * 512;
536
614
 
537
615
    nbd_coroutine_start(s, &request);
549
627
{
550
628
    BDRVNBDState *s = bs->opaque;
551
629
    g_free(s->export_name);
552
 
    g_free(s->host_spec);
 
630
    qemu_opts_del(s->socket_opts);
553
631
 
554
632
    nbd_teardown_connection(bs);
555
633
}
565
643
    .format_name         = "nbd",
566
644
    .protocol_name       = "nbd",
567
645
    .instance_size       = sizeof(BDRVNBDState),
 
646
    .bdrv_parse_filename = nbd_parse_filename,
568
647
    .bdrv_file_open      = nbd_open,
569
648
    .bdrv_co_readv       = nbd_co_readv,
570
649
    .bdrv_co_writev      = nbd_co_writev,
578
657
    .format_name         = "nbd",
579
658
    .protocol_name       = "nbd+tcp",
580
659
    .instance_size       = sizeof(BDRVNBDState),
 
660
    .bdrv_parse_filename = nbd_parse_filename,
581
661
    .bdrv_file_open      = nbd_open,
582
662
    .bdrv_co_readv       = nbd_co_readv,
583
663
    .bdrv_co_writev      = nbd_co_writev,
591
671
    .format_name         = "nbd",
592
672
    .protocol_name       = "nbd+unix",
593
673
    .instance_size       = sizeof(BDRVNBDState),
 
674
    .bdrv_parse_filename = nbd_parse_filename,
594
675
    .bdrv_file_open      = nbd_open,
595
676
    .bdrv_co_readv       = nbd_co_readv,
596
677
    .bdrv_co_writev      = nbd_co_writev,