Hi Huan, > Subject: Re: [PATCH v5 4/7] udmabuf: udmabuf_create pin folio codestyle > cleanup > > > 在 2024/9/6 16:17, Kasireddy, Vivek 写道: > > Hi Huan, > > > >> Subject: [PATCH v5 4/7] udmabuf: udmabuf_create pin folio codestyle > >> cleanup > >> > >> This patch split pin folios into single function: udmabuf_pin_folios. > >> > >> When record folio and offset into udmabuf_folio and offsets, the outer > >> loop of this patch iterates through folios, while the inner loop correctly > >> sets the folio and corresponding offset into the udmabuf starting from > >> the offset. if reach to pgcnt or nr_folios, end of loop. > >> > >> By this, more readable. > >> > >> Signed-off-by: Huan Yang <link@xxxxxxxx> > >> --- > >> drivers/dma-buf/udmabuf.c | 132 ++++++++++++++++++++------------------ > >> 1 file changed, 71 insertions(+), 61 deletions(-) > >> > >> diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c > >> index 456db58446e1..ca2b21c5c57f 100644 > >> --- a/drivers/dma-buf/udmabuf.c > >> +++ b/drivers/dma-buf/udmabuf.c > >> @@ -330,17 +330,67 @@ static int export_udmabuf(struct udmabuf > *ubuf, > >> return dma_buf_fd(buf, flags); > >> } > >> > >> +static int udmabuf_pin_folios(struct udmabuf *ubuf, struct file *memfd, > >> + loff_t start, loff_t size) > >> +{ > >> + pgoff_t pgoff, pgcnt, upgcnt = ubuf->pagecount; > >> + u32 cur_folio, cur_pgcnt; > >> + struct folio **folios = NULL; > >> + long nr_folios; > >> + loff_t end; > >> + int ret = 0; > > Change ret's type and this function's return type to long for consistency. > > > >> + > >> + pgcnt = size >> PAGE_SHIFT; > >> + folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL); > >> + if (!folios) > >> + return -ENOMEM; > >> + > >> + end = start + (pgcnt << PAGE_SHIFT) - 1; > >> + nr_folios = memfd_pin_folios(memfd, start, end, folios, pgcnt, > >> &pgoff); > >> + if (nr_folios <= 0) { > >> + ret = nr_folios ? nr_folios : -EINVAL; > >> + goto err; > >> + } > >> + > >> + cur_pgcnt = 0; > >> + for (cur_folio = 0; cur_folio < nr_folios; ++cur_folio) { > >> + pgoff_t subpgoff = pgoff; > >> + size_t fsize = folio_size(folios[cur_folio]); > >> + > >> + ret = add_to_unpin_list(&ubuf->unpin_list, folios[cur_folio]); > >> + if (ret < 0) > >> + goto err; > >> + > >> + for (; subpgoff < fsize; subpgoff += PAGE_SIZE) { > >> + ubuf->folios[upgcnt] = folios[cur_folio]; > >> + ubuf->offsets[upgcnt] = subpgoff; > >> + ++upgcnt; > >> + > >> + if (++cur_pgcnt >= pgcnt) > >> + goto end; > >> + } > >> + > >> + /** > >> + * The term range may start with offset, so the first folio > >> + * need take care of it. And the remain folio start from 0. > > The comments above are not very meaningful. Please rewrite them as: > > * In a given range, only the first subpage of the first folio has an offset, that > > * is returned by memfd_pin_folios(). The first subpages of other folios (in > the > > * range) have an offset of 0. > > > >> + */ > >> + pgoff = 0; > >> + } > >> +end: > >> +err: > > No need to have two labels here. Keep end and get rid of err? > > > >> + ubuf->pagecount = upgcnt; > >> + kvfree(folios); > >> + return ret; > >> +} > >> + > >> static long udmabuf_create(struct miscdevice *device, > >> struct udmabuf_create_list *head, > >> struct udmabuf_create_item *list) > >> { > >> - pgoff_t pgoff, pgcnt, pglimit, pgbuf = 0; > >> - long nr_folios, ret = -EINVAL; > >> - struct file *memfd = NULL; > >> - struct folio **folios; > >> + pgoff_t pgcnt = 0, pglimit; > >> + long ret = -EINVAL; > >> struct udmabuf *ubuf; > >> - u32 i, j, k, flags; > >> - loff_t end; > >> + u32 i, flags; > >> > >> ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL); > >> if (!ubuf) > >> @@ -349,81 +399,43 @@ static long udmabuf_create(struct miscdevice > >> *device, > >> INIT_LIST_HEAD(&ubuf->unpin_list); > >> pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT; > >> for (i = 0; i < head->count; i++) { > >> - if (!IS_ALIGNED(list[i].offset, PAGE_SIZE)) > >> + if (!PAGE_ALIGNED(list[i].offset)) > >> goto err; > >> - if (!IS_ALIGNED(list[i].size, PAGE_SIZE)) > >> + if (!PAGE_ALIGNED(list[i].size)) > >> goto err; > >> - ubuf->pagecount += list[i].size >> PAGE_SHIFT; > >> - if (ubuf->pagecount > pglimit) > >> + > >> + pgcnt += list[i].size >> PAGE_SHIFT; > >> + if (pgcnt > pglimit) > >> goto err; > >> } > >> > >> - if (!ubuf->pagecount) > >> + if (!pgcnt) > >> goto err; > >> > >> - ubuf->folios = kvmalloc_array(ubuf->pagecount, sizeof(*ubuf- > >>> folios), > >> - GFP_KERNEL); > >> + ubuf->folios = kvmalloc_array(pgcnt, sizeof(*ubuf->folios), > >> GFP_KERNEL); > >> if (!ubuf->folios) { > >> ret = -ENOMEM; > >> goto err; > >> } > >> - ubuf->offsets = kvcalloc(ubuf->pagecount, sizeof(*ubuf->offsets), > >> - GFP_KERNEL); > >> + > >> + ubuf->offsets = kvcalloc(pgcnt, sizeof(*ubuf->offsets), GFP_KERNEL); > >> if (!ubuf->offsets) { > >> ret = -ENOMEM; > >> goto err; > >> } > >> > >> - pgbuf = 0; > >> for (i = 0; i < head->count; i++) { > >> - memfd = fget(list[i].memfd); > >> + struct file *memfd = fget(list[i].memfd); > >> + > >> ret = check_memfd_seals(memfd); > >> if (ret < 0) > >> goto err; > >> > >> - pgcnt = list[i].size >> PAGE_SHIFT; > >> - folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL); > >> - if (!folios) { > >> - ret = -ENOMEM; > >> - goto err; > >> - } > >> - > >> - end = list[i].offset + (pgcnt << PAGE_SHIFT) - 1; > >> - ret = memfd_pin_folios(memfd, list[i].offset, end, > >> - folios, pgcnt, &pgoff); > >> - if (ret <= 0) { > >> - kvfree(folios); > >> - if (!ret) > >> - ret = -EINVAL; > >> - goto err; > >> - } > >> - > >> - nr_folios = ret; > >> - pgoff >>= PAGE_SHIFT; > >> - for (j = 0, k = 0; j < pgcnt; j++) { > >> - ubuf->folios[pgbuf] = folios[k]; > >> - ubuf->offsets[pgbuf] = pgoff << PAGE_SHIFT; > >> - > >> - if (j == 0 || ubuf->folios[pgbuf-1] != folios[k]) { > >> - ret = add_to_unpin_list(&ubuf->unpin_list, > >> - folios[k]); > >> - if (ret < 0) { > >> - kfree(folios); > >> - goto err; > >> - } > >> - } > >> - > >> - pgbuf++; > >> - if (++pgoff == folio_nr_pages(folios[k])) { > >> - pgoff = 0; > >> - if (++k == nr_folios) > >> - break; > >> - } > >> - } > >> - > >> - kvfree(folios); > >> + ret = udmabuf_pin_folios(ubuf, memfd, list[i].offset, > >> + list[i].size); > >> fput(memfd); > >> - memfd = NULL; > >> + if (ret) > >> + goto err; > >> } > >> > >> flags = head->flags & UDMABUF_FLAGS_CLOEXEC ? O_CLOEXEC : 0; > >> @@ -434,8 +446,6 @@ static long udmabuf_create(struct miscdevice > >> *device, > >> return ret; > >> > >> err: > >> - if (memfd) > >> - fput(memfd); > > I think this needs to stay because if the seals check fails, then we would not > be > > doing fput(memfd). > > Yes, there a mistake, but I'd like set it into here: > > ret = check_memfd_seals(memfd); > if (ret < 0) { You still need an if (memfd) check here because check_memfd_seals() might do: if (!memfd) return -EBADFD; Thanks, Vivek > fput(memfd); > goto err; > } > due to only in inner look, memfd can get. and memfd change into loop var. > Thanks > > > > > Thanks, > > Vivek > > > >> unpin_all_folios(&ubuf->unpin_list); > >> kvfree(ubuf->offsets); > >> kvfree(ubuf->folios); > >> -- > >> 2.45.2