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"
46 /* eflags calculation is the same between oldstyle and newstyle
50 protocol_compute_eflags (struct connection
*conn
, uint16_t *flags
)
52 uint16_t eflags
= NBD_FLAG_HAS_FLAGS
;
55 fl
= backend
->can_write (backend
, conn
);
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
);
67 eflags
|= NBD_FLAG_SEND_WRITE_ZEROES
;
68 conn
->can_zero
= true;
71 fl
= backend
->can_trim (backend
, conn
);
75 eflags
|= NBD_FLAG_SEND_TRIM
;
76 conn
->can_trim
= true;
79 fl
= backend
->can_fua (backend
, conn
);
83 eflags
|= NBD_FLAG_SEND_FUA
;
88 fl
= backend
->can_flush (backend
, conn
);
92 eflags
|= NBD_FLAG_SEND_FLUSH
;
93 conn
->can_flush
= true;
96 fl
= backend
->is_rotational (backend
, conn
);
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
);
111 eflags
|= NBD_FLAG_CAN_MULTI_CONN
;
112 conn
->can_multi_conn
= true;
116 fl
= backend
->can_cache (backend
, conn
);
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
);
134 conn
->can_extents
= true;
136 if (conn
->structured_replies
)
137 eflags
|= NBD_FLAG_SEND_DF
;
144 protocol_handshake (struct connection
*conn
)
150 r
= protocol_handshake_oldstyle (conn
);
152 r
= protocol_handshake_newstyle (conn
);
153 unlock_request (conn
);