Skip to content

Commit 3c90d8b

Browse files
committed
udmabuf: udmabuf_create pin folio codestyle cleanup
JIRA: https://issues.redhat.com/browse/RHEL-89519 Conflicts: A merge conflict in a udmabuf_create() hunk due to the presence of a later upstream commit f49856f ("udmabuf: fix memory leak on last export_udmabuf() error path"). commit 164fd9e Author: Huan Yang <link@vivo.com> Date: Wed, 18 Sep 2024 10:52:27 +0800 udmabuf: udmabuf_create pin folio codestyle cleanup This patch aim to simplify the memfd folio pin during the udmabuf create. No functional changes. This patch create a udmabuf_pin_folios function, in this, do the memfd pin folio and then record each pinned folio, offset. This patch simplify the pinned folio record, iter by each pinned folio, and then record each offset in it. Compare to iter by pgcnt, more readable. Suggested-by: Vivek Kasireddy <vivek.kasireddy@intel.com> Signed-off-by: Huan Yang <link@vivo.com> Acked-by: Vivek Kasireddy <vivek.kasireddy@intel.com> Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240918025238.2957823-5-link@vivo.com Signed-off-by: Waiman Long <longman@redhat.com>
1 parent 100c8a5 commit 3c90d8b

File tree

1 file changed

+76
-61
lines changed

1 file changed

+76
-61
lines changed

drivers/dma-buf/udmabuf.c

Lines changed: 76 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,6 @@ static int check_memfd_seals(struct file *memfd)
291291
{
292292
int seals;
293293

294-
if (!memfd)
295-
return -EBADFD;
296-
297294
if (!shmem_file(memfd) && !is_file_hugepages(memfd))
298295
return -EBADFD;
299296

@@ -322,18 +319,69 @@ static struct dma_buf *export_udmabuf(struct udmabuf *ubuf,
322319
return dma_buf_export(&exp_info);
323320
}
324321

322+
static long udmabuf_pin_folios(struct udmabuf *ubuf, struct file *memfd,
323+
loff_t start, loff_t size)
324+
{
325+
pgoff_t pgoff, pgcnt, upgcnt = ubuf->pagecount;
326+
struct folio **folios = NULL;
327+
u32 cur_folio, cur_pgcnt;
328+
long nr_folios;
329+
long ret = 0;
330+
loff_t end;
331+
332+
pgcnt = size >> PAGE_SHIFT;
333+
folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL);
334+
if (!folios)
335+
return -ENOMEM;
336+
337+
end = start + (pgcnt << PAGE_SHIFT) - 1;
338+
nr_folios = memfd_pin_folios(memfd, start, end, folios, pgcnt, &pgoff);
339+
if (nr_folios <= 0) {
340+
ret = nr_folios ? nr_folios : -EINVAL;
341+
goto end;
342+
}
343+
344+
cur_pgcnt = 0;
345+
for (cur_folio = 0; cur_folio < nr_folios; ++cur_folio) {
346+
pgoff_t subpgoff = pgoff;
347+
size_t fsize = folio_size(folios[cur_folio]);
348+
349+
ret = add_to_unpin_list(&ubuf->unpin_list, folios[cur_folio]);
350+
if (ret < 0)
351+
goto end;
352+
353+
for (; subpgoff < fsize; subpgoff += PAGE_SIZE) {
354+
ubuf->folios[upgcnt] = folios[cur_folio];
355+
ubuf->offsets[upgcnt] = subpgoff;
356+
++upgcnt;
357+
358+
if (++cur_pgcnt >= pgcnt)
359+
goto end;
360+
}
361+
362+
/**
363+
* In a given range, only the first subpage of the first folio
364+
* has an offset, that is returned by memfd_pin_folios().
365+
* The first subpages of other folios (in the range) have an
366+
* offset of 0.
367+
*/
368+
pgoff = 0;
369+
}
370+
end:
371+
ubuf->pagecount = upgcnt;
372+
kvfree(folios);
373+
return ret;
374+
}
375+
325376
static long udmabuf_create(struct miscdevice *device,
326377
struct udmabuf_create_list *head,
327378
struct udmabuf_create_item *list)
328379
{
329-
pgoff_t pgoff, pgcnt, pglimit, pgbuf = 0;
330-
long nr_folios, ret = -EINVAL;
331-
struct file *memfd = NULL;
332-
struct folio **folios;
380+
pgoff_t pgcnt = 0, pglimit;
333381
struct udmabuf *ubuf;
334382
struct dma_buf *dmabuf;
335-
u32 i, j, k, flags;
336-
loff_t end;
383+
long ret = -EINVAL;
384+
u32 i, flags;
337385

338386
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
339387
if (!ubuf)
@@ -342,81 +390,50 @@ static long udmabuf_create(struct miscdevice *device,
342390
INIT_LIST_HEAD(&ubuf->unpin_list);
343391
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
344392
for (i = 0; i < head->count; i++) {
345-
if (!IS_ALIGNED(list[i].offset, PAGE_SIZE))
393+
if (!PAGE_ALIGNED(list[i].offset))
346394
goto err;
347-
if (!IS_ALIGNED(list[i].size, PAGE_SIZE))
395+
if (!PAGE_ALIGNED(list[i].size))
348396
goto err;
349-
ubuf->pagecount += list[i].size >> PAGE_SHIFT;
350-
if (ubuf->pagecount > pglimit)
397+
398+
pgcnt += list[i].size >> PAGE_SHIFT;
399+
if (pgcnt > pglimit)
351400
goto err;
352401
}
353402

354-
if (!ubuf->pagecount)
403+
if (!pgcnt)
355404
goto err;
356405

357-
ubuf->folios = kvmalloc_array(ubuf->pagecount, sizeof(*ubuf->folios),
358-
GFP_KERNEL);
406+
ubuf->folios = kvmalloc_array(pgcnt, sizeof(*ubuf->folios), GFP_KERNEL);
359407
if (!ubuf->folios) {
360408
ret = -ENOMEM;
361409
goto err;
362410
}
363-
ubuf->offsets = kvcalloc(ubuf->pagecount, sizeof(*ubuf->offsets),
364-
GFP_KERNEL);
411+
412+
ubuf->offsets = kvcalloc(pgcnt, sizeof(*ubuf->offsets), GFP_KERNEL);
365413
if (!ubuf->offsets) {
366414
ret = -ENOMEM;
367415
goto err;
368416
}
369417

370-
pgbuf = 0;
371418
for (i = 0; i < head->count; i++) {
372-
memfd = fget(list[i].memfd);
373-
ret = check_memfd_seals(memfd);
374-
if (ret < 0)
375-
goto err;
419+
struct file *memfd = fget(list[i].memfd);
376420

377-
pgcnt = list[i].size >> PAGE_SHIFT;
378-
folios = kvmalloc_array(pgcnt, sizeof(*folios), GFP_KERNEL);
379-
if (!folios) {
380-
ret = -ENOMEM;
421+
if (!memfd) {
422+
ret = -EBADFD;
381423
goto err;
382424
}
383425

384-
end = list[i].offset + (pgcnt << PAGE_SHIFT) - 1;
385-
ret = memfd_pin_folios(memfd, list[i].offset, end,
386-
folios, pgcnt, &pgoff);
387-
if (ret <= 0) {
388-
kvfree(folios);
389-
if (!ret)
390-
ret = -EINVAL;
426+
ret = check_memfd_seals(memfd);
427+
if (ret < 0) {
428+
fput(memfd);
391429
goto err;
392430
}
393431

394-
nr_folios = ret;
395-
pgoff >>= PAGE_SHIFT;
396-
for (j = 0, k = 0; j < pgcnt; j++) {
397-
ubuf->folios[pgbuf] = folios[k];
398-
ubuf->offsets[pgbuf] = pgoff << PAGE_SHIFT;
399-
400-
if (j == 0 || ubuf->folios[pgbuf-1] != folios[k]) {
401-
ret = add_to_unpin_list(&ubuf->unpin_list,
402-
folios[k]);
403-
if (ret < 0) {
404-
kfree(folios);
405-
goto err;
406-
}
407-
}
408-
409-
pgbuf++;
410-
if (++pgoff == folio_nr_pages(folios[k])) {
411-
pgoff = 0;
412-
if (++k == nr_folios)
413-
break;
414-
}
415-
}
416-
417-
kvfree(folios);
432+
ret = udmabuf_pin_folios(ubuf, memfd, list[i].offset,
433+
list[i].size);
418434
fput(memfd);
419-
memfd = NULL;
435+
if (ret)
436+
goto err;
420437
}
421438

422439
flags = head->flags & UDMABUF_FLAGS_CLOEXEC ? O_CLOEXEC : 0;
@@ -438,8 +455,6 @@ static long udmabuf_create(struct miscdevice *device,
438455
return ret;
439456

440457
err:
441-
if (memfd)
442-
fput(memfd);
443458
unpin_all_folios(&ubuf->unpin_list);
444459
kvfree(ubuf->offsets);
445460
kvfree(ubuf->folios);

0 commit comments

Comments
 (0)