aboutsummaryrefslogtreecommitdiffstats
path: root/tools/fs-back
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-07-08 10:58:09 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-07-08 10:58:09 +0100
commit6d821524b14a20133b955f711e28e45d92c3725f (patch)
tree9c0415b2396dc5ba1a859c2a35db06521128923b /tools/fs-back
parentf96f790bc4438a9b174f31972fa16fbc78b5e03c (diff)
downloadxen-6d821524b14a20133b955f711e28e45d92c3725f.tar.gz
xen-6d821524b14a20133b955f711e28e45d92c3725f.tar.bz2
xen-6d821524b14a20133b955f711e28e45d92c3725f.zip
fs-back: better error handling in fs-backend
Currently most of the error checking in fs-backend is done by the use of asserts that would terminate the daemon in case of a single error on a single request. This patch replaces the asserts with debugging messages and terminates the connection on which the error occurred. With this patch applied I was able to complete successfully over 1000 live migrations with stubdoms. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'tools/fs-back')
-rw-r--r--tools/fs-back/fs-backend.c67
-rw-r--r--tools/fs-back/fs-backend.h11
-rw-r--r--tools/fs-back/fs-ops.c67
-rw-r--r--tools/fs-back/fs-xenbus.c43
4 files changed, 138 insertions, 50 deletions
diff --git a/tools/fs-back/fs-backend.c b/tools/fs-back/fs-backend.c
index 3b68d7658e..648b63b471 100644
--- a/tools/fs-back/fs-backend.c
+++ b/tools/fs-back/fs-backend.c
@@ -144,7 +144,8 @@ moretodo:
xc_evtchn_notify(mount->evth, mount->local_evtchn);
}
-static void terminate_mount_request(struct fs_mount *mount) {
+void terminate_mount_request(struct fs_mount *mount)
+{
int count = 0, i;
FS_DEBUG("terminate_mount_request %s\n", mount->frontend);
@@ -158,7 +159,13 @@ static void terminate_mount_request(struct fs_mount *mount) {
}
mount->nr_entries = count;
- while (!xenbus_frontend_state_changed(mount, STATE_CLOSING));
+ /* wait for the frontend to shut down but don't wait more than 3
+ * seconds */
+ i = 0;
+ while (!xenbus_frontend_state_changed(mount, STATE_CLOSING) && i < 3) {
+ sleep(1);
+ i++;
+ }
xenbus_write_backend_state(mount, STATE_CLOSED);
xc_gnttab_munmap(mount->gnth, mount->ring.sring, mount->shared_ring_size);
@@ -183,7 +190,7 @@ static void handle_connection(int frontend_dom_id, int export_id, char *frontend
{
struct fs_mount *mount;
struct fs_export *export;
- struct fsif_sring *sring;
+ struct fsif_sring *sring = NULL;
uint32_t dom_ids[MAX_RING_SIZE];
int i;
@@ -204,24 +211,38 @@ static void handle_connection(int frontend_dom_id, int export_id, char *frontend
}
mount = (struct fs_mount*)malloc(sizeof(struct fs_mount));
+ memset(mount, 0, sizeof(struct fs_mount));
mount->dom_id = frontend_dom_id;
mount->export = export;
mount->mount_id = mount_id++;
- xenbus_read_mount_request(mount, frontend);
+ if (xenbus_read_mount_request(mount, frontend) < 0)
+ goto error;
FS_DEBUG("Frontend found at: %s (gref=%d, evtchn=%d)\n",
mount->frontend, mount->grefs[0], mount->remote_evtchn);
- xenbus_write_backend_node(mount);
+ if (!xenbus_write_backend_node(mount)) {
+ FS_DEBUG("ERROR: failed to write backend node on xenbus\n");
+ goto error;
+ }
mount->evth = -1;
mount->evth = xc_evtchn_open();
- assert(mount->evth != -1);
+ if (mount->evth < 0) {
+ FS_DEBUG("ERROR: Couldn't open evtchn!\n");
+ goto error;
+ }
mount->local_evtchn = -1;
mount->local_evtchn = xc_evtchn_bind_interdomain(mount->evth,
mount->dom_id,
mount->remote_evtchn);
- assert(mount->local_evtchn != -1);
+ if (mount->local_evtchn < 0) {
+ FS_DEBUG("ERROR: Couldn't bind evtchn!\n");
+ goto error;
+ }
mount->gnth = -1;
mount->gnth = xc_gnttab_open();
- assert(mount->gnth != -1);
+ if (mount->gnth < 0) {
+ FS_DEBUG("ERROR: Couldn't open gnttab!\n");
+ goto error;
+ }
for(i=0; i<mount->shared_ring_size; i++)
dom_ids[i] = mount->dom_id;
sring = xc_gnttab_map_grant_refs(mount->gnth,
@@ -230,16 +251,40 @@ static void handle_connection(int frontend_dom_id, int export_id, char *frontend
mount->grefs,
PROT_READ | PROT_WRITE);
+ if (!sring) {
+ FS_DEBUG("ERROR: Couldn't amp grant refs!\n");
+ goto error;
+ }
+
BACK_RING_INIT(&mount->ring, sring, mount->shared_ring_size * XC_PAGE_SIZE);
mount->nr_entries = mount->ring.nr_ents;
for (i = 0; i < MAX_FDS; i++)
mount->fds[i] = -1;
LIST_INSERT_HEAD(&mount_requests_head, mount, entries);
- xenbus_watch_frontend_state(mount);
- xenbus_write_backend_state(mount, STATE_READY);
-
+ if (!xenbus_watch_frontend_state(mount)) {
+ FS_DEBUG("ERROR: failed to watch frontend state on xenbus\n");
+ goto error;
+ }
+ if (!xenbus_write_backend_state(mount, STATE_READY)) {
+ FS_DEBUG("ERROR: failed to write backend state to xenbus\n");
+ goto error;
+ }
+
allocate_request_array(mount);
+
+ return;
+
+error:
+ xenbus_write_backend_state(mount, STATE_CLOSED);
+ if (sring)
+ xc_gnttab_munmap(mount->gnth, mount->ring.sring, mount->shared_ring_size);
+ if (mount->gnth > 0)
+ xc_gnttab_close(mount->gnth);
+ if (mount->local_evtchn > 0)
+ xc_evtchn_unbind(mount->evth, mount->local_evtchn);
+ if (mount->evth > 0)
+ xc_evtchn_close(mount->evth);
}
static void await_connections(void)
diff --git a/tools/fs-back/fs-backend.h b/tools/fs-back/fs-backend.h
index 504569027e..9399841a57 100644
--- a/tools/fs-back/fs-backend.h
+++ b/tools/fs-back/fs-backend.h
@@ -56,6 +56,7 @@ struct fs_mount
LIST_ENTRY(fs_mount) entries;
};
+void terminate_mount_request(struct fs_mount *mount);
/* Handle to XenStore driver */
extern struct xs_handle *xsh;
@@ -63,12 +64,12 @@ extern struct xs_handle *xsh;
bool xenbus_create_request_node(void);
int xenbus_register_export(struct fs_export *export);
int xenbus_get_watch_fd(void);
-void xenbus_read_mount_request(struct fs_mount *mount, char *frontend);
-void xenbus_write_backend_node(struct fs_mount *mount);
-void xenbus_write_backend_state(struct fs_mount *mount, const char *state);
+int xenbus_read_mount_request(struct fs_mount *mount, char *frontend);
+bool xenbus_write_backend_node(struct fs_mount *mount);
+bool xenbus_write_backend_state(struct fs_mount *mount, const char *state);
int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate);
-void xenbus_watch_frontend_state(struct fs_mount *mount);
-void xenbus_unwatch_frontend_state(struct fs_mount *mount);
+bool xenbus_watch_frontend_state(struct fs_mount *mount);
+bool xenbus_unwatch_frontend_state(struct fs_mount *mount);
char* xenbus_read_frontend_state(struct fs_mount *mount);
/* File operations, implemented in fs-ops.c */
diff --git a/tools/fs-back/fs-ops.c b/tools/fs-back/fs-ops.c
index 420b217b2f..2dc9ba6125 100644
--- a/tools/fs-back/fs-ops.c
+++ b/tools/fs-back/fs-ops.c
@@ -99,7 +99,10 @@ static void dispatch_file_open(struct fs_mount *mount, struct fsif_request *req)
}
}
out:
- assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+ if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
mount->ring.req_cons++;
@@ -187,7 +190,11 @@ static void dispatch_file_read(struct fs_mount *mount, struct fsif_request *req)
priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
- assert(aio_read(&priv_req->aiocb) >= 0);
+ if (aio_read(&priv_req->aiocb) < 0) {
+ FS_DEBUG("ERROR: aio_read failed errno=%d\n", errno);
+ xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
@@ -201,9 +208,10 @@ static void end_file_read(struct fs_mount *mount, struct fs_request *priv_req)
uint16_t req_id;
/* Release the grant */
- assert(xc_gnttab_munmap(mount->gnth,
- priv_req->page,
- priv_req->count) == 0);
+ if (xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* Get a response from the ring */
rsp_idx = mount->ring.rsp_prod_pvt++;
@@ -257,7 +265,11 @@ static void dispatch_file_write(struct fs_mount *mount, struct fsif_request *req
priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
- assert(aio_write(&priv_req->aiocb) >= 0);
+ if (aio_write(&priv_req->aiocb) < 0) {
+ FS_DEBUG("ERROR: aio_write failed errno=%d\n", errno);
+ xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
@@ -272,9 +284,10 @@ static void end_file_write(struct fs_mount *mount, struct fs_request *priv_req)
uint16_t req_id;
/* Release the grant */
- assert(xc_gnttab_munmap(mount->gnth,
- priv_req->page,
- priv_req->count) == 0);
+ if (xc_gnttab_munmap(mount->gnth, priv_req->page, priv_req->count) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* Get a response from the ring */
rsp_idx = mount->ring.rsp_prod_pvt++;
@@ -392,7 +405,10 @@ static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req)
ret = remove(file_name);
}
FS_DEBUG("Got ret: %d\n", ret);
- assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+ if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
mount->ring.req_cons++;
@@ -435,7 +451,10 @@ static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req)
ret = rename(old_file_name, new_file_name);
}
FS_DEBUG("Got ret: %d\n", ret);
- assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0);
+ if (xc_gnttab_munmap(mount->gnth, buf, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
mount->ring.req_cons++;
@@ -500,7 +519,10 @@ static void dispatch_create(struct fs_mount *mount, struct fsif_request *req)
}
}
out:
- assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+ if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
FS_DEBUG("Got ret %d (errno=%d)\n", ret, errno);
/* Get a response from the ring */
@@ -556,7 +578,8 @@ static void dispatch_list(struct fs_mount *mount, struct fsif_request *req)
/* If there was any error with reading the directory, errno will be set */
error_code = errno;
/* Copy file names of the remaining non-NULL dirents into buf */
- assert(NAME_MAX < XC_PAGE_SIZE >> 1);
+ if (NAME_MAX >= XC_PAGE_SIZE >> 1)
+ goto error_out;
while(dirent != NULL &&
(XC_PAGE_SIZE - ((unsigned long)buf & XC_PAGE_MASK) > NAME_MAX))
{
@@ -572,8 +595,11 @@ error_out:
ret_val = ((nr_files << NR_FILES_SHIFT) & NR_FILES_MASK) |
((error_code << ERROR_SHIFT) & ERROR_MASK) |
(dirent != NULL ? HAS_MORE_FLAG : 0);
- assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
-
+ if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
+
/* Get a response from the ring */
rsp_idx = mount->ring.rsp_prod_pvt++;
FS_DEBUG("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id);
@@ -640,7 +666,10 @@ static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req)
if(ret >= 0)
ret = stat.f_bsize * stat.f_bfree;
- assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0);
+ if (xc_gnttab_munmap(mount->gnth, file_name, 1) != 0) {
+ FS_DEBUG("ERROR: xc_gnttab_munmap failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
mount->ring.req_cons++;
@@ -680,9 +709,11 @@ static void dispatch_file_sync(struct fs_mount *mount, struct fsif_request *req)
priv_req->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
priv_req->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
priv_req->aiocb.aio_sigevent.sigev_value.sival_ptr = priv_req;
- assert(aio_fsync(O_SYNC, &priv_req->aiocb) >= 0);
+ if (aio_fsync(O_SYNC, &priv_req->aiocb) < 0) {
+ FS_DEBUG("ERROR: aio_fsync failed errno=%d\n", errno);
+ terminate_mount_request(mount);
+ }
-
/* We can advance the request consumer index, from here on, the request
* should not be used (it may be overrinden by a response) */
mount->ring.req_cons++;
diff --git a/tools/fs-back/fs-xenbus.c b/tools/fs-back/fs-xenbus.c
index cc47dbcfd6..603bfb9ef4 100644
--- a/tools/fs-back/fs-xenbus.c
+++ b/tools/fs-back/fs-xenbus.c
@@ -107,11 +107,15 @@ int xenbus_get_watch_fd(void)
int res;
assert(xsh != NULL);
res = xs_watch(xsh, WATCH_NODE, "conn-watch");
- assert(res);
+ if (!res) {
+ FS_DEBUG("ERROR: xs_watch %s failed ret=%d errno=%d\n",
+ WATCH_NODE, res, errno);
+ return -1;
+ }
return xs_fileno(xsh);
}
-void xenbus_read_mount_request(struct fs_mount *mount, char *frontend)
+int xenbus_read_mount_request(struct fs_mount *mount, char *frontend)
{
char node[1024];
char *s;
@@ -126,12 +130,18 @@ void xenbus_read_mount_request(struct fs_mount *mount, char *frontend)
mount->frontend = frontend;
snprintf(node, sizeof(node), "%s/state", frontend);
s = xs_read(xsh, XBT_NULL, node, NULL);
- assert(strcmp(s, STATE_READY) == 0);
+ if (strcmp(s, STATE_READY) != 0) {
+ FS_DEBUG("ERROR: frontend not read\n");
+ goto error;
+ }
free(s);
snprintf(node, sizeof(node), "%s/ring-size", frontend);
s = xs_read(xsh, XBT_NULL, node, NULL);
mount->shared_ring_size = atoi(s);
- assert(mount->shared_ring_size <= MAX_RING_SIZE);
+ if (mount->shared_ring_size > MAX_RING_SIZE) {
+ FS_DEBUG("ERROR: shared_ring_size (%d) > MAX_RING_SIZE\n", mount->shared_ring_size);
+ goto error;
+ }
free(s);
for(i=0; i<mount->shared_ring_size; i++)
{
@@ -144,6 +154,11 @@ void xenbus_read_mount_request(struct fs_mount *mount, char *frontend)
s = xs_read(xsh, XBT_NULL, node, NULL);
mount->remote_evtchn = atoi(s);
free(s);
+ return 0;
+
+error:
+ free(s);
+ return -1;
}
/* Small utility function to figure out our domain id */
@@ -161,7 +176,7 @@ static int get_self_id(void)
}
-void xenbus_write_backend_node(struct fs_mount *mount)
+bool xenbus_write_backend_node(struct fs_mount *mount)
{
char node[1024], backend_node[1024];
int self_id;
@@ -175,10 +190,10 @@ void xenbus_write_backend_node(struct fs_mount *mount)
xs_write(xsh, XBT_NULL, node, backend_node, strlen(backend_node));
snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
- xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
+ return xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED));
}
-void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
+bool xenbus_write_backend_state(struct fs_mount *mount, const char *state)
{
char node[1024];
int self_id;
@@ -186,29 +201,25 @@ void xenbus_write_backend_state(struct fs_mount *mount, const char *state)
assert(xsh != NULL);
self_id = get_self_id();
snprintf(node, sizeof(node), ROOT_NODE"/%d/state", mount->mount_id);
- xs_write(xsh, XBT_NULL, node, state, strlen(state));
+ return xs_write(xsh, XBT_NULL, node, state, strlen(state));
}
-void xenbus_watch_frontend_state(struct fs_mount *mount)
+bool xenbus_watch_frontend_state(struct fs_mount *mount)
{
- int res;
char statepath[1024];
assert(xsh != NULL);
snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
- res = xs_watch(xsh, statepath, "frontend-state");
- assert(res);
+ return xs_watch(xsh, statepath, "frontend-state");
}
-void xenbus_unwatch_frontend_state(struct fs_mount *mount)
+bool xenbus_unwatch_frontend_state(struct fs_mount *mount)
{
- int res;
char statepath[1024];
assert(xsh != NULL);
snprintf(statepath, sizeof(statepath), "%s/state", mount->frontend);
- res = xs_unwatch(xsh, statepath, "frontend-state");
- assert(res);
+ return xs_unwatch(xsh, statepath, "frontend-state");
}
int xenbus_frontend_state_changed(struct fs_mount *mount, const char *oldstate)