Hi Jarkko,
On 9/1/2022 2:53 PM, Jarkko Sakkinen wrote:
On Wed, Aug 31, 2022 at 01:39:53PM -0700, Reinette Chatre wrote:
On 8/31/2022 10:38 AM, Jarkko Sakkinen wrote:
I think I am missing something here. A lot of logic is added here but I do not see why it is necessary. ksgxd() knows via kthread_should_stop() if the reclaimer was canceled. I am thus wondering, could the above not be simplified to something similar to V1:
@@ -388,6 +393,8 @@ void sgx_reclaim_direct(void) static int ksgxd(void *p) {
- unsigned long left_dirty;
- set_freezable();
/* @@ -395,10 +402,10 @@ static int ksgxd(void *p) * required for SECS pages, whose child pages blocked EREMOVE. */ __sgx_sanitize_pages(&sgx_dirty_page_list);
IMHO, would make sense also to have here:
if (!kthread_should_stop()) return 0;
Would this not prematurely stop the thread when it should not be?
- __sgx_sanitize_pages(&sgx_dirty_page_list);
- /* sanity check: */
- WARN_ON(!list_empty(&sgx_dirty_page_list));
- left_dirty = __sgx_sanitize_pages(&sgx_dirty_page_list);
- if (left_dirty && !kthread_should_stop())
pr_err("%lu unsanitized pages\n", left_dirty);
That would be incorrect, if the function returned because of kthread stopped.
I should have highlighted this but in my example I changed left_dirty to be "unsigned long" with the intention that the "return -ECANCELED" is replaced with "return 0".
__sgx_sanitize_pages() returns 0 when it exits because of kthread stopped.
To elaborate I was thinking about:
+static unsigned long __sgx_sanitize_pages(struct list_head *dirty_page_list) { + unsigned long left_dirty = 0; struct sgx_epc_page *page; LIST_HEAD(dirty); int ret;
- /* dirty_page_list is thread-local, no need for a lock: */ while (!list_empty(dirty_page_list)) { if (kthread_should_stop()) - return; + return 0;
page = list_first_entry(dirty_page_list, struct sgx_epc_page, list);
@@ -92,12 +95,14 @@ static void __sgx_sanitize_pages(struct list_head *dirty_page_list) } else { /* The page is not yet clean - move to the dirty list. */ list_move_tail(&page->list, &dirty); + left_dirty++; }
cond_resched(); }
list_splice(&dirty, dirty_page_list); + return left_dirty; }
and then with what I had in previous email the checks should work:
@@ -388,6 +393,8 @@ void sgx_reclaim_direct(void)
static int ksgxd(void *p) { + unsigned long left_dirty; + set_freezable();
/* @@ -395,10 +402,10 @@ static int ksgxd(void *p) * required for SECS pages, whose child pages blocked EREMOVE. */ __sgx_sanitize_pages(&sgx_dirty_page_list); - __sgx_sanitize_pages(&sgx_dirty_page_list);
- /* sanity check: */ - WARN_ON(!list_empty(&sgx_dirty_page_list)); + left_dirty = __sgx_sanitize_pages(&sgx_dirty_page_list); + if (left_dirty && !kthread_should_stop()) + pr_err("%lu unsanitized pages\n", left_dirty);
while (!kthread_should_stop()) { if (try_to_freeze())
If you do the check here you already have a window where kthread could have been stopped anyhow.
So even this would be less correct:
if (kthreas_should_stop()) { return 0; } else if (left_dirty) { pr_err("%lu unsanitized pages\n", left_dirty); }
So in the end you end as complicated and less correct fix. This all is explained in the commit message.
If you unconditionally print error, you don't have a meaning for the number of unsanitized pags.
Understood that the goal is to only print the number of unsanitized pages if ksgxd has not been stopped prematurely.
Reinette