[PATCH v5 4/7] udmabuf: udmabuf_create pin folio codestyle cleanup

Huan Yang link at vivo.com
Fri Sep 6 08:30:56 UTC 2024


在 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) {
			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