@@ -307,13 +307,15 @@ static void sgx_reclaim_pages(void)
list_del_init(&epc_page->list);
encl_page = epc_page->owner;
- if (kref_get_unless_zero(&encl_page->encl->refcount) != 0)
+ if (kref_get_unless_zero(&encl_page->encl->refcount) != 0) {
+ epc_page->flags |= SGX_EPC_PAGE_RECLAIM_IN_PROGRESS;
chunk[cnt++] = epc_page;
- else
+ } else {
/* The owner is freeing the page. No need to add the
* page back to the list of reclaimable pages.
*/
epc_page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED;
+ }
}
spin_unlock(&sgx_global_lru.lock);
@@ -339,6 +341,7 @@ static void sgx_reclaim_pages(void)
skip:
spin_lock(&sgx_global_lru.lock);
+ epc_page->flags &= ~SGX_EPC_PAGE_RECLAIM_IN_PROGRESS;
list_add_tail(&epc_page->list, &sgx_global_lru.reclaimable);
spin_unlock(&sgx_global_lru.lock);
@@ -362,7 +365,8 @@ static void sgx_reclaim_pages(void)
sgx_reclaimer_write(epc_page, &backing[i]);
kref_put(&encl_page->encl->refcount, sgx_encl_release);
- epc_page->flags &= ~SGX_EPC_PAGE_RECLAIMER_TRACKED;
+ epc_page->flags &= ~(SGX_EPC_PAGE_RECLAIMER_TRACKED |
+ SGX_EPC_PAGE_RECLAIM_IN_PROGRESS);
sgx_free_epc_page(epc_page);
}
@@ -504,7 +508,7 @@ struct sgx_epc_page *__sgx_alloc_epc_page(void)
void sgx_record_epc_page(struct sgx_epc_page *page, unsigned long flags)
{
spin_lock(&sgx_global_lru.lock);
- WARN_ON(page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED);
+ WARN_ON(page->flags & SGX_EPC_PAGE_RECLAIM_FLAGS);
page->flags |= flags;
if (flags & SGX_EPC_PAGE_RECLAIMER_TRACKED)
list_add_tail(&page->list, &sgx_global_lru.reclaimable);
@@ -528,7 +532,7 @@ int sgx_drop_epc_page(struct sgx_epc_page *page)
spin_lock(&sgx_global_lru.lock);
if (page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED) {
/* The page is being reclaimed. */
- if (list_empty(&page->list)) {
+ if (page->flags & SGX_EPC_PAGE_RECLAIM_IN_PROGRESS) {
spin_unlock(&sgx_global_lru.lock);
return -EBUSY;
}
@@ -29,6 +29,11 @@
/* Pages on free list */
#define SGX_EPC_PAGE_IS_FREE BIT(1)
+/* page flag to indicate reclaim is in progress */
+#define SGX_EPC_PAGE_RECLAIM_IN_PROGRESS BIT(2)
+#define SGX_EPC_PAGE_RECLAIM_FLAGS (SGX_EPC_PAGE_RECLAIMER_TRACKED | \
+ SGX_EPC_PAGE_RECLAIM_IN_PROGRESS)
+
struct sgx_epc_page {
unsigned int section;
u16 flags;