static int kvp_on_msg(void *msg, int len) { struct hv_kvp_msg *message = (struct hv_kvp_msg *)msg; struct hv_kvp_msg_enumerate *data; int error = 0; if (len < sizeof(*message)) return -EINVAL; /* * If we are negotiating the version information * with the daemon; handle that first. */ if (kvp_transaction.state < HVUTIL_READY) { return kvp_handle_handshake(message); } /* We didn't send anything to userspace so the reply is spurious */ if (kvp_transaction.state < HVUTIL_USERSPACE_REQ) return -EINVAL; kvp_transaction.state = HVUTIL_USERSPACE_RECV; /* * Based on the version of the daemon, we propagate errors from the * daemon differently. */ data = &message->body.kvp_enum_data; switch (dm_reg_value) { case KVP_OP_REGISTER: /* * Null string is used to pass back error condition. */ if (data->data.key[0] == 0) error = HV_S_CONT; break; case KVP_OP_REGISTER1: /* * We use the message header information from * the user level daemon to transmit errors. */ error = message->error; break; } /* * Complete the transaction by forwarding the key value * to the host. But first, cancel the timeout. */ if (cancel_delayed_work_sync(&kvp_timeout_work)) { kvp_respond_to_host(message, error); hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper); } return 0; }
static void kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) { struct hv_kvp_msg *message; struct hv_kvp_msg_enumerate *data; int error = 0; message = (struct hv_kvp_msg *)msg->data; /* * If we are negotiating the version information * with the daemon; handle that first. */ if (in_hand_shake) { if (kvp_handle_handshake(message)) in_hand_shake = false; return; } /* * Based on the version of the daemon, we propagate errors from the * daemon differently. */ data = &message->body.kvp_enum_data; switch (dm_reg_value) { case KVP_OP_REGISTER: /* * Null string is used to pass back error condition. */ if (data->data.key[0] == 0) error = HV_S_CONT; break; case KVP_OP_REGISTER1: /* * We use the message header information from * the user level daemon to transmit errors. */ error = message->error; break; } /* * Complete the transaction by forwarding the key value * to the host. But first, cancel the timeout. */ if (cancel_delayed_work_sync(&kvp_work)) kvp_respond_to_host(message, error); }