diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2019-05-23 12:37:52 -0400 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2019-05-23 16:34:08 -0400 |
commit | 12ccde1834b06147346259de3fa2cc65d019c43c (patch) | |
tree | 73febfe39ea715612bf55ce723929af39fc0a032 | |
parent | 3fe4ee6511878a83836763f8789b0360db073948 (diff) |
mm/hmm: do not try to create hmm struct from within hmm_range_register() v2
Driver should never call hmm_range_register() without a valid and active
registered hmm_mirror and thus without a valid and active hmm struct. So
if that happens just return -EFAULT.
Changes since v1:
- do not use READ_ONCE() and make it clear what is the API expectation
- remove hmm variable in hmm_range_register()
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Suggested-by: Ralph Campbell <rcampbell@nvidia.com>
Suggested-by: Jason Gunthorpe <jgg@mellanox.com>
Cc: Jason Gunthorpe <jgg@mellanox.com>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Ralph Campbell <rcampbell@nvidia.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Souptick Joarder <jrdr.linux@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r-- | mm/hmm.c | 19 |
1 files changed, 11 insertions, 8 deletions
@@ -912,7 +912,6 @@ int hmm_range_register(struct hmm_range *range, unsigned page_shift) { unsigned long mask = ((1UL << page_shift) - 1UL); - struct hmm *hmm; range->valid = false; range->hmm = NULL; @@ -922,14 +921,18 @@ int hmm_range_register(struct hmm_range *range, if (start >= end) return -EINVAL; + /* + * The caller must hold a valid struct hmm_mirror to call this api, + * and a valid hmm_mirror guarantees mm->hmm is valid and does not + * change. + */ + range->hmm = mm->hmm; + kref_get(&range->hmm->kref); + range->page_shift = page_shift; range->start = start; range->end = end; - range->hmm = hmm_get_or_create(mm); - if (!range->hmm) - return -EFAULT; - /* Check if hmm_mm_destroy() was call. */ if (range->hmm->mm == NULL || range->hmm->dead) { hmm_put(range->hmm); @@ -939,15 +942,15 @@ int hmm_range_register(struct hmm_range *range, /* Initialize range to track CPU page table updates. */ mutex_lock(&range->hmm->lock); - list_add_rcu(&range->list, &hmm->ranges); + list_add_rcu(&range->list, &range->hmm->ranges); /* * If there are any concurrent notifiers we have to wait for them for * the range to be valid (see hmm_range_wait_until_valid()). */ - if (!hmm->notifiers) + if (!range->hmm->notifiers) range->valid = true; - mutex_unlock(&hmm->lock); + mutex_unlock(&range->hmm->lock); return 0; } |