Commit c8a53b2d authored by Jason Gunthorpe's avatar Jason Gunthorpe
Browse files

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
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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! */
void hmm_mm_destroy(struct mm_struct *mm);

static inline void hmm_mm_init(struct mm_struct *mm)
{
	mm->hmm = NULL;
}
#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) {}
#endif /* IS_ENABLED(CONFIG_HMM_MIRROR) */

+0 −1
Original line number Diff line number Diff line
@@ -673,7 +673,6 @@ void __mmdrop(struct mm_struct *mm)
	WARN_ON_ONCE(mm == current->active_mm);
	mm_free_pgd(mm);
	destroy_context(mm);
	hmm_mm_destroy(mm);
	mmu_notifier_mm_destroy(mm);
	check_mm(mm);
	put_user_ns(mm->user_ns);
+4 −18
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/swapops.h>
#include <linux/hugetlb.h>
#include <linux/memremap.h>
#include <linux/sched/mm.h>
#include <linux/jump_label.h>
#include <linux/dma-mapping.h>
#include <linux/mmu_notifier.h>
@@ -73,6 +74,7 @@ static struct hmm *hmm_get_or_create(struct mm_struct *mm)
	hmm->notifiers = 0;
	hmm->dead = false;
	hmm->mm = mm;
	mmgrab(hmm->mm);

	spin_lock(&mm->page_table_lock);
	if (!mm->hmm)
@@ -100,6 +102,7 @@ error_mm:
		mm->hmm = NULL;
	spin_unlock(&mm->page_table_lock);
error:
	mmdrop(hmm->mm);
	kfree(hmm);
	return NULL;
}
@@ -121,6 +124,7 @@ static void hmm_free(struct kref *kref)
		mm->hmm = NULL;
	spin_unlock(&mm->page_table_lock);

	mmdrop(hmm->mm);
	mmu_notifier_call_srcu(&hmm->rcu, hmm_free_rcu);
}

@@ -129,24 +133,6 @@ static inline void hmm_put(struct hmm *hmm)
	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)
{
	struct hmm *hmm = container_of(mn, struct hmm, mmu_notifier);