mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 17:54:13 +08:00
drivers/mic/scif: do not use mmap_sem
The driver uses mmap_sem for both pinned_vm accounting and get_user_pages(). By using gup_fast() and letting the mm handle the lock if needed, we can no longer rely on the semaphore and simplify the whole thing. Reviewed-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
parent
70f8a3ca68
commit
4f564ff3d4
@ -272,21 +272,12 @@ static inline void __scif_release_mm(struct mm_struct *mm)
|
||||
|
||||
static inline int
|
||||
__scif_dec_pinned_vm_lock(struct mm_struct *mm,
|
||||
int nr_pages, bool try_lock)
|
||||
int nr_pages)
|
||||
{
|
||||
if (!mm || !nr_pages || !scif_ulimit_check)
|
||||
return 0;
|
||||
if (try_lock) {
|
||||
if (!down_write_trylock(&mm->mmap_sem)) {
|
||||
dev_err(scif_info.mdev.this_device,
|
||||
"%s %d err\n", __func__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
down_write(&mm->mmap_sem);
|
||||
}
|
||||
|
||||
atomic64_sub(nr_pages, &mm->pinned_vm);
|
||||
up_write(&mm->mmap_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -298,16 +289,16 @@ static inline int __scif_check_inc_pinned_vm(struct mm_struct *mm,
|
||||
if (!mm || !nr_pages || !scif_ulimit_check)
|
||||
return 0;
|
||||
|
||||
locked = nr_pages;
|
||||
locked += atomic64_read(&mm->pinned_vm);
|
||||
lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
|
||||
locked = atomic64_add_return(nr_pages, &mm->pinned_vm);
|
||||
|
||||
if ((locked > lock_limit) && !capable(CAP_IPC_LOCK)) {
|
||||
atomic64_sub(nr_pages, &mm->pinned_vm);
|
||||
dev_err(scif_info.mdev.this_device,
|
||||
"locked(%lu) > lock_limit(%lu)\n",
|
||||
locked, lock_limit);
|
||||
return -ENOMEM;
|
||||
}
|
||||
atomic64_set(&mm->pinned_vm, locked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -326,7 +317,7 @@ int scif_destroy_window(struct scif_endpt *ep, struct scif_window *window)
|
||||
|
||||
might_sleep();
|
||||
if (!window->temp && window->mm) {
|
||||
__scif_dec_pinned_vm_lock(window->mm, window->nr_pages, 0);
|
||||
__scif_dec_pinned_vm_lock(window->mm, window->nr_pages);
|
||||
__scif_release_mm(window->mm);
|
||||
window->mm = NULL;
|
||||
}
|
||||
@ -737,7 +728,7 @@ done:
|
||||
ep->rma_info.dma_chan);
|
||||
} else {
|
||||
if (!__scif_dec_pinned_vm_lock(window->mm,
|
||||
window->nr_pages, 1)) {
|
||||
window->nr_pages)) {
|
||||
__scif_release_mm(window->mm);
|
||||
window->mm = NULL;
|
||||
}
|
||||
@ -1385,28 +1376,23 @@ int __scif_pin_pages(void *addr, size_t len, int *out_prot,
|
||||
prot |= SCIF_PROT_WRITE;
|
||||
retry:
|
||||
mm = current->mm;
|
||||
down_write(&mm->mmap_sem);
|
||||
if (ulimit) {
|
||||
err = __scif_check_inc_pinned_vm(mm, nr_pages);
|
||||
if (err) {
|
||||
up_write(&mm->mmap_sem);
|
||||
pinned_pages->nr_pages = 0;
|
||||
goto error_unmap;
|
||||
}
|
||||
}
|
||||
|
||||
pinned_pages->nr_pages = get_user_pages(
|
||||
pinned_pages->nr_pages = get_user_pages_fast(
|
||||
(u64)addr,
|
||||
nr_pages,
|
||||
(prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
|
||||
pinned_pages->pages,
|
||||
NULL);
|
||||
up_write(&mm->mmap_sem);
|
||||
pinned_pages->pages);
|
||||
if (nr_pages != pinned_pages->nr_pages) {
|
||||
if (try_upgrade) {
|
||||
if (ulimit)
|
||||
__scif_dec_pinned_vm_lock(mm,
|
||||
nr_pages, 0);
|
||||
__scif_dec_pinned_vm_lock(mm, nr_pages);
|
||||
/* Roll back any pinned pages */
|
||||
for (i = 0; i < pinned_pages->nr_pages; i++) {
|
||||
if (pinned_pages->pages[i])
|
||||
@ -1433,7 +1419,7 @@ retry:
|
||||
return err;
|
||||
dec_pinned:
|
||||
if (ulimit)
|
||||
__scif_dec_pinned_vm_lock(mm, nr_pages, 0);
|
||||
__scif_dec_pinned_vm_lock(mm, nr_pages);
|
||||
/* Something went wrong! Rollback */
|
||||
error_unmap:
|
||||
pinned_pages->nr_pages = nr_pages;
|
||||
|
Loading…
Reference in New Issue
Block a user