mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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>
This commit is contained in:
1 parent
9905ac2b90
commit
51010e4de3
2 files changed
+25
No files matched your search
@@ -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;
|
||||
|
||||
@@ -252,6 +252,11 @@ static inline unsigned long tmh_freeable_mb(void)
|
||||
(20 - PAGE_SHIFT);
|
||||
}
|
||||
|
||||
static inline unsigned long tmh_free_mb(void)
|
||||
{
|
||||
return (tmh_avail_pages() + total_free_pages()) >> (20 - PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory allocation for "infrastructure" data
|
||||
*/
|
||||
|
||||