[PATCH v2 hmm 00/11] Various revisions from a locking/code review
Jason Gunthorpe
jgg at ziepe.ca
Thu Jun 13 17:50:09 UTC 2019
On Wed, Jun 12, 2019 at 09:49:12PM +0000, Yang, Philip wrote:
> Rebase to https://github.com/jgunthorpe/linux.git hmm branch, need some
> changes because of interface hmm_range_register change. Then run a quick
> amdgpu_test. Test is finished, result is ok.
Great! Thanks
I'll add your Tested-by to the series
> But there is below kernel BUG message, seems hmm_free_rcu calls
> down_write.....
>
> [ 1171.919921] BUG: sleeping function called from invalid context at
> /home/yangp/git/compute_staging/kernel/kernel/locking/rwsem.c:65
> [ 1171.919933] in_atomic(): 1, irqs_disabled(): 0, pid: 53, name:
> kworker/1:1
> [ 1171.919938] 2 locks held by kworker/1:1/53:
> [ 1171.919940] #0: 000000001c7c19d4 ((wq_completion)rcu_gp){+.+.}, at:
> process_one_work+0x20e/0x630
> [ 1171.919951] #1: 00000000923f2cfa
> ((work_completion)(&sdp->work)){+.+.}, at: process_one_work+0x20e/0x630
> [ 1171.919959] CPU: 1 PID: 53 Comm: kworker/1:1 Tainted: G W
> 5.2.0-rc1-kfd-yangp #196
> [ 1171.919961] Hardware name: ASUS All Series/Z97-PRO(Wi-Fi ac)/USB 3.1,
> BIOS 9001 03/07/2016
> [ 1171.919965] Workqueue: rcu_gp srcu_invoke_callbacks
> [ 1171.919968] Call Trace:
> [ 1171.919974] dump_stack+0x67/0x9b
> [ 1171.919980] ___might_sleep+0x149/0x230
> [ 1171.919985] down_write+0x1c/0x70
> [ 1171.919989] hmm_free_rcu+0x24/0x80
> [ 1171.919993] srcu_invoke_callbacks+0xc9/0x150
> [ 1171.920000] process_one_work+0x28e/0x630
> [ 1171.920008] worker_thread+0x39/0x3f0
> [ 1171.920014] ? process_one_work+0x630/0x630
> [ 1171.920017] kthread+0x11c/0x140
> [ 1171.920021] ? kthread_park+0x90/0x90
> [ 1171.920026] ret_from_fork+0x24/0x30
Thank you Phillip, it seems the prior tests were not done with
lockdep..
Sigh, I will keep this with the gross pagetable_lock then. I updated
the patches on the git with this modification. I think we have covered
all the bases so I will send another V of the series to the list and
if no more comments then it will move ahead to hmm.git. Thanks to all.
diff --git a/mm/hmm.c b/mm/hmm.c
index 136c812faa2790..4c64d4c32f4825 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -49,16 +49,15 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm)
lockdep_assert_held_exclusive(&mm->mmap_sem);
+ /* Abuse the page_table_lock to also protect mm->hmm. */
+ spin_lock(&mm->page_table_lock);
if (mm->hmm) {
- if (kref_get_unless_zero(&mm->hmm->kref))
+ if (kref_get_unless_zero(&mm->hmm->kref)) {
+ spin_unlock(&mm->page_table_lock);
return mm->hmm;
- /*
- * The hmm is being freed by some other CPU and is pending a
- * RCU grace period, but this CPU can NULL now it since we
- * have the mmap_sem.
- */
- mm->hmm = NULL;
+ }
}
+ spin_unlock(&mm->page_table_lock);
hmm = kmalloc(sizeof(*hmm), GFP_KERNEL);
if (!hmm)
@@ -81,7 +80,14 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm)
}
mmgrab(hmm->mm);
+
+ /*
+ * We hold the exclusive mmap_sem here so we know that mm->hmm is
+ * still NULL or 0 kref, and is safe to update.
+ */
+ spin_lock(&mm->page_table_lock);
mm->hmm = hmm;
+ spin_unlock(&mm->page_table_lock);
return hmm;
}
@@ -89,10 +95,14 @@ static void hmm_free_rcu(struct rcu_head *rcu)
{
struct hmm *hmm = container_of(rcu, struct hmm, rcu);
- down_write(&hmm->mm->mmap_sem);
+ /*
+ * The mm->hmm pointer is kept valid while notifier ops can be running
+ * so they don't have to deal with a NULL mm->hmm value
+ */
+ spin_lock(&hmm->mm->page_table_lock);
if (hmm->mm->hmm == hmm)
hmm->mm->hmm = NULL;
- up_write(&hmm->mm->mmap_sem);
+ spin_unlock(&hmm->mm->page_table_lock);
mmdrop(hmm->mm);
kfree(hmm);
More information about the amd-gfx
mailing list