aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/tmem.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-09 10:44:56 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-09 10:44:56 +0000
commit51010e4de3d40cd83549768c2cf10ecdcf6ee4a8 (patch)
treeea18e6921dd14d075e32d4b263cb6a16d674203c /xen/common/tmem.c
parent9905ac2b90a3e7cecd9e7dfe21c252362e7080b2 (diff)
downloadxen-51010e4de3d40cd83549768c2cf10ecdcf6ee4a8.tar.gz
xen-51010e4de3d40cd83549768c2cf10ecdcf6ee4a8.tar.bz2
xen-51010e4de3d40cd83549768c2cf10ecdcf6ee4a8.zip
tmem: reclaim minimal memory proactively
When a single domain is using most/all of tmem memory for ephemeral pages belonging to the same object, e.g. when copying a single huge file larger than ephemeral memory, long lists are traversed looking for a page to evict that doesn't belong to this object (as pages in the object for which a page is currently being inserted are locked and cannot be evicted). This is essentially a livelock. Avoid this by proactively ensuring there is a margin of available memory (1MB) before locks are taken on the object. Signed-off-by: Dan Magenheimer <dan.magenheimer@oracle.com>
Diffstat (limited to 'xen/common/tmem.c')
-rw-r--r--xen/common/tmem.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/xen/common/tmem.c b/xen/common/tmem.c
index af1537d3b5..ab1b3cd8f6 100644
--- a/xen/common/tmem.c
+++ b/xen/common/tmem.c
@@ -1093,6 +1093,24 @@ static unsigned long tmem_relinquish_npages(unsigned long n)
return avail_pages;
}
+/* Under certain conditions (e.g. if each client is putting pages for exactly
+ * one object), once locks are held, freeing up memory may
+ * result in livelocks and very long "put" times, so we try to ensure there
+ * is a minimum amount of memory (1MB) available BEFORE any data structure
+ * locks are held */
+static inline void tmem_ensure_avail_pages(void)
+{
+ int failed_evict = 10;
+
+ while ( !tmh_free_mb() )
+ {
+ if ( tmem_evict() )
+ continue;
+ else if ( failed_evict-- <= 0 )
+ break;
+ }
+}
+
/************ TMEM CORE OPERATIONS ************************************/
static NOINLINE int do_tmem_put_compress(pgp_t *pgp, tmem_cli_mfn_t cmfn,
@@ -2315,10 +2333,12 @@ EXPORT long do_tmem_op(tmem_cli_op_t uops)
op.u.new.uuid[0], op.u.new.uuid[1]);
break;
case TMEM_NEW_PAGE:
+ tmem_ensure_avail_pages();
rc = do_tmem_put(pool, op.u.gen.object,
op.u.gen.index, op.u.gen.cmfn, 0, 0, 0, NULL);
break;
case TMEM_PUT_PAGE:
+ tmem_ensure_avail_pages();
rc = do_tmem_put(pool, op.u.gen.object,
op.u.gen.index, op.u.gen.cmfn, 0, 0, PAGE_SIZE, NULL);
if (rc == 1) succ_put = 1;