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
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
43 #include "byte-swapping.h"
44 #include "nbd-protocol.h"
47 protocol_handshake (struct connection
*conn
)
53 r
= protocol_handshake_oldstyle (conn
);
55 r
= protocol_handshake_newstyle (conn
);
56 unlock_request (conn
);
61 /* Common code used by oldstyle and newstyle protocols to:
63 * - call the backend .open method
65 * - get the export size
67 * - compute the eflags (same between oldstyle and newstyle
70 * The protocols must defer this as late as possible so that
71 * unauthorized clients can't cause unnecessary work in .open by
72 * simply opening a TCP connection.
75 protocol_common_open (struct connection
*conn
,
76 uint64_t *exportsize
, uint16_t *flags
)
79 uint16_t eflags
= NBD_FLAG_HAS_FLAGS
;
82 if (backend_open (backend
, conn
, read_only
) == -1)
85 /* Prepare (for filters), called just after open. */
86 if (backend_prepare (backend
, conn
) == -1)
89 size
= backend_get_size (backend
, conn
);
93 nbdkit_error (".get_size function returned invalid value "
94 "(%" PRIi64
")", size
);
98 /* Check all flags even if they won't be advertised, to prime the
99 * cache and make later request validation easier.
101 fl
= backend_can_write (backend
, conn
);
105 eflags
|= NBD_FLAG_READ_ONLY
;
107 fl
= backend_can_zero (backend
, conn
);
111 eflags
|= NBD_FLAG_SEND_WRITE_ZEROES
;
113 fl
= backend_can_fast_zero (backend
, conn
);
117 eflags
|= NBD_FLAG_SEND_FAST_ZERO
;
119 fl
= backend_can_trim (backend
, conn
);
123 eflags
|= NBD_FLAG_SEND_TRIM
;
125 fl
= backend_can_fua (backend
, conn
);
129 eflags
|= NBD_FLAG_SEND_FUA
;
131 fl
= backend_can_flush (backend
, conn
);
135 eflags
|= NBD_FLAG_SEND_FLUSH
;
137 fl
= backend_is_rotational (backend
, conn
);
141 eflags
|= NBD_FLAG_ROTATIONAL
;
143 /* multi-conn is useless if parallel connections are not allowed. */
144 fl
= backend_can_multi_conn (backend
, conn
);
147 if (fl
&& (backend
->thread_model (backend
) >
148 NBDKIT_THREAD_MODEL_SERIALIZE_CONNECTIONS
))
149 eflags
|= NBD_FLAG_CAN_MULTI_CONN
;
151 fl
= backend_can_cache (backend
, conn
);
155 eflags
|= NBD_FLAG_SEND_CACHE
;
157 /* The result of this is not directly advertised as part of the
158 * handshake, but priming the cache here makes BLOCK_STATUS handling
159 * not have to worry about errors, and makes test-layers easier to
162 fl
= backend_can_extents (backend
, conn
);
166 if (conn
->structured_replies
)
167 eflags
|= NBD_FLAG_SEND_DF
;