linux/drivers/infiniband/core/umem.c
/**
 * ib_umem_release - release memory pinned with ib_umem_get
 * @umem: umem struct to release
 */
release memory pinned with ib_umem_get
@umem: umem struct to release
release memory pinned with ib_umem_get @umem : umem struct to release
void ib_umem_release(struct ib_umem *umem)
{
	struct ib_ucontext *context = umem->context;
	struct mm_struct *mm;
	struct task_struct *task;
	unsigned long diff;
	if (umem->odp_data) {
		ib_umem_odp_release(umem);
		return;
	}
	__ib_umem_release(umem->context->device, umem, 1);
	task = get_pid_task(umem->context->tgid, PIDTYPE_PID);
	if (!task)
		goto out;
	mm = get_task_mm(task);
	put_task_struct(task);
	if (!mm)
		goto out;
	diff = ib_umem_num_pages(umem);
	if (context->closing) {
		if (!down_write_trylock(&mm->mmap_sem)) {
			INIT_WORK(&umem->work, ib_umem_account);
			umem->mm   = mm;
			umem->diff = diff;
			queue_work(ib_wq, &umem->work);
			return;
		}
	} else
		down_write(&mm->mmap_sem);
	mm->pinned_vm -= diff;
	up_write(&mm->mmap_sem);
	mmput(mm);
out:
	kfree(umem);
}
void ib_umem_release ( struct ib_umem * umem ) { struct ib_ucontext * context = umem -> context ; struct mm_struct * mm ; struct task_struct * task ; unsigned long diff ; if ( umem -> odp_data ) { ib_umem_odp_release ( umem ) ; return ; } __ib_umem_release ( umem -> context -> device , umem , 1 ) ; task = get_pid_task ( umem -> context -> tgid , PIDTYPE_PID ) ; if ( ! task ) goto out ; mm = get_task_mm ( task ) ; put_task_struct ( task ) ; if ( ! mm ) goto out ; diff = ib_umem_num_pages ( umem ) ; if ( context -> closing ) { if ( ! down_write_trylock ( & mm -> mmap_sem ) ) { INIT_WORK ( & umem -> work , ib_umem_account ) ; umem -> mm = mm ; umem -> diff = diff ; queue_work ( ib_wq , & umem -> work ) ; return ; } } else down_write ( & mm -> mmap_sem ) ; mm -> pinned_vm -= diff ; up_write ( & mm -> mmap_sem ) ; mmput ( mm ) ; out : kfree ( umem ) ; }
ib_umem_release - release memory pinned with ib_umem_get
 @umem: umem struct to release
ib_umem_release - release memory pinned with ib_umem_get @umem : umem struct to release
/*
	 * We may be called with the mm's mmap_sem already held.  This
	 * can happen when a userspace munmap() is the call that drops
	 * the last reference to our file and calls our release
	 * method.  If there are memory regions to destroy, we'll end
	 * up here and not be able to take the mmap_sem.  In that case
	 * we defer the vm_locked accounting to the system workqueue.
	 */