Remove remaining panic()s from server-side code. Also, allow to

send an out-of-band error.  Make the client retry syscall requests
if this error is EAGAIN, fail them otherwise.
This commit is contained in:
pooka 2010-11-29 16:08:03 +00:00
parent 240e9917d0
commit d402686fe2
3 changed files with 96 additions and 35 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpclient.c,v 1.5 2010/11/25 17:59:03 pooka Exp $ */
/* $NetBSD: rumpclient.c,v 1.6 2010/11/29 16:08:03 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -70,15 +70,18 @@ syscall_req(struct spclient *spc, int sysnum,
rhdr.rsp_type = RUMPSP_SYSCALL;
rhdr.rsp_sysnum = sysnum;
putwait(spc, &rw, &rhdr);
rv = dosend(spc, &rhdr, sizeof(rhdr));
rv = dosend(spc, data, dlen);
if (rv) {
unputwait(spc, &rw);
return rv;
}
do {
putwait(spc, &rw, &rhdr);
rv = dosend(spc, &rhdr, sizeof(rhdr));
rv = dosend(spc, data, dlen);
if (rv) {
unputwait(spc, &rw);
return rv;
}
rv = waitresp(spc, &rw);
} while (rv == EAGAIN);
rv = waitresp(spc, &rw);
*resp = rw.rw_data;
return rv;
}
@ -198,9 +201,7 @@ handlereq(struct spclient *spc)
break;
}
free(spc->spc_buf);
spc->spc_off = 0;
spc->spc_buf = NULL;
spcfreebuf(spc);
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: rumpuser_sp.c,v 1.20 2010/11/29 11:40:54 pooka Exp $ */
/* $NetBSD: rumpuser_sp.c,v 1.21 2010/11/29 16:08:03 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: rumpuser_sp.c,v 1.20 2010/11/29 11:40:54 pooka Exp $");
__RCSID("$NetBSD: rumpuser_sp.c,v 1.21 2010/11/29 16:08:03 pooka Exp $");
#include <sys/types.h>
#include <sys/atomic.h>
@ -178,6 +178,22 @@ nextreq(struct spclient *spc)
return nw;
}
static void
send_error_resp(struct spclient *spc, uint64_t reqno, int error)
{
struct rsp_hdr rhdr;
rhdr.rsp_len = sizeof(rhdr);
rhdr.rsp_reqno = reqno;
rhdr.rsp_class = RUMPSP_ERROR;
rhdr.rsp_type = 0;
rhdr.rsp_error = error;
sendlock(spc);
(void)dosend(spc, &rhdr, sizeof(rhdr));
sendunlock(spc);
}
static int
send_syscall_resp(struct spclient *spc, uint64_t reqno, int error,
register_t *retval)
@ -605,21 +621,29 @@ handlereq(struct spclient *spc)
{
struct sysbouncearg *sba;
pthread_t pt;
int retries;
/* XXX: check that it's a syscall */
if (__predict_false(spc->spc_hdr.rsp_type != RUMPSP_SYSCALL)) {
send_error_resp(spc, spc->spc_hdr.rsp_reqno, EINVAL);
spcfreebuf(spc);
return;
}
sba = malloc(sizeof(*sba));
if (sba == NULL) {
/* panic */
abort();
retries = 0;
while ((sba = malloc(sizeof(*sba))) == NULL) {
if (nworker == 0 || retries > 10) {
send_error_resp(spc, spc->spc_hdr.rsp_reqno, EAGAIN);
spcfreebuf(spc);
return;
}
/* slim chance of more memory? */
usleep(10000);
}
sba->sba_spc = spc;
sba->sba_hdr = spc->spc_hdr;
sba->sba_data = spc->spc_buf;
spc->spc_buf = NULL;
spc->spc_off = 0;
spcresetbuf(spc);
spcref(spc);
@ -731,8 +755,10 @@ spserver(void *arg)
handlereq(spc);
break;
default:
printf("PANIC\n");
abort();
send_error_resp(spc,
spc->spc_hdr.rsp_reqno,
ENOENT);
spcfreebuf(spc);
break;
}
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: sp_common.c,v 1.12 2010/11/26 18:51:03 pooka Exp $ */
/* $NetBSD: sp_common.c,v 1.13 2010/11/29 16:08:03 pooka Exp $ */
/*
* Copyright (c) 2010 Antti Kantee. All Rights Reserved.
@ -44,6 +44,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
#include <stdarg.h>
@ -73,7 +74,7 @@ mydprintf(const char *fmt, ...)
* Bah, I hate writing on-off-wire conversions in C
*/
enum { RUMPSP_REQ, RUMPSP_RESP };
enum { RUMPSP_REQ, RUMPSP_RESP, RUMPSP_ERROR };
enum { RUMPSP_SYSCALL,
RUMPSP_COPYIN, RUMPSP_COPYINSTR,
RUMPSP_COPYOUT, RUMPSP_COPYOUTSTR,
@ -88,9 +89,14 @@ struct rsp_hdr {
* We want this structure 64bit-aligned for typecast fun,
* so might as well use the following for something.
*/
uint32_t rsp_sysnum;
union {
uint32_t sysnum;
uint32_t error;
} u;
};
#define HDRSZ sizeof(struct rsp_hdr)
#define rsp_sysnum u.sysnum
#define rsp_error u.error
/*
* Data follows the header. We have two types of structured data.
@ -113,6 +119,7 @@ struct respwait {
uint64_t rw_reqno;
void *rw_data;
size_t rw_dlen;
int rw_error;
pthread_cond_t rw_cv;
@ -153,6 +160,22 @@ typedef int (*connecthook_fn)(int);
static int readframe(struct spclient *);
static void handlereq(struct spclient *);
static __inline void
spcresetbuf(struct spclient *spc)
{
spc->spc_buf = NULL;
spc->spc_off = 0;
}
static __inline void
spcfreebuf(struct spclient *spc)
{
free(spc->spc_buf);
spcresetbuf(spc);
}
static void
sendlockl(struct spclient *spc)
{
@ -266,18 +289,25 @@ kickwaiter(struct spclient *spc)
break;
}
if (rw == NULL) {
printf("PANIC: no waiter\n");
abort();
DPRINTF(("no waiter found, invalid reqno %" PRIu64 "?\n",
spc->spc_hdr.rsp_reqno));
return;
}
DPRINTF(("rump_sp: client %p woke up waiter at %p\n", spc, rw));
rw->rw_data = spc->spc_buf;
rw->rw_dlen = (size_t)(spc->spc_off - HDRSZ);
if (spc->spc_hdr.rsp_class == RUMPSP_ERROR) {
rw->rw_error = spc->spc_hdr.rsp_error;
} else {
rw->rw_error = 0;
}
pthread_cond_signal(&rw->rw_cv);
pthread_mutex_unlock(&spc->spc_mtx);
spc->spc_buf = NULL;
spc->spc_off = 0;
if (rw->rw_error)
spcfreebuf(spc);
else
spcresetbuf(spc);
}
static void
@ -298,7 +328,8 @@ waitresp(struct spclient *spc, struct respwait *rw)
sendunlockl(spc);
while (rw->rw_data == NULL && spc->spc_dying == 0) {
rw->rw_error = 0;
while (rw->rw_data == NULL && rw->rw_error == 0 && spc->spc_dying == 0){
/* are we free to receive? */
if (spc->spc_istatus == SPCSTATUS_FREE) {
int gotresp;
@ -324,6 +355,7 @@ waitresp(struct spclient *spc, struct respwait *rw)
switch (spc->spc_hdr.rsp_class) {
case RUMPSP_RESP:
case RUMPSP_ERROR:
kickwaiter(spc);
gotresp = spc->spc_hdr.rsp_reqno ==
rw->rw_reqno;
@ -352,9 +384,11 @@ waitresp(struct spclient *spc, struct respwait *rw)
pthread_cond_destroy(&rw->rw_cv);
if (rv == 0 && spc->spc_dying)
rv = ENOTCONN;
return rv;
if (rv)
return rv;
if (spc->spc_dying)
return ENOTCONN;
return rw->rw_error;
}
static int