Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/bouyer-xen2]: src/sys/arch/xen Improve ressource shortage recovery: if x...
details: https://anonhg.NetBSD.org/src/rev/7d7fecf9bfc2
branches: bouyer-xen2
changeset: 571904:7d7fecf9bfc2
user: bouyer <bouyer%NetBSD.org@localhost>
date: Tue Mar 08 22:24:10 2005 +0000
description:
Improve ressource shortage recovery: if xen_shm_map() fails, register a
callback wich will retry the I/O when xen_shm_unmap() is called.
diffstat:
sys/arch/xen/i386/xen_shm_machdep.c | 74 ++++++++++++++++++++++++++++++++---
sys/arch/xen/include/xen_shm.h | 8 ++-
sys/arch/xen/xen/xbdback.c | 76 ++++++++++++++++++++++++++----------
sys/arch/xen/xen/xennetback.c | 4 +-
4 files changed, 130 insertions(+), 32 deletions(-)
diffs (truncated from 321 to 300 lines):
diff -r 432a91efaf3d -r 7d7fecf9bfc2 sys/arch/xen/i386/xen_shm_machdep.c
--- a/sys/arch/xen/i386/xen_shm_machdep.c Tue Mar 08 19:33:01 2005 +0000
+++ b/sys/arch/xen/i386/xen_shm_machdep.c Tue Mar 08 22:24:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_shm_machdep.c,v 1.1.2.1 2005/02/16 13:46:29 bouyer Exp $ */
+/* $NetBSD: xen_shm_machdep.c,v 1.1.2.2 2005/03/08 22:24:10 bouyer Exp $ */
/*
* Copyright (c) 2005 Manuel Bouyer.
@@ -54,9 +54,12 @@
* At boot time, we grap some kernel VM space that we'll use to map the foreing
* pages. We also maintain a virtual to machine mapping table to give back
* the appropriate address to bus_dma if requested.
+ * If no more VM space is available, we return an error. The caller can then
+ * register a callback which will be called when the required VM space is
+ * available.
*/
-
+/* pointers to our VM space */
vaddr_t xen_shm_base_address;
u_long xen_shm_base_address_pg;
vaddr_t xen_shm_end_address;
@@ -74,9 +77,29 @@
/* vm space management */
struct extent *xen_shm_ex;
+/* callbacks are registered in a FIFO list. */
+
+SIMPLEQ_HEAD(xen_shm_callback_head, xen_shm_callback_entry) xen_shm_callbacks;
+struct xen_shm_callback_entry {
+ SIMPLEQ_ENTRY(xen_shm_callback_entry) xshmc_entries;
+ int (*xshmc_callback)(void *); /* our callback */
+ void *xshmc_arg; /* cookie passed to the callback */
+};
+/* a pool of struct xen_shm_callback_entry */
+struct pool xen_shm_callback_pool;
+
void
xen_shm_init()
{
+ SIMPLEQ_INIT(&xen_shm_callbacks);
+ pool_init(&xen_shm_callback_pool, sizeof(struct xen_shm_callback_entry),
+ 0, 0, 0, "xshmc", NULL);
+ /* ensure we'll always get items */
+ if (pool_prime(&xen_shm_callback_pool,
+ PAGE_SIZE / sizeof(struct xen_shm_callback_entry)) != 0) {
+ panic("xen_shm_init can't prime pool");
+ }
+
xen_shm_base_address = uvm_km_valloc(kernel_map, xen_shm_size);
xen_shm_end_address = xen_shm_base_address + xen_shm_size;
xen_shm_base_address_pg = xen_shm_base_address >> PAGE_SHIFT;
@@ -93,8 +116,8 @@
memset(_xen_shm_vaddr2ma, -1, sizeof(_xen_shm_vaddr2ma));
}
-vaddr_t
-xen_shm_map(paddr_t *ma, int nentries, int domid)
+int
+xen_shm_map(paddr_t *ma, int nentries, int domid, vaddr_t *vap, int flags)
{
int i;
vaddr_t new_va;
@@ -102,10 +125,19 @@
multicall_entry_t mcl[XENSHM_MAX_PAGES_PER_REQUEST];
int remap_prot = PG_V | PG_RW | PG_U | PG_M;
+ /*
+ * if a driver is waiting for ressources, don't try to allocate
+ * yet. This is to avoid a flood of small requests stalling large
+ * ones.
+ */
+ if (__predict_false(SIMPLEQ_FIRST(&xen_shm_callbacks) != NULL) &&
+ (flags & XSHM_CALLBACK) == 0)
+ return ENOMEM;
/* allocate the needed virtual space */
if (extent_alloc(xen_shm_ex, nentries, 1, 0, EX_NOWAIT, &new_va_pg)
!= 0)
- return 0;
+ return ENOMEM;
+
new_va = new_va_pg << PAGE_SHIFT;
for (i = 0; i < nentries; i++, new_va_pg++) {
mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
@@ -123,10 +155,11 @@
if ((mcl[i].args[5] != 0)) {
printf("xen_shm_map: mcl[%d] failed\n", i);
xen_shm_unmap(new_va, ma, nentries, domid);
- return 0;
+ return EINVAL;
}
}
- return new_va;
+ *vap = new_va;
+ return 0;
}
void
@@ -134,6 +167,7 @@
{
multicall_entry_t mcl[XENSHM_MAX_PAGES_PER_REQUEST];
int i;
+ struct xen_shm_callback_entry *xshmc;
va = va >> PAGE_SHIFT;
for (i = 0; i < nentries; i++) {
@@ -148,8 +182,34 @@
panic("xen_shm_unmap");
if (extent_free(xen_shm_ex, va, nentries, EX_NOWAIT) != 0)
panic("xen_shm_unmap: extent_free");
+ while (__predict_false((xshmc = SIMPLEQ_FIRST(&xen_shm_callbacks))
+ != NULL)) {
+ if (xshmc->xshmc_callback(xshmc->xshmc_arg) == 0) {
+ /* callback succeeded */
+ SIMPLEQ_REMOVE_HEAD(&xen_shm_callbacks, xshmc_entries);
+ pool_put(&xen_shm_callback_pool, xshmc);
+ } else {
+ /* callback failed, probably out of ressources */
+ return;
+ }
+ }
}
+int
+xen_shm_callback(int (*callback)(void *), void *arg)
+{
+ struct xen_shm_callback_entry *xshmc;
+
+ xshmc = pool_get(&xen_shm_callback_pool, PR_NOWAIT);
+ if (xshmc == NULL)
+ return ENOMEM;
+ xshmc->xshmc_arg = arg;
+ xshmc->xshmc_callback = callback;
+ SIMPLEQ_INSERT_TAIL(&xen_shm_callbacks, xshmc, xshmc_entries);
+ return 0;
+}
+
+
/*
* Shared memory pages are managed by drivers, and are not known from
* the pmap. This tests if va is a shared memory page, and if so
diff -r 432a91efaf3d -r 7d7fecf9bfc2 sys/arch/xen/include/xen_shm.h
--- a/sys/arch/xen/include/xen_shm.h Tue Mar 08 19:33:01 2005 +0000
+++ b/sys/arch/xen/include/xen_shm.h Tue Mar 08 22:24:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xen_shm.h,v 1.1.2.1 2005/02/16 13:46:29 bouyer Exp $ */
+/* $NetBSD: xen_shm.h,v 1.1.2.2 2005/03/08 22:24:10 bouyer Exp $ */
/*
* Copyright (c) 2005 Manuel Bouyer.
@@ -36,6 +36,10 @@
* space, do I/O to it, and unmap it.
*/
-vaddr_t xen_shm_map(paddr_t *, int, int);
+int xen_shm_map(paddr_t *, int, int, vaddr_t *, int);
void xen_shm_unmap(vaddr_t, paddr_t *, int, int);
+int xen_shm_callback(int (*)(void *), void *);
int xen_shm_vaddr2ma(vaddr_t, paddr_t *);
+
+/* flags for xen_shm_map() */
+#define XSHM_CALLBACK 0x01 /* called from a callback */
diff -r 432a91efaf3d -r 7d7fecf9bfc2 sys/arch/xen/xen/xbdback.c
--- a/sys/arch/xen/xen/xbdback.c Tue Mar 08 19:33:01 2005 +0000
+++ b/sys/arch/xen/xen/xbdback.c Tue Mar 08 22:24:10 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xbdback.c,v 1.1.2.2 2005/03/08 19:33:01 bouyer Exp $ */
+/* $NetBSD: xbdback.c,v 1.1.2.3 2005/03/08 22:24:10 bouyer Exp $ */
/*
* Copyright (c) 2005 Manuel Bouyer.
@@ -119,6 +119,7 @@
SLIST_ENTRY(xbdback_request) next;
blkif_request_t *rq_req; /* the request itself */
vaddr_t rq_vaddr; /* the virtual address to map the request at */
+ paddr_t rq_ma[BLKIF_MAX_PAGES_PER_REQUEST]; /* machine address to map */
struct xbdback_instance *rq_xbdi; /* our xbd instance */
};
SLIST_HEAD(, xbdback_request) free_xbdback_requests;
@@ -130,6 +131,8 @@
static struct xbd_vbd * vbd_lookup(struct xbdback_instance *, blkif_vdev_t);
static int xbdback_io(struct xbdback_instance *, blkif_request_t *);
+static int xbdback_shm_callback(void *);
+static void xbdback_do_io(struct xbdback_request *);
static void xbdback_iodone(struct buf *);
static int xbdback_probe(struct xbdback_instance *, blkif_request_t *);
static void xbdback_send_reply(struct xbdback_instance *, int , int , int);
@@ -523,7 +526,7 @@
}
switch (error) {
case 0:
- /* reply has already been sent */
+ /* reply has already been sent, or will be */
break;
default:
xbdback_send_reply(xbdi, req->id, req->operation,
@@ -563,11 +566,6 @@
SLIST_REMOVE_HEAD(&free_xbdback_requests, next);
xbd_req->rq_xbdi = xbdi;
- if (xbdback_map_shm(req, xbd_req) < 0) {
- xbd_req->rq_req = NULL;
- SLIST_INSERT_HEAD(&free_xbdback_requests, xbd_req, next);
- return EINVAL;
- }
start_offset =
blkif_first_sect(req->frame_and_sects[0]) * VBD_BSIZE;
@@ -606,20 +604,60 @@
xbd_req->rq_buf.b_vp = vbd->vp;
xbd_req->rq_buf.b_blkno = req->sector_number;
xbd_req->rq_buf.b_bcount = (daddr_t)req_size;
- xbd_req->rq_buf.b_data = (void *)(xbd_req->rq_vaddr + start_offset);
+ xbd_req->rq_buf.b_data = (void *)start_offset;
xbd_req->rq_buf.b_private = xbd_req;
- if ((xbd_req->rq_buf.b_flags & B_READ) == 0)
- xbd_req->rq_buf.b_vp->v_numoutput++;
- XENPRINTF(("xbdback_io domain %d: start reqyest\n", xbdi->domid));
- VOP_STRATEGY(vbd->vp, &xbd_req->rq_buf);
- return 0;
+ switch(xbdback_map_shm(req, xbd_req)) {
+ case 0:
+ xbdback_do_io(xbd_req);
+ return 0;
+ case ENOMEM:
+ if (xen_shm_callback(xbdback_shm_callback, xbd_req) == 0)
+ return 0;
+ error = ENOMEM;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
end:
- xbdback_unmap_shm(xbd_req);
xbd_req->rq_req = NULL;
SLIST_INSERT_HEAD(&free_xbdback_requests, xbd_req, next);
return error;
}
+static int
+xbdback_shm_callback(void *arg)
+{
+ struct xbdback_request *xbd_req = arg;
+
+ switch(xen_shm_map(xbd_req->rq_ma, xbd_req->rq_req->nr_segments,
+ xbd_req->rq_xbdi->domid, &xbd_req->rq_vaddr, XSHM_CALLBACK)) {
+ case ENOMEM:
+ return -1; /* will try again later */
+ case 0:
+ xbdback_do_io(xbd_req);
+ return 0;
+ default:
+ xbdback_send_reply(xbd_req->rq_xbdi, xbd_req->rq_req->id,
+ xbd_req->rq_req->operation, BLKIF_RSP_ERROR);
+ xbd_req->rq_req = NULL;
+ SLIST_INSERT_HEAD(&free_xbdback_requests, xbd_req, next);
+ return 0;
+ }
+}
+
+static void
+xbdback_do_io(struct xbdback_request *xbd_req)
+{
+ xbd_req->rq_buf.b_data =
+ (void *)((vaddr_t)xbd_req->rq_buf.b_data + xbd_req->rq_vaddr);
+ if ((xbd_req->rq_buf.b_flags & B_READ) == 0)
+ xbd_req->rq_buf.b_vp->v_numoutput++;
+ XENPRINTF(("xbdback_io domain %d: start reqyest\n",
+ xbd_req->rq_xbdi->domid));
+ VOP_STRATEGY(xbd_req->rq_buf.b_vp, &xbd_req->rq_buf);
+}
+
static void
xbdback_iodone(struct buf *bp)
{
@@ -717,7 +755,6 @@
static int
xbdback_map_shm(blkif_request_t *req, struct xbdback_request *xbd_req)
{
- paddr_t ma[BLKIF_MAX_PAGES_PER_REQUEST];
int i;
xbd_req->rq_req = req;
@@ -731,13 +768,10 @@
#endif
for (i = 0; i < req->nr_segments; i++) {
- ma[i] = (req->frame_and_sects[i] & ~PAGE_MASK);
+ xbd_req->rq_ma[i] = (req->frame_and_sects[i] & ~PAGE_MASK);
}
- xbd_req->rq_vaddr =
- xen_shm_map(ma, req->nr_segments, xbd_req->rq_xbdi->domid);
- if (xbd_req->rq_vaddr == -1)
- panic("xbdback_map_shm");
- return 0;
+ return xen_shm_map(xbd_req->rq_ma, req->nr_segments,
+ xbd_req->rq_xbdi->domid, &xbd_req->rq_vaddr, 0);
Home |
Main Index |
Thread Index |
Old Index