Commit c8a53b2d authored by Jason Gunthorpe's avatar Jason Gunthorpe

mm/hmm: Hold a mmgrab from hmm to mm

So long as a struct hmm pointer exists, so should the struct mm it is
linked too. Hold the mmgrab() as soon as a hmm is created, and mmdrop() it
once the hmm refcount goes to zero.

Since mmdrop() (ie a 0 kref on struct mm) is now impossible with a !NULL
mm->hmm delete the hmm_hmm_destroy().
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Reviewed-by: default avatarJérôme Glisse <jglisse@redhat.com>
Reviewed-by: default avatarJohn Hubbard <jhubbard@nvidia.com>
Reviewed-by: default avatarRalph Campbell <rcampbell@nvidia.com>
Reviewed-by: default avatarIra Weiny <ira.weiny@intel.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Tested-by: default avatarPhilip Yang <Philip.Yang@amd.com>
parent e36acfe6
...@@ -577,14 +577,11 @@ static inline int hmm_vma_fault(struct hmm_mirror *mirror, ...@@ -577,14 +577,11 @@ static inline int hmm_vma_fault(struct hmm_mirror *mirror,
} }
/* Below are for HMM internal use only! Not to be used by device driver! */ /* Below are for HMM internal use only! Not to be used by device driver! */
void hmm_mm_destroy(struct mm_struct *mm);
static inline void hmm_mm_init(struct mm_struct *mm) static inline void hmm_mm_init(struct mm_struct *mm)
{ {
mm->hmm = NULL; mm->hmm = NULL;
} }
#else /* IS_ENABLED(CONFIG_HMM_MIRROR) */ #else /* IS_ENABLED(CONFIG_HMM_MIRROR) */
static inline void hmm_mm_destroy(struct mm_struct *mm) {}
static inline void hmm_mm_init(struct mm_struct *mm) {} static inline void hmm_mm_init(struct mm_struct *mm) {}
#endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */ #endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */
......
...@@ -673,7 +673,6 @@ void __mmdrop(struct mm_struct *mm) ...@@ -673,7 +673,6 @@ void __mmdrop(struct mm_struct *mm)
WARN_ON_ONCE(mm == current->active_mm); WARN_ON_ONCE(mm == current->active_mm);
mm_free_pgd(mm); mm_free_pgd(mm);
destroy_context(mm); destroy_context(mm);
hmm_mm_destroy(mm);
mmu_notifier_mm_destroy(mm); mmu_notifier_mm_destroy(mm);
check_mm(mm); check_mm(mm);
put_user_ns(mm->user_ns); put_user_ns(mm->user_ns);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/swapops.h> #include <linux/swapops.h>
#include <linux/hugetlb.h> #include <linux/hugetlb.h>
#include <linux/memremap.h> #include <linux/memremap.h>
#include <linux/sched/mm.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/mmu_notifier.h> #include <linux/mmu_notifier.h>
...@@ -73,6 +74,7 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm) ...@@ -73,6 +74,7 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm)
hmm->notifiers = 0; hmm->notifiers = 0;
hmm->dead = false; hmm->dead = false;
hmm->mm = mm; hmm->mm = mm;
mmgrab(hmm->mm);
spin_lock(&mm->page_table_lock); spin_lock(&mm->page_table_lock);
if (!mm->hmm) if (!mm->hmm)
...@@ -100,6 +102,7 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm) ...@@ -100,6 +102,7 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm)
mm->hmm = NULL; mm->hmm = NULL;
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
error: error:
mmdrop(hmm->mm);
kfree(hmm); kfree(hmm);
return NULL; return NULL;
} }
...@@ -121,6 +124,7 @@ static void hmm_free(struct kref *kref) ...@@ -121,6 +124,7 @@ static void hmm_free(struct kref *kref)
mm->hmm = NULL; mm->hmm = NULL;
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
mmdrop(hmm->mm);
mmu_notifier_call_srcu(&hmm->rcu, hmm_free_rcu); mmu_notifier_call_srcu(&hmm->rcu, hmm_free_rcu);
} }
...@@ -129,24 +133,6 @@ static inline void hmm_put(struct hmm *hmm) ...@@ -129,24 +133,6 @@ static inline void hmm_put(struct hmm *hmm)
kref_put(&hmm->kref, hmm_free); kref_put(&hmm->kref, hmm_free);
} }
void hmm_mm_destroy(struct mm_struct *mm)
{
struct hmm *hmm;
spin_lock(&mm->page_table_lock);
hmm = mm_get_hmm(mm);
mm->hmm = NULL;
if (hmm) {
hmm->mm = NULL;
hmm->dead = true;
spin_unlock(&mm->page_table_lock);
hmm_put(hmm);
return;
}
spin_unlock(&mm->page_table_lock);
}
static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm) static void hmm_release(struct mmu_notifier *mn, struct mm_struct *mm)
{ {
struct hmm *hmm = container_of(mn, struct hmm, mmu_notifier); struct hmm *hmm = container_of(mn, struct hmm, mmu_notifier);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment