[PATCH v5 4/7] udmabuf: udmabuf_create pin folio codestyle cleanup
Huan Yang
link at vivo.com
Mon Sep 9 06:31:15 UTC 2024
在 2024/9/9 13:03, Kasireddy, Vivek 写道:
> 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 at vivo.com>
>>>> ---
>>>> 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;
Yes, fput do not check if pointer is NULL.
Thanks.
>
> 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
More information about the dri-devel
mailing list