Commit fa3d5b85c681518b6e4ec515814dcb2d5b702b89

Authored by K. Y. Srinivasan
Committed by Greg Kroah-Hartman
1 parent e485ceac9e

Drivers: hv: Support the newly introduced KVP messages in the driver

Support the newly defined KVP message types. It turns out that the host
pushes a set of standard key value pairs as soon as the guest opens the KVP channel.
Since we cannot handle these tuples until the user level daemon loads up, defer
reading the KVP channel until the user level daemon is launched.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 3 changed files with 176 additions and 51 deletions Side-by-side Diff

... ... @@ -42,9 +42,10 @@
42 42 static struct {
43 43 bool active; /* transaction status - active or not */
44 44 int recv_len; /* number of bytes received. */
45   - int index; /* current index */
  45 + struct hv_kvp_msg *kvp_msg; /* current message */
46 46 struct vmbus_channel *recv_channel; /* chn we got the request */
47 47 u64 recv_req_id; /* request ID. */
  48 + void *kvp_context; /* for the channel callback */
48 49 } kvp_transaction;
49 50  
50 51 static void kvp_send_key(struct work_struct *dummy);
51 52  
52 53  
... ... @@ -110,12 +111,15 @@
110 111 struct hv_kvp_msg_enumerate *data;
111 112  
112 113 message = (struct hv_kvp_msg *)msg->data;
113   - if (message->kvp_hdr.operation == KVP_OP_REGISTER) {
  114 + switch (message->kvp_hdr.operation) {
  115 + case KVP_OP_REGISTER:
114 116 pr_info("KVP: user-mode registering done.\n");
115 117 kvp_register();
116   - }
  118 + kvp_transaction.active = false;
  119 + hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
  120 + break;
117 121  
118   - if (message->kvp_hdr.operation == KVP_OP_ENUMERATE) {
  122 + default:
119 123 data = &message->body.kvp_enum_data;
120 124 /*
121 125 * Complete the transaction by forwarding the key value
122 126  
123 127  
124 128  
125 129  
... ... @@ -133,21 +137,104 @@
133 137 {
134 138 struct cn_msg *msg;
135 139 struct hv_kvp_msg *message;
136   - int index = kvp_transaction.index;
  140 + struct hv_kvp_msg *in_msg;
  141 + __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
  142 + __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
  143 + __u32 val32;
  144 + __u64 val64;
137 145  
138 146 msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
  147 + if (!msg)
  148 + return;
139 149  
140   - if (msg) {
141   - msg->id.idx = CN_KVP_IDX;
142   - msg->id.val = CN_KVP_VAL;
  150 + msg->id.idx = CN_KVP_IDX;
  151 + msg->id.val = CN_KVP_VAL;
143 152  
144   - message = (struct hv_kvp_msg *)msg->data;
145   - message->kvp_hdr.operation = KVP_OP_ENUMERATE;
146   - message->body.kvp_enum_data.index = index;
147   - msg->len = sizeof(struct hv_kvp_msg);
148   - cn_netlink_send(msg, 0, GFP_ATOMIC);
149   - kfree(msg);
  153 + message = (struct hv_kvp_msg *)msg->data;
  154 + message->kvp_hdr.operation = operation;
  155 + message->kvp_hdr.pool = pool;
  156 + in_msg = kvp_transaction.kvp_msg;
  157 +
  158 + /*
  159 + * The key/value strings sent from the host are encoded in
  160 + * in utf16; convert it to utf8 strings.
  161 + * The host assures us that the utf16 strings will not exceed
  162 + * the max lengths specified. We will however, reserve room
  163 + * for the string terminating character - in the utf16s_utf8s()
  164 + * function we limit the size of the buffer where the converted
  165 + * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
  166 + * that the strings can be properly terminated!
  167 + */
  168 +
  169 + switch (message->kvp_hdr.operation) {
  170 + case KVP_OP_SET:
  171 + switch (in_msg->body.kvp_set.data.value_type) {
  172 + case REG_SZ:
  173 + /*
  174 + * The value is a string - utf16 encoding.
  175 + */
  176 + message->body.kvp_set.data.value_size =
  177 + utf16s_to_utf8s(
  178 + (wchar_t *)in_msg->body.kvp_set.data.value,
  179 + in_msg->body.kvp_set.data.value_size,
  180 + UTF16_LITTLE_ENDIAN,
  181 + message->body.kvp_set.data.value,
  182 + HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
  183 + break;
  184 +
  185 + case REG_U32:
  186 + /*
  187 + * The value is a 32 bit scalar.
  188 + * We save this as a utf8 string.
  189 + */
  190 + val32 = in_msg->body.kvp_set.data.value_u32;
  191 + message->body.kvp_set.data.value_size =
  192 + sprintf(message->body.kvp_set.data.value,
  193 + "%d", val32) + 1;
  194 + break;
  195 +
  196 + case REG_U64:
  197 + /*
  198 + * The value is a 64 bit scalar.
  199 + * We save this as a utf8 string.
  200 + */
  201 + val64 = in_msg->body.kvp_set.data.value_u64;
  202 + message->body.kvp_set.data.value_size =
  203 + sprintf(message->body.kvp_set.data.value,
  204 + "%llu", val64) + 1;
  205 + break;
  206 +
  207 + }
  208 + case KVP_OP_GET:
  209 + message->body.kvp_set.data.key_size =
  210 + utf16s_to_utf8s(
  211 + (wchar_t *)in_msg->body.kvp_set.data.key,
  212 + in_msg->body.kvp_set.data.key_size,
  213 + UTF16_LITTLE_ENDIAN,
  214 + message->body.kvp_set.data.key,
  215 + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
  216 + break;
  217 +
  218 + case KVP_OP_DELETE:
  219 + message->body.kvp_delete.key_size =
  220 + utf16s_to_utf8s(
  221 + (wchar_t *)in_msg->body.kvp_delete.key,
  222 + in_msg->body.kvp_delete.key_size,
  223 + UTF16_LITTLE_ENDIAN,
  224 + message->body.kvp_delete.key,
  225 + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
  226 + break;
  227 +
  228 + case KVP_OP_ENUMERATE:
  229 + message->body.kvp_enum_data.index =
  230 + in_msg->body.kvp_enum_data.index;
  231 + break;
150 232 }
  233 +
  234 + msg->len = sizeof(struct hv_kvp_msg);
  235 + cn_netlink_send(msg, 0, GFP_ATOMIC);
  236 + kfree(msg);
  237 +
151 238 return;
152 239 }
153 240  
154 241  
... ... @@ -159,10 +246,11 @@
159 246 kvp_respond_to_host(char *key, char *value, int error)
160 247 {
161 248 struct hv_kvp_msg *kvp_msg;
162   - struct hv_kvp_msg_enumerate *kvp_data;
  249 + struct hv_kvp_exchg_msg_value *kvp_data;
163 250 char *key_name;
164 251 struct icmsg_hdr *icmsghdrp;
165   - int keylen, valuelen;
  252 + int keylen = 0;
  253 + int valuelen = 0;
166 254 u32 buf_len;
167 255 struct vmbus_channel *channel;
168 256 u64 req_id;
... ... @@ -189,6 +277,9 @@
189 277  
190 278 kvp_transaction.active = false;
191 279  
  280 + icmsghdrp = (struct icmsg_hdr *)
  281 + &recv_buffer[sizeof(struct vmbuspipe_hdr)];
  282 +
192 283 if (channel->onchannel_callback == NULL)
193 284 /*
194 285 * We have raced with util driver being unloaded;
195 286  
196 287  
197 288  
198 289  
199 290  
200 291  
201 292  
... ... @@ -196,42 +287,67 @@
196 287 */
197 288 return;
198 289  
199   - icmsghdrp = (struct icmsg_hdr *)
200   - &recv_buffer[sizeof(struct vmbuspipe_hdr)];
201   - kvp_msg = (struct hv_kvp_msg *)
202   - &recv_buffer[sizeof(struct vmbuspipe_hdr) +
203   - sizeof(struct icmsg_hdr)];
204   - kvp_data = &kvp_msg->body.kvp_enum_data;
205   - key_name = key;
206 290  
207 291 /*
208 292 * If the error parameter is set, terminate the host's enumeration.
209 293 */
210 294 if (error) {
211 295 /*
212   - * We don't support this index or the we have timedout;
  296 + * Something failed or the we have timedout;
213 297 * terminate the host-side iteration by returning an error.
214 298 */
215 299 icmsghdrp->status = HV_E_FAIL;
216 300 goto response_done;
217 301 }
218 302  
  303 + icmsghdrp->status = HV_S_OK;
  304 +
  305 + kvp_msg = (struct hv_kvp_msg *)
  306 + &recv_buffer[sizeof(struct vmbuspipe_hdr) +
  307 + sizeof(struct icmsg_hdr)];
  308 +
  309 + switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
  310 + case KVP_OP_GET:
  311 + kvp_data = &kvp_msg->body.kvp_get.data;
  312 + goto copy_value;
  313 +
  314 + case KVP_OP_SET:
  315 + case KVP_OP_DELETE:
  316 + goto response_done;
  317 +
  318 + default:
  319 + break;
  320 + }
  321 +
  322 + kvp_data = &kvp_msg->body.kvp_enum_data.data;
  323 + key_name = key;
  324 +
219 325 /*
220 326 * The windows host expects the key/value pair to be encoded
221   - * in utf16.
  327 + * in utf16. Ensure that the key/value size reported to the host
  328 + * will be less than or equal to the MAX size (including the
  329 + * terminating character).
222 330 */
223 331 keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
224   - (wchar_t *) kvp_data->data.key,
225   - HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2);
226   - kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
  332 + (wchar_t *) kvp_data->key,
  333 + (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2);
  334 + kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
  335 +
  336 +copy_value:
227 337 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
228   - (wchar_t *) kvp_data->data.value,
229   - HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2);
230   - kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
  338 + (wchar_t *) kvp_data->value,
  339 + (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
  340 + kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */
231 341  
232   - kvp_data->data.value_type = REG_SZ; /* all our values are strings */
233   - icmsghdrp->status = HV_S_OK;
  342 + /*
  343 + * If the utf8s to utf16s conversion failed; notify host
  344 + * of the error.
  345 + */
  346 + if ((keylen < 0) || (valuelen < 0))
  347 + icmsghdrp->status = HV_E_FAIL;
234 348  
  349 + kvp_data->value_type = REG_SZ; /* all our values are strings */
  350 +
235 351 response_done:
236 352 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
237 353  
238 354  
... ... @@ -257,11 +373,18 @@
257 373 u64 requestid;
258 374  
259 375 struct hv_kvp_msg *kvp_msg;
260   - struct hv_kvp_msg_enumerate *kvp_data;
261 376  
262 377 struct icmsg_hdr *icmsghdrp;
263 378 struct icmsg_negotiate *negop = NULL;
264 379  
  380 + if (kvp_transaction.active) {
  381 + /*
  382 + * We will defer processing this callback once
  383 + * the current transaction is complete.
  384 + */
  385 + kvp_transaction.kvp_context = context;
  386 + return;
  387 + }
265 388  
266 389 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
267 390  
268 391  
269 392  
270 393  
... ... @@ -276,29 +399,16 @@
276 399 sizeof(struct vmbuspipe_hdr) +
277 400 sizeof(struct icmsg_hdr)];
278 401  
279   - kvp_data = &kvp_msg->body.kvp_enum_data;
280   -
281 402 /*
282   - * We only support the "get" operation on
283   - * "KVP_POOL_AUTO" pool.
284   - */
285   -
286   - if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
287   - (kvp_msg->kvp_hdr.operation !=
288   - KVP_OP_ENUMERATE)) {
289   - icmsghdrp->status = HV_E_FAIL;
290   - goto callback_done;
291   - }
292   -
293   - /*
294 403 * Stash away this global state for completing the
295 404 * transaction; note transactions are serialized.
296 405 */
  406 +
297 407 kvp_transaction.recv_len = recvlen;
298 408 kvp_transaction.recv_channel = channel;
299 409 kvp_transaction.recv_req_id = requestid;
300 410 kvp_transaction.active = true;
301   - kvp_transaction.index = kvp_data->index;
  411 + kvp_transaction.kvp_msg = kvp_msg;
302 412  
303 413 /*
304 414 * Get the information from the
... ... @@ -316,8 +426,6 @@
316 426  
317 427 }
318 428  
319   -callback_done:
320   -
321 429 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
322 430 | ICMSGHDRFLAG_RESPONSE;
323 431  
... ... @@ -337,6 +445,14 @@
337 445 if (err)
338 446 return err;
339 447 recv_buffer = srv->recv_buffer;
  448 +
  449 + /*
  450 + * When this driver loads, the user level daemon that
  451 + * processes the host requests may not yet be running.
  452 + * Defer processing channel callbacks until the daemon
  453 + * has registered.
  454 + */
  455 + kvp_transaction.active = true;
340 456  
341 457 return 0;
342 458 }
include/linux/hyperv.h
... ... @@ -119,6 +119,8 @@
119 119 */
120 120  
121 121 #define REG_SZ 1
  122 +#define REG_U32 4
  123 +#define REG_U64 8
122 124  
123 125 enum hv_kvp_exchg_op {
124 126 KVP_OP_GET = 0,
tools/hv/hv_kvp_daemon.c
... ... @@ -389,10 +389,16 @@
389 389 }
390 390 continue;
391 391  
  392 + case KVP_OP_SET:
  393 + case KVP_OP_GET:
  394 + case KVP_OP_DELETE:
392 395 default:
393 396 break;
394 397 }
395 398  
  399 + if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
  400 + goto kvp_done;
  401 +
396 402 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
397 403 key_name = (char *)hv_msg->body.kvp_enum_data.data.key;
398 404 key_value = (char *)hv_msg->body.kvp_enum_data.data.value;
... ... @@ -454,6 +460,7 @@
454 460 * already in the receive buffer. Update the cn_msg header to
455 461 * reflect the key value that has been added to the message
456 462 */
  463 +kvp_done:
457 464  
458 465 incoming_cn_msg->id.idx = CN_KVP_IDX;
459 466 incoming_cn_msg->id.val = CN_KVP_VAL;