FreeBSD/sys/dev/hyperv/utilities/hv_kvp.c
/*
 * Function to read the kvp request buffer from host
 * and interact with daemon
 */
Function to read the kvp request buffer from host
and interact with daemon
Function to read the kvp request buffer from host and interact with daemon
static void
hv_kvp_process_request(void *context, int pending)
{
	uint8_t *kvp_buf;
	hv_vmbus_channel *channel;
	uint32_t recvlen = 0;
	uint64_t requestid;
	struct hv_vmbus_icmsg_hdr *icmsghdrp;
	int ret = 0;
	hv_kvp_sc		*sc;
	hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
	sc = (hv_kvp_sc*)context;
	kvp_buf = sc->util_sc.receive_buffer;
	channel = sc->util_sc.hv_dev->channel;
	ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
		&recvlen, &requestid);
	while ((ret == 0) && (recvlen > 0)) {
		icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
			&kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
		hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
		if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
			hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf);
			hv_kvp_respond_host(sc, ret);
			sc->req_in_progress = false;
			hv_kvp_log_info("%s :version negotiated\n", __func__);
		} else {
			if (!sc->daemon_busy) {
				hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
				mtx_lock(&sc->pending_mutex);
				sc->req_timed_out = false;
				sc->daemon_busy = true;
				mtx_unlock(&sc->pending_mutex);
				hv_kvp_send_msg_to_daemon(sc);
				hv_kvp_log_info("%s: waiting for daemon\n", __func__);
			}
			tsleep(sc, 0, "kvpworkitem", 5 * hz);
			hv_kvp_log_info("%s: came out of wait\n", __func__);
		}
		mtx_lock(&sc->pending_mutex);
		sc->req_timed_out = true;
		if (hv_kvp_req_in_progress(sc)) {
			hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
			hv_kvp_respond_host(sc, HV_KVP_E_FAIL);
			sc->req_in_progress = false;
		}
		mtx_unlock(&sc->pending_mutex);
		recvlen = 0;
		ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
			&recvlen, &requestid);
		hv_kvp_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
			__func__, context, ret, recvlen);
	}
}
static void hv_kvp_process_request ( void * context , int pending ) { uint8_t * kvp_buf ; hv_vmbus_channel * channel ; uint32_t recvlen = 0 ; uint64_t requestid ; struct hv_vmbus_icmsg_hdr * icmsghdrp ; int ret = 0 ; hv_kvp_sc * sc ; hv_kvp_log_info ( " \n " , __func__ ) ; sc = ( hv_kvp_sc * ) context ; kvp_buf = sc -> util_sc . receive_buffer ; channel = sc -> util_sc . hv_dev -> channel ; ret = hv_vmbus_channel_recv_packet ( channel , kvp_buf , 2 * PAGE_SIZE , & recvlen , & requestid ) ; while ( ( ret == 0 ) && ( recvlen > 0 ) ) { icmsghdrp = ( struct hv_vmbus_icmsg_hdr * ) & kvp_buf [ sizeof ( struct hv_vmbus_pipe_hdr ) ] ; hv_kvp_transaction_init ( sc , recvlen , requestid , kvp_buf ) ; if ( icmsghdrp -> icmsgtype == HV_ICMSGTYPE_NEGOTIATE ) { hv_kvp_negotiate_version ( icmsghdrp , NULL , kvp_buf ) ; hv_kvp_respond_host ( sc , ret ) ; sc -> req_in_progress = false ; hv_kvp_log_info ( " \n " , __func__ ) ; } else { if ( ! sc -> daemon_busy ) { hv_kvp_log_info ( " \n " , __func__ ) ; mtx_lock ( & sc -> pending_mutex ) ; sc -> req_timed_out = false ; sc -> daemon_busy = true ; mtx_unlock ( & sc -> pending_mutex ) ; hv_kvp_send_msg_to_daemon ( sc ) ; hv_kvp_log_info ( " \n " , __func__ ) ; } tsleep ( sc , 0 , " " , 5 * hz ) ; hv_kvp_log_info ( " \n " , __func__ ) ; } mtx_lock ( & sc -> pending_mutex ) ; sc -> req_timed_out = true ; if ( hv_kvp_req_in_progress ( sc ) ) { hv_kvp_log_info ( " \n " , __func__ ) ; hv_kvp_respond_host ( sc , HV_KVP_E_FAIL ) ; sc -> req_in_progress = false ; } mtx_unlock ( & sc -> pending_mutex ) ; recvlen = 0 ; ret = hv_vmbus_channel_recv_packet ( channel , kvp_buf , 2 * PAGE_SIZE , & recvlen , & requestid ) ; hv_kvp_log_info ( " \n " , __func__ , context , ret , recvlen ) ; } }
Function to read the kvp request buffer from host
 and interact with daemon
Function to read the kvp request buffer from host and interact with daemon
/*
			 * It is ok to not acquire the mutex before setting
			 * req_in_progress here because negotiation is the
			 * first thing that happens and hence there is no
			 * chance of a race condition.
			 */ /* Wait 5 seconds for daemon to respond back */ /* Notice that once req_timed_out is set to true
		 * it will remain true until the next request is
		 * sent to the daemon. The response from daemon
		 * is forwarded to host only when this flag is
		 * false.
		 */ /*
		 * Cancel request if so need be.
		 */ /*
		 * Try reading next buffer
		 */