server: Rework storage of per-backend handle
[nbdkit/ericb.git] / server / protocol-handshake.c
blob4d12b3dc16557c2783eb209f5d22ab551ef7d726
1 /* nbdkit
2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
33 #include <config.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <inttypes.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "internal.h"
43 #include "byte-swapping.h"
44 #include "protocol.h"
46 /* eflags calculation is the same between oldstyle and newstyle
47 * protocols.
49 int
50 protocol_compute_eflags (struct connection *conn, uint16_t *flags)
52 uint16_t eflags = NBD_FLAG_HAS_FLAGS;
53 int fl;
55 fl = backend_can_write (backend, conn);
56 if (fl == -1)
57 return -1;
58 if (readonly || !fl) {
59 eflags |= NBD_FLAG_READ_ONLY;
60 conn->readonly = true;
62 if (!conn->readonly) {
63 fl = backend_can_zero (backend, conn);
64 if (fl == -1)
65 return -1;
66 if (fl) {
67 eflags |= NBD_FLAG_SEND_WRITE_ZEROES;
68 conn->can_zero = true;
71 fl = backend_can_trim (backend, conn);
72 if (fl == -1)
73 return -1;
74 if (fl) {
75 eflags |= NBD_FLAG_SEND_TRIM;
76 conn->can_trim = true;
79 fl = backend_can_fua (backend, conn);
80 if (fl == -1)
81 return -1;
82 if (fl) {
83 eflags |= NBD_FLAG_SEND_FUA;
84 conn->can_fua = true;
88 fl = backend_can_flush (backend, conn);
89 if (fl == -1)
90 return -1;
91 if (fl) {
92 eflags |= NBD_FLAG_SEND_FLUSH;
93 conn->can_flush = true;
96 fl = backend_is_rotational (backend, conn);
97 if (fl == -1)
98 return -1;
99 if (fl) {
100 eflags |= NBD_FLAG_ROTATIONAL;
101 conn->is_rotational = true;
104 /* multi-conn is useless if parallel connections are not allowed */
105 if (backend->thread_model (backend) >
106 NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS) {
107 fl = backend_can_multi_conn (backend, conn);
108 if (fl == -1)
109 return -1;
110 if (fl) {
111 eflags |= NBD_FLAG_CAN_MULTI_CONN;
112 conn->can_multi_conn = true;
116 fl = backend_can_cache (backend, conn);
117 if (fl == -1)
118 return -1;
119 if (fl) {
120 eflags |= NBD_FLAG_SEND_CACHE;
121 conn->can_cache = true;
122 conn->emulate_cache = fl == NBDKIT_CACHE_EMULATE;
125 /* The result of this is not returned to callers here (or at any
126 * time during the handshake). However it makes sense to do it once
127 * per connection and store the result in the handle anyway. This
128 * protocol_compute_eflags function is a bit misnamed XXX.
130 fl = backend_can_extents (backend, conn);
131 if (fl == -1)
132 return -1;
133 if (fl)
134 conn->can_extents = true;
136 if (conn->structured_replies)
137 eflags |= NBD_FLAG_SEND_DF;
139 *flags = eflags;
140 return 0;
144 protocol_handshake (struct connection *conn)
146 int r;
148 lock_request (conn);
149 if (!newstyle)
150 r = protocol_handshake_oldstyle (conn);
151 else
152 r = protocol_handshake_newstyle (conn);
153 unlock_request (conn);
155 return r;