On 2021/1/25 23:47, Jason Gunthorpe wrote: > On Mon, Jan 25, 2021 at 04:34:56PM +0800, Zhou Wang wrote: > >> +static int uacce_pin_page(struct uacce_pin_container *priv, >> + struct uacce_pin_address *addr) >> +{ >> + unsigned int flags = FOLL_FORCE | FOLL_WRITE; >> + unsigned long first, last, nr_pages; >> + struct page **pages; >> + struct pin_pages *p; >> + int ret; >> + >> + first = (addr->addr & PAGE_MASK) >> PAGE_SHIFT; >> + last = ((addr->addr + addr->size - 1) & PAGE_MASK) >> PAGE_SHIFT; >> + nr_pages = last - first + 1; >> + >> + pages = vmalloc(nr_pages * sizeof(struct page *)); >> + if (!pages) >> + return -ENOMEM; >> + >> + p = kzalloc(sizeof(*p), GFP_KERNEL); >> + if (!p) { >> + ret = -ENOMEM; >> + goto free; >> + } >> + >> + ret = pin_user_pages_fast(addr->addr & PAGE_MASK, nr_pages, >> + flags | FOLL_LONGTERM, pages); > > This needs to copy the RLIMIT_MEMLOCK and can_do_mlock() stuff from > other places, like ib_umem_get I am confused as can_do_mlock seems to be about the limitation of mlock, which has different meaning with pin memory? > >> + ret = xa_err(xa_store(&priv->array, p->first, p, GFP_KERNEL)); > > And this is really weird, I don't think it makes sense to make handles > for DMA based on the starting VA. Here starting VA is used as an index of pinned pages. When doing unpinning, starting VA is used to get pinned pages, check unpinned VA/size. But it has problem here to use xa_store here as new one will replace old one :( Seems we can use xa_insert here, which returns -EBUSY if the entry at one index is not empty. The design here will be that we only support to pin same VA once. > >> +static int uacce_unpin_page(struct uacce_pin_container *priv, >> + struct uacce_pin_address *addr) >> +{ >> + unsigned long first, last, nr_pages; >> + struct pin_pages *p; >> + >> + first = (addr->addr & PAGE_MASK) >> PAGE_SHIFT; >> + last = ((addr->addr + addr->size - 1) & PAGE_MASK) >> PAGE_SHIFT; >> + nr_pages = last - first + 1; >> + >> + /* find pin_pages */ >> + p = xa_load(&priv->array, first); >> + if (!p) >> + return -ENODEV; >> + >> + if (p->nr_pages != nr_pages) >> + return -EINVAL; >> + >> + /* unpin */ >> + unpin_user_pages(p->pages, p->nr_pages); > > And unpinning without guaranteeing there is no ongoing DMA is really > weird > > Are you abusing this in conjunction with a SVA scheme just to prevent > page motion? Why wasn't mlock good enough? Just as Barry said, mlock can not avoid IOPF from page migration. Best, Zhou > > Jason > > . >