From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thanos Makatos Subject: [PATCH 7 of 9 RFC v3] blktap3/libblktapctl: Introduce tapdisk message exchange functionality Date: Thu, 24 Jan 2013 12:20:47 +0000 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xensource.com Cc: thanos.makatos@citrix.com List-Id: xen-devel@lists.xenproject.org This patch introduces file conrol/tap-ctl-ipc.c, where the functionality of talking to a tapdisk process is implemented. This file is imported from the existing blktap2 implementation, with most changes coming from blktap2 living in github. --- Changed since v2: * Check for unexpected response in tap_ctl_send_and_receive. * If the message has been served but an error occurred, the error in the message is returned by the function in order to simplify error checking/handling by the caller. diff --git a/tools/blktap2/control/tap-ctl-ipc.c b/tools/blktap3/control/tap-ctl-ipc.c copy from tools/blktap2/control/tap-ctl-ipc.c copy to tools/blktap3/control/tap-ctl-ipc.c --- a/tools/blktap2/control/tap-ctl-ipc.c +++ b/tools/blktap3/control/tap-ctl-ipc.c @@ -30,44 +30,34 @@ #include #include #include +#include #include #include #include #include +#include #include "tap-ctl.h" -#include "blktap2.h" +#include "blktap3.h" int tap_ctl_debug = 0; int -tap_ctl_read_message(int fd, tapdisk_message_t *message, int timeout) +tap_ctl_read_raw(int fd, void *buf, size_t size, struct timeval *timeout) { fd_set readfds; - int ret, len, offset; - struct timeval tv, *t; + size_t offset = 0; + int ret; - t = NULL; - offset = 0; - len = sizeof(tapdisk_message_t); - - if (timeout) { - tv.tv_sec = timeout; - tv.tv_usec = 0; - t = &tv; - } - - memset(message, 0, sizeof(tapdisk_message_t)); - - while (offset < len) { + while (offset < size) { FD_ZERO(&readfds); FD_SET(fd, &readfds); - ret = select(fd + 1, &readfds, NULL, NULL, t); + ret = select(fd + 1, &readfds, NULL, NULL, timeout); if (ret == -1) break; else if (FD_ISSET(fd, &readfds)) { - ret = read(fd, message + offset, len - offset); + ret = read(fd, buf + offset, size - offset); if (ret <= 0) break; offset += ret; @@ -75,34 +65,24 @@ tap_ctl_read_message(int fd, tapdisk_mes break; } - if (offset != len) { - EPRINTF("failure reading message\n"); + if (offset != size) { + EPRINTF("failure reading data %zd/%zd\n", offset, size); return -EIO; } - DBG("received '%s' message (uuid = %u)\n", - tapdisk_message_name(message->type), message->cookie); - return 0; } int -tap_ctl_write_message(int fd, tapdisk_message_t *message, int timeout) +tap_ctl_write_message(int fd, tapdisk_message_t * message, + struct timeval *timeout) { fd_set writefds; int ret, len, offset; - struct timeval tv, *t; - t = NULL; offset = 0; len = sizeof(tapdisk_message_t); - if (timeout) { - tv.tv_sec = timeout; - tv.tv_usec = 0; - t = &tv; - } - DBG("sending '%s' message (uuid = %u)\n", tapdisk_message_name(message->type), message->cookie); @@ -113,7 +93,7 @@ tap_ctl_write_message(int fd, tapdisk_me /* we don't bother reinitializing tv. at worst, it will wait a * bit more time than expected. */ - ret = select(fd + 1, NULL, &writefds, NULL, t); + ret = select(fd + 1, NULL, &writefds, NULL, timeout); if (ret == -1) break; else if (FD_ISSET(fd, &writefds)) { @@ -134,9 +114,15 @@ tap_ctl_write_message(int fd, tapdisk_me } int -tap_ctl_send_and_receive(int sfd, tapdisk_message_t *message, int timeout) +tap_ctl_send_and_receive(const int sfd, tapdisk_message_t * const message, + struct timeval *timeout) { int err; + td_msg_id_t msg_type; + + assert(message); + + msg_type = message->type; err = tap_ctl_write_message(sfd, message, timeout); if (err) { @@ -147,12 +133,29 @@ tap_ctl_send_and_receive(int sfd, tapdis err = tap_ctl_read_message(sfd, message, timeout); if (err) { + /* + * TODO If there are messages for which a response is not required + * and failure to receive a reply is expected, this print is bogus. + */ EPRINTF("failed to receive '%s' message\n", tapdisk_message_name(message->type)); return err; } - return 0; + if (tapdisk_message_is_rsp_paired(msg_type)) { + if (message->type - msg_type != 1) { + err = EINVAL; + EPRINTF("invalid response '%s' to message '%s'\n", + tapdisk_message_name(message->type), + tapdisk_message_name(msg_type)); + } else if (message->u.response.error) { + err = message->u.response.error; + EPRINTF("failed to serve message '%s': %s\n", + tapdisk_message_name(msg_type), strerror(err)); + } + } + + return err; } char * @@ -161,7 +164,7 @@ tap_ctl_socket_name(int id) char *name; if (asprintf(&name, "%s/%s%d", - BLKTAP2_CONTROL_DIR, BLKTAP2_CONTROL_SOCKET, id) == -1) + BLKTAP3_CONTROL_DIR, BLKTAP3_CONTROL_SOCKET, id) == -1) return NULL; return name; @@ -222,7 +225,8 @@ tap_ctl_connect_id(int id, int *sfd) } int -tap_ctl_connect_send_and_receive(int id, tapdisk_message_t *message, int timeout) +tap_ctl_connect_send_and_receive(int id, tapdisk_message_t * message, + struct timeval *timeout) { int err, sfd; @@ -235,3 +239,20 @@ tap_ctl_connect_send_and_receive(int id, close(sfd); return err; } + +int +tap_ctl_read_message(int fd, tapdisk_message_t * message, + struct timeval *timeout) +{ + size_t size = sizeof(tapdisk_message_t); + int err; + + err = tap_ctl_read_raw(fd, message, size, timeout); + if (err) + return err; + + DBG("received '%s' message (uuid = %u)\n", + tapdisk_message_name(message->type), message->cookie); + + return 0; +}