On Mon, Jun 27, 2005 at 04:59:54PM -0700, Roland Dreier wrote: > Something like this should work...
Yes, but don't forget the first part of my patch (for libibverbs/src/device.c) I think it should be applied to. [snip] > > -void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) > +static void ib_umem_account(void *work_ptr) > { > - struct mm_struct *mm; > + struct ib_umem_account_work *work = work_ptr; > > - mm = get_task_mm(current); Are you sure that ib_umem_account will run on behalf the process that schedules it? Anyway you are correctly using work->mm in the rest of the function so this line should be dropped I think. > + down_write(&work->mm->mmap_sem); > + work->mm->locked_vm -= work->diff; > + up_write(&work->mm->mmap_sem); > + mmput(work->mm); > + kfree(work); > +} > > - if (mm) { > - down_write(&mm->mmap_sem); > - mm->locked_vm -= PAGE_ALIGN(umem->length + umem->offset) >> > PAGE_SHIFT; > - } > +void ib_umem_release(struct ib_device *dev, struct ib_umem *umem) > +{ > + struct mm_struct *mm; > > __ib_umem_release(dev, umem, 1); > > + mm = get_task_mm(current); > if (mm) { > - up_write(&mm->mmap_sem); > - mmput(mm); > + /* > + * 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. > + * > + * To handle this, we try to grab the mmap_sem, and if > + * we can't get it immediately, we defer the > + * accounting to the system workqueue. > + */ > + if (down_write_trylock(&mm->mmap_sem)) { > + mm->locked_vm -= PAGE_ALIGN(umem->length + > umem->offset) >> PAGE_SHIFT; > + up_write(&mm->mmap_sem); > + mmput(mm); > + } else { > + struct ib_umem_account_work *work; > + > + work = kmalloc(sizeof *work, GFP_KERNEL); > + if (!work) > + return; > + > + INIT_WORK(&work->work, ib_umem_account, work); > + work->mm = mm; > + work->diff = PAGE_ALIGN(umem->length + umem->offset) >> > PAGE_SHIFT; > + > + schedule_work(&work->work); > + } > } > } -- Gleb. _______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general