Instead of an awkward goto-construct use a loop-construct to delete entries from the list of mm_struct's. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> --- Still problems with my test env so only compilation test at this point. arch/x86/kernel/cpu/sgx/driver/main.c | 39 +++++++++++++-------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/driver/main.c b/arch/x86/kernel/cpu/sgx/driver/main.c index 27cf271b25f6..bb7f1932529f 100644 --- a/arch/x86/kernel/cpu/sgx/driver/main.c +++ b/arch/x86/kernel/cpu/sgx/driver/main.c @@ -55,30 +55,27 @@ static int sgx_release(struct inode *inode, struct file *file) struct sgx_encl *encl = file->private_data; struct sgx_encl_mm *encl_mm; - /* - * Objects can't be *moved* off an RCU protected list (deletion is ok), - * nor can the object be freed until after synchronize_srcu(). - */ -restart: - spin_lock(&encl->mm_lock); - if (list_empty(&encl->mm_list)) { - encl_mm = NULL; - } else { - encl_mm = list_first_entry(&encl->mm_list, struct sgx_encl_mm, - list); - list_del_rcu(&encl_mm->list); - } - spin_unlock(&encl->mm_lock); + for ( ; ; ) { + spin_lock(&encl->mm_lock); + + if (list_empty(&encl->mm_list)) { + encl_mm = NULL; + } else { + encl_mm = list_first_entry(&encl->mm_list, + struct sgx_encl_mm, list); + list_del_rcu(&encl_mm->list); + } - if (encl_mm) { - synchronize_srcu(&encl->srcu); + spin_unlock(&encl->mm_lock); - mmu_notifier_unregister(&encl_mm->mmu_notifier, encl_mm->mm); + /* The list is empty, ready to go. */ + if (!encl_mm) + break; + synchronize_srcu(&encl->srcu); + mmu_notifier_unregister(&encl_mm->mmu_notifier, encl_mm->mm); kfree(encl_mm); - - goto restart; - } + }; mutex_lock(&encl->lock); encl->flags |= SGX_ENCL_DEAD; @@ -86,8 +83,8 @@ static int sgx_release(struct inode *inode, struct file *file) if (encl->work.func) flush_work(&encl->work); - kref_put(&encl->refcount, sgx_encl_release); + kref_put(&encl->refcount, sgx_encl_release); return 0; } -- 2.20.1