Commit b47a81dcc5a806efb6d970608299129771588289

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

Drivers: hv: kvp: Cleanup error handling in KVP

In preparation to implementing IP injection, cleanup the way we propagate
and handle errors both in the driver as well as in the user level daemon.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Olaf Hering <olaf@aepfle.de>
Reviewed-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 3 changed files with 135 additions and 62 deletions Side-by-side Diff

... ... @@ -48,13 +48,24 @@
48 48 void *kvp_context; /* for the channel callback */
49 49 } kvp_transaction;
50 50  
  51 +/*
  52 + * Before we can accept KVP messages from the host, we need
  53 + * to handshake with the user level daemon. This state tracks
  54 + * if we are in the handshake phase.
  55 + */
  56 +static bool in_hand_shake = true;
  57 +
  58 +/*
  59 + * This state maintains the version number registered by the daemon.
  60 + */
  61 +static int dm_reg_value;
  62 +
51 63 static void kvp_send_key(struct work_struct *dummy);
52 64  
53   -#define TIMEOUT_FIRED 1
54 65  
55 66 static void kvp_respond_to_host(char *key, char *value, int error);
56 67 static void kvp_work_func(struct work_struct *dummy);
57   -static void kvp_register(void);
  68 +static void kvp_register(int);
58 69  
59 70 static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
60 71 static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
... ... @@ -68,7 +79,7 @@
68 79 */
69 80  
70 81 static void
71   -kvp_register(void)
  82 +kvp_register(int reg_value)
72 83 {
73 84  
74 85 struct cn_msg *msg;
... ... @@ -83,7 +94,7 @@
83 94 msg->id.idx = CN_KVP_IDX;
84 95 msg->id.val = CN_KVP_VAL;
85 96  
86   - kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER;
  97 + kvp_msg->kvp_hdr.operation = reg_value;
87 98 strcpy(version, HV_DRV_VERSION);
88 99 msg->len = sizeof(struct hv_kvp_msg);
89 100 cn_netlink_send(msg, 0, GFP_ATOMIC);
90 101  
... ... @@ -97,9 +108,43 @@
97 108 * If the timer fires, the user-mode component has not responded;
98 109 * process the pending transaction.
99 110 */
100   - kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
  111 + kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
101 112 }
102 113  
  114 +static int kvp_handle_handshake(struct hv_kvp_msg *msg)
  115 +{
  116 + int ret = 1;
  117 +
  118 + switch (msg->kvp_hdr.operation) {
  119 + case KVP_OP_REGISTER:
  120 + dm_reg_value = KVP_OP_REGISTER;
  121 + pr_info("KVP: IP injection functionality not available\n");
  122 + pr_info("KVP: Upgrade the KVP daemon\n");
  123 + break;
  124 + case KVP_OP_REGISTER1:
  125 + dm_reg_value = KVP_OP_REGISTER1;
  126 + break;
  127 + default:
  128 + pr_info("KVP: incompatible daemon\n");
  129 + pr_info("KVP: KVP version: %d, Daemon version: %d\n",
  130 + KVP_OP_REGISTER1, msg->kvp_hdr.operation);
  131 + ret = 0;
  132 + }
  133 +
  134 + if (ret) {
  135 + /*
  136 + * We have a compatible daemon; complete the handshake.
  137 + */
  138 + pr_info("KVP: user-mode registering done.\n");
  139 + kvp_register(dm_reg_value);
  140 + kvp_transaction.active = false;
  141 + if (kvp_transaction.kvp_context)
  142 + hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
  143 + }
  144 + return ret;
  145 +}
  146 +
  147 +
103 148 /*
104 149 * Callback when data is received from user mode.
105 150 */
106 151  
107 152  
108 153  
109 154  
110 155  
111 156  
... ... @@ -109,27 +154,52 @@
109 154 {
110 155 struct hv_kvp_msg *message;
111 156 struct hv_kvp_msg_enumerate *data;
  157 + int error = 0;
112 158  
113 159 message = (struct hv_kvp_msg *)msg->data;
114   - switch (message->kvp_hdr.operation) {
  160 +
  161 + /*
  162 + * If we are negotiating the version information
  163 + * with the daemon; handle that first.
  164 + */
  165 +
  166 + if (in_hand_shake) {
  167 + if (kvp_handle_handshake(message))
  168 + in_hand_shake = false;
  169 + return;
  170 + }
  171 +
  172 + /*
  173 + * Based on the version of the daemon, we propagate errors from the
  174 + * daemon differently.
  175 + */
  176 +
  177 + data = &message->body.kvp_enum_data;
  178 +
  179 + switch (dm_reg_value) {
115 180 case KVP_OP_REGISTER:
116   - pr_info("KVP: user-mode registering done.\n");
117   - kvp_register();
118   - kvp_transaction.active = false;
119   - hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
  181 + /*
  182 + * Null string is used to pass back error condition.
  183 + */
  184 + if (data->data.key[0] == 0)
  185 + error = HV_S_CONT;
120 186 break;
121 187  
122   - default:
123   - data = &message->body.kvp_enum_data;
  188 + case KVP_OP_REGISTER1:
124 189 /*
125   - * Complete the transaction by forwarding the key value
126   - * to the host. But first, cancel the timeout.
  190 + * We use the message header information from
  191 + * the user level daemon to transmit errors.
127 192 */
128   - if (cancel_delayed_work_sync(&kvp_work))
129   - kvp_respond_to_host(data->data.key,
130   - data->data.value,
131   - !strlen(data->data.key));
  193 + error = message->error;
  194 + break;
132 195 }
  196 +
  197 + /*
  198 + * Complete the transaction by forwarding the key value
  199 + * to the host. But first, cancel the timeout.
  200 + */
  201 + if (cancel_delayed_work_sync(&kvp_work))
  202 + kvp_respond_to_host(data->data.key, data->data.value, error);
133 203 }
134 204  
135 205 static void
... ... @@ -287,6 +357,7 @@
287 357 */
288 358 return;
289 359  
  360 + icmsghdrp->status = error;
290 361  
291 362 /*
292 363 * If the error parameter is set, terminate the host's enumeration
293 364  
294 365  
... ... @@ -294,14 +365,11 @@
294 365 */
295 366 if (error) {
296 367 /*
297   - * Something failed or the we have timedout;
298   - * terminate the current host-side iteration.
  368 + * Something failed or we have timedout;
  369 + * terminate the current host-side iteration.
299 370 */
300   - icmsghdrp->status = HV_S_CONT;
301 371 goto response_done;
302 372 }
303   -
304   - icmsghdrp->status = HV_S_OK;
305 373  
306 374 kvp_msg = (struct hv_kvp_msg *)
307 375 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
include/linux/hyperv.h
... ... @@ -181,6 +181,17 @@
181 181 KVP_POOL_COUNT /* Number of pools, must be last. */
182 182 };
183 183  
  184 +/*
  185 + * Some Hyper-V status codes.
  186 + */
  187 +
  188 +#define HV_S_OK 0x00000000
  189 +#define HV_E_FAIL 0x80004005
  190 +#define HV_S_CONT 0x80070103
  191 +#define HV_ERROR_NOT_SUPPORTED 0x80070032
  192 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7
  193 +#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
  194 +
184 195 #define ADDR_FAMILY_NONE 0x00
185 196 #define ADDR_FAMILY_IPV4 0x01
186 197 #define ADDR_FAMILY_IPV6 0x02
... ... @@ -1048,12 +1059,6 @@
1048 1059 #define ICMSGHDRFLAG_REQUEST 2
1049 1060 #define ICMSGHDRFLAG_RESPONSE 4
1050 1061  
1051   -#define HV_S_OK 0x00000000
1052   -#define HV_E_FAIL 0x80004005
1053   -#define HV_S_CONT 0x80070103
1054   -#define HV_ERROR_NOT_SUPPORTED 0x80070032
1055   -#define HV_ERROR_MACHINE_LOCKED 0x800704F7
1056   -#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
1057 1062  
1058 1063 /*
1059 1064 * While we want to handle util services as regular devices,
tools/hv/hv_kvp_daemon.c
... ... @@ -71,13 +71,14 @@
71 71 static char kvp_send_buffer[4096];
72 72 static char kvp_recv_buffer[4096 * 2];
73 73 static struct sockaddr_nl addr;
  74 +static int in_hand_shake = 1;
74 75  
75 76 static char *os_name = "";
76 77 static char *os_major = "";
77 78 static char *os_minor = "";
78 79 static char *processor_arch;
79 80 static char *os_build;
80   -static char *lic_version;
  81 +static char *lic_version = "Unknown version";
81 82 static struct utsname uts_buf;
82 83  
83 84  
... ... @@ -394,7 +395,7 @@
394 395 return 1;
395 396 }
396 397  
397   -static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
  398 +static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
398 399 __u8 *value, int value_size)
399 400 {
400 401 struct kvp_record *record;
401 402  
... ... @@ -406,16 +407,12 @@
406 407 record = kvp_file_info[pool].records;
407 408  
408 409 if (index >= kvp_file_info[pool].num_records) {
409   - /*
410   - * This is an invalid index; terminate enumeration;
411   - * - a NULL value will do the trick.
412   - */
413   - strcpy(value, "");
414   - return;
  410 + return 1;
415 411 }
416 412  
417 413 memcpy(key, record[index].key, key_size);
418 414 memcpy(value, record[index].value, value_size);
  415 + return 0;
419 416 }
420 417  
421 418  
... ... @@ -646,6 +643,8 @@
646 643 char *p;
647 644 char *key_value;
648 645 char *key_name;
  646 + int op;
  647 + int pool;
649 648  
650 649 daemon(1, 0);
651 650 openlog("KVP", 0, LOG_USER);
... ... @@ -687,7 +686,7 @@
687 686 message->id.val = CN_KVP_VAL;
688 687  
689 688 hv_msg = (struct hv_kvp_msg *)message->data;
690   - hv_msg->kvp_hdr.operation = KVP_OP_REGISTER;
  689 + hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
691 690 message->ack = 0;
692 691 message->len = sizeof(struct hv_kvp_msg);
693 692  
694 693  
... ... @@ -721,12 +720,21 @@
721 720 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
722 721 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
723 722  
724   - switch (hv_msg->kvp_hdr.operation) {
725   - case KVP_OP_REGISTER:
  723 + /*
  724 + * We will use the KVP header information to pass back
  725 + * the error from this daemon. So, first copy the state
  726 + * and set the error code to success.
  727 + */
  728 + op = hv_msg->kvp_hdr.operation;
  729 + pool = hv_msg->kvp_hdr.pool;
  730 + hv_msg->error = HV_S_OK;
  731 +
  732 + if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
726 733 /*
727 734 * Driver is registering with us; stash away the version
728 735 * information.
729 736 */
  737 + in_hand_shake = 0;
730 738 p = (char *)hv_msg->body.kvp_register.version;
731 739 lic_version = malloc(strlen(p) + 1);
732 740 if (lic_version) {
733 741  
734 742  
735 743  
736 744  
737 745  
738 746  
739 747  
740 748  
... ... @@ -737,44 +745,39 @@
737 745 syslog(LOG_ERR, "malloc failed");
738 746 }
739 747 continue;
  748 + }
740 749  
741   - /*
742   - * The current protocol with the kernel component uses a
743   - * NULL key name to pass an error condition.
744   - * For the SET, GET and DELETE operations,
745   - * use the existing protocol to pass back error.
746   - */
747   -
  750 + switch (op) {
748 751 case KVP_OP_SET:
749   - if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
  752 + if (kvp_key_add_or_modify(pool,
750 753 hv_msg->body.kvp_set.data.key,
751 754 hv_msg->body.kvp_set.data.key_size,
752 755 hv_msg->body.kvp_set.data.value,
753 756 hv_msg->body.kvp_set.data.value_size))
754   - strcpy(hv_msg->body.kvp_set.data.key, "");
  757 + hv_msg->error = HV_S_CONT;
755 758 break;
756 759  
757 760 case KVP_OP_GET:
758   - if (kvp_get_value(hv_msg->kvp_hdr.pool,
  761 + if (kvp_get_value(pool,
759 762 hv_msg->body.kvp_set.data.key,
760 763 hv_msg->body.kvp_set.data.key_size,
761 764 hv_msg->body.kvp_set.data.value,
762 765 hv_msg->body.kvp_set.data.value_size))
763   - strcpy(hv_msg->body.kvp_set.data.key, "");
  766 + hv_msg->error = HV_S_CONT;
764 767 break;
765 768  
766 769 case KVP_OP_DELETE:
767   - if (kvp_key_delete(hv_msg->kvp_hdr.pool,
  770 + if (kvp_key_delete(pool,
768 771 hv_msg->body.kvp_delete.key,
769 772 hv_msg->body.kvp_delete.key_size))
770   - strcpy(hv_msg->body.kvp_delete.key, "");
  773 + hv_msg->error = HV_S_CONT;
771 774 break;
772 775  
773 776 default:
774 777 break;
775 778 }
776 779  
777   - if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
  780 + if (op != KVP_OP_ENUMERATE)
778 781 goto kvp_done;
779 782  
780 783 /*
781 784  
... ... @@ -782,13 +785,14 @@
782 785 * both the key and the value; if not read from the
783 786 * appropriate pool.
784 787 */
785   - if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
786   - kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
  788 + if (pool != KVP_POOL_AUTO) {
  789 + if (kvp_pool_enumerate(pool,
787 790 hv_msg->body.kvp_enum_data.index,
788 791 hv_msg->body.kvp_enum_data.data.key,
789 792 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
790 793 hv_msg->body.kvp_enum_data.data.value,
791   - HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
  794 + HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
  795 + hv_msg->error = HV_S_CONT;
792 796 goto kvp_done;
793 797 }
794 798  
... ... @@ -841,11 +845,7 @@
841 845 strcpy(key_name, "ProcessorArchitecture");
842 846 break;
843 847 default:
844   - strcpy(key_value, "Unknown Key");
845   - /*
846   - * We use a null key name to terminate enumeration.
847   - */
848   - strcpy(key_name, "");
  848 + hv_msg->error = HV_S_CONT;
849 849 break;
850 850 }
851 851 /*