dm: support VMs communication with virtio-console
Add feature that client uos can still connect to server uos after rebooting. Tracked-On: #3459 Signed-off-by: Gao Junhao <junhao.gao@intel.com> Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
18ecdc123a
commit
ff299d5c50
|
@ -109,7 +109,9 @@ struct virtio_console_port {
|
|||
struct virtio_console_backend {
|
||||
struct virtio_console_port *port;
|
||||
struct mevent *evp;
|
||||
struct mevent *conn_evp;
|
||||
int fd;
|
||||
int server_fd;
|
||||
bool open;
|
||||
enum virtio_console_be_type be_type;
|
||||
int pts_fd; /* only valid for PTY */
|
||||
|
@ -428,6 +430,19 @@ virtio_console_reset_backend(struct virtio_console_backend *be)
|
|||
be->open = false;
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_console_socket_clear(struct virtio_console_backend *be)
|
||||
{
|
||||
if (be->conn_evp) {
|
||||
mevent_delete(be->conn_evp);
|
||||
be->conn_evp = NULL;
|
||||
}
|
||||
if (be->fd != -1) {
|
||||
close(be->fd);
|
||||
be->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
virtio_console_backend_read(int fd __attribute__((unused)),
|
||||
enum ev_type t __attribute__((unused)),
|
||||
|
@ -470,6 +485,11 @@ virtio_console_backend_read(int fd __attribute__((unused)),
|
|||
if (len == -1 && errno == EAGAIN)
|
||||
return;
|
||||
|
||||
/* when client uos reboot or shutdown,
|
||||
* be->fd will be closed, then the return
|
||||
* value of readv function will be 0 */
|
||||
if (len == 0 || errno == ECONNRESET)
|
||||
goto clear;
|
||||
/* any other errors */
|
||||
goto close;
|
||||
}
|
||||
|
@ -478,11 +498,22 @@ virtio_console_backend_read(int fd __attribute__((unused)),
|
|||
} while (vq_has_descs(vq));
|
||||
|
||||
vq_endchains(vq, 1);
|
||||
return;
|
||||
|
||||
close:
|
||||
virtio_console_reset_backend(be);
|
||||
WPRINTF(("vtcon: be read failed and close! len = %d, errno = %d\n",
|
||||
len, errno));
|
||||
clear:
|
||||
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||
|| !strcmp(be->socket_type,"server"))) {
|
||||
virtio_console_socket_clear(be);
|
||||
} else if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET
|
||||
&& !strcmp(be->socket_type,"client")) {
|
||||
virtio_console_reset_backend(be);
|
||||
WPRINTF(("vtcon: be read failed and close! len = %d, errno = %d\n",
|
||||
len, errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -517,6 +548,13 @@ virtio_console_backend_write(struct virtio_console_port *port, void *arg,
|
|||
if (ret == -1 && (errno == EAGAIN || errno == ENOTCONN))
|
||||
return;
|
||||
|
||||
if (ret == -1 && errno == EBADF) {
|
||||
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||
|| !strcmp(be->socket_type,"server"))) {
|
||||
virtio_console_socket_clear(be);
|
||||
return;
|
||||
}
|
||||
}
|
||||
virtio_console_reset_backend(be);
|
||||
WPRINTF(("vtcon: be write failed! errno = %d\n", errno));
|
||||
}
|
||||
|
@ -617,7 +655,6 @@ virtio_console_accept_new_connection(int fd __attribute__((unused)),
|
|||
{
|
||||
|
||||
int accepted_fd;
|
||||
int close_true;
|
||||
uint32_t len;
|
||||
struct sockaddr_un addr;
|
||||
struct virtio_console_backend *be = arg;
|
||||
|
@ -628,30 +665,18 @@ virtio_console_accept_new_connection(int fd __attribute__((unused)),
|
|||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||
|
||||
len = sizeof(addr);
|
||||
accepted_fd = accept(be->fd, (struct sockaddr *)&addr, &len);
|
||||
/* be->server_fd is kept for client uos reconnect again */
|
||||
accepted_fd = accept(be->server_fd, (struct sockaddr *)&addr, &len);
|
||||
if (accepted_fd == -1) {
|
||||
WPRINTF(("accept error= %d, addr.sun_path=%s\n", errno, addr.sun_path));
|
||||
return;
|
||||
} else {
|
||||
/* close the fd associated with listening socket
|
||||
* and reuse it for accepted socket.
|
||||
*/
|
||||
close_true = 1;
|
||||
setsockopt(be->fd, SOL_SOCKET, SO_REUSEADDR, &close_true, sizeof(int));
|
||||
close(be->fd);
|
||||
be->fd = accepted_fd;
|
||||
}
|
||||
|
||||
if (be->evp) {
|
||||
/* close the event associated with listening socket
|
||||
* and reuse it for accepted socket.
|
||||
*/
|
||||
mevent_delete(be->evp);
|
||||
}
|
||||
|
||||
be->evp = mevent_add(be->fd, EVF_READ, virtio_console_backend_read, be,
|
||||
virtio_console_teardown_backend, be);
|
||||
if (be->evp == NULL) {
|
||||
be->conn_evp = mevent_add(be->fd, EVF_READ, virtio_console_backend_read, be,
|
||||
NULL, NULL);
|
||||
if (be->conn_evp == NULL) {
|
||||
WPRINTF(("accepted fd mevent_add failed\n"));
|
||||
return;
|
||||
}
|
||||
|
@ -745,21 +770,11 @@ virtio_console_config_backend(struct virtio_console_backend *be)
|
|||
WPRINTF(("Backend config: fcntl Error\n"));
|
||||
return -1;
|
||||
}
|
||||
be->evp = mevent_add(fd, EVF_READ, virtio_console_accept_new_connection, be, NULL, NULL);
|
||||
if (be->evp == NULL) {
|
||||
WPRINTF(("Socket Accept mevent_add failed\n"));
|
||||
return -1;
|
||||
}
|
||||
} else if (!strcmp(be->socket_type,"client")) {
|
||||
if (access(be->portpath,0)) {
|
||||
WPRINTF(("%s not exist\n", be->portpath));
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* When the VM reset, client will not able to connect to server.
|
||||
* But here only show some warning.
|
||||
* TODO: implement re-connect function
|
||||
*/
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
WPRINTF(("vtcon: connect error[%d] \n", errno));
|
||||
} else {
|
||||
|
@ -866,6 +881,7 @@ virtio_console_add_backend(struct virtio_console *console, char *opt)
|
|||
}
|
||||
|
||||
be->fd = fd;
|
||||
be->server_fd = fd;
|
||||
be->be_type = be_type;
|
||||
be->portpath = portpath;
|
||||
be->socket_type = socket_type;
|
||||
|
@ -885,17 +901,24 @@ virtio_console_add_backend(struct virtio_console *console, char *opt)
|
|||
}
|
||||
|
||||
if (virtio_console_backend_can_read(be_type)) {
|
||||
if (isatty(fd)) {
|
||||
if (be->be_type == VIRTIO_CONSOLE_BE_SOCKET && (be->socket_type == NULL
|
||||
|| !strcmp(be->socket_type,"server"))) {
|
||||
be->evp = mevent_add(fd, EVF_READ,
|
||||
virtio_console_accept_new_connection, be,
|
||||
virtio_console_teardown_backend, be);
|
||||
}
|
||||
else if (isatty(fd) || (be->be_type == VIRTIO_CONSOLE_BE_SOCKET
|
||||
&& !strcmp(be->socket_type,"client"))) {
|
||||
be->evp = mevent_add(fd, EVF_READ,
|
||||
virtio_console_backend_read, be,
|
||||
virtio_console_teardown_backend, be);
|
||||
if (be->evp == NULL) {
|
||||
WPRINTF(("vtcon: mevent_add failed\n"));
|
||||
error = -1;
|
||||
goto out;
|
||||
}
|
||||
console->ref_count++;
|
||||
}
|
||||
if (be->evp == NULL) {
|
||||
WPRINTF(("vtcon: mevent_add failed\n"));
|
||||
error = -1;
|
||||
goto out;
|
||||
}
|
||||
console->ref_count++;
|
||||
}
|
||||
|
||||
virtio_console_open_port(be->port, true);
|
||||
|
@ -952,6 +975,15 @@ virtio_console_close_backend(struct virtio_console_backend *be)
|
|||
case VIRTIO_CONSOLE_BE_STDIO:
|
||||
virtio_console_restore_stdio();
|
||||
break;
|
||||
case VIRTIO_CONSOLE_BE_SOCKET:
|
||||
if (be->socket_type == NULL || !strcmp(be->socket_type,"server")) {
|
||||
virtio_console_socket_clear(be);
|
||||
if (be->server_fd > 0) {
|
||||
close(be->server_fd);
|
||||
be->server_fd = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue