linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] media: v4l2-dev: optimize device node number allocation logic
@ 2025-06-11 13:59 Haipeng Jiang
  2025-06-12  9:30 ` Ricardo Ribalda
  0 siblings, 1 reply; 5+ messages in thread
From: Haipeng Jiang @ 2025-06-11 13:59 UTC (permalink / raw)
  To: hverkuil, mchehab, ribalda, sebastian.fricke, bartosz.golaszewski,
	hljunggr, make24, viro
  Cc: linux-media, Haipeng Jiang

Refactor the device node number selection to:
1. Avoid redundant search in auto-allocation case (nr < 0)
2. Simplify error handling with unified boundary check
3. Maintain identical behavior for both auto and specific allocation

For automatic allocation (start = 0):
- Only search [0, minor_cnt) once
- Return -ENFILE if no free node found

For specific node request (start > 0):
- First search [start, minor_cnt)
- Then search [0, start) if first fails
- Return -ENFILE if both ranges have no free node

Signed-off-by: Haipeng Jiang <haipengjiang@foxmail.com>
---
 drivers/media/v4l2-core/v4l2-dev.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index c369235113d9..23d04c890e6b 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -907,6 +907,7 @@ int __video_register_device(struct video_device *vdev,
 	int ret;
 	int minor_offset = 0;
 	int minor_cnt = VIDEO_NUM_DEVICES;
+	int start;
 	const char *name_base;
 
 	/* A minor value of -1 marks this video device as never
@@ -994,10 +995,11 @@ int __video_register_device(struct video_device *vdev,
 
 	/* Pick a device node number */
 	mutex_lock(&videodev_lock);
-	nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
-	if (nr == minor_cnt)
-		nr = devnode_find(vdev, 0, minor_cnt);
-	if (nr == minor_cnt) {
+	start = (nr < 0) ? 0 : nr;
+	nr = devnode_find(vdev, start, minor_cnt);
+	if (nr == minor_cnt && start != 0)
+		nr = devnode_find(vdev, 0, start);
+	if (nr == (start != 0 ? start : minor_cnt)) {
 		pr_err("could not get a free device node number\n");
 		mutex_unlock(&videodev_lock);
 		return -ENFILE;
-- 
2.46.2.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] media: v4l2-dev: optimize device node number allocation logic
  2025-06-11 13:59 [PATCH] media: v4l2-dev: optimize device node number allocation logic Haipeng Jiang
@ 2025-06-12  9:30 ` Ricardo Ribalda
  2025-06-14  6:34   ` [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find Haipeng Jiang
  0 siblings, 1 reply; 5+ messages in thread
From: Ricardo Ribalda @ 2025-06-12  9:30 UTC (permalink / raw)
  To: Haipeng Jiang
  Cc: hverkuil, mchehab, sebastian.fricke, bartosz.golaszewski,
	hljunggr, make24, viro, linux-media

Hi Haipeng

Thanks for the patch.

Please note that devnode_find should be a very efficient bit
operation, it is most of the time done in O(1) and not in O(N) despide
it would sound otherwise.

If you want to refactor the code, I would suggest modifying
devnode_find() instead. Something like this (untested)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c
b/drivers/media/v4l2-core/v4l2-dev.c
index c369235113d9..400240afb85d 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -138,10 +138,20 @@ static inline void devnode_clear(struct
video_device *vdev)
        clear_bit(vdev->num, devnode_bits(vdev->vfl_type));
 }

-/* Try to find a free device node number in the range [from, to> */
+/* Try to find a free device node number in the range [from, to> , wrapping */
 static inline int devnode_find(struct video_device *vdev, int from, int to)
 {
-       return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
+       int ret;
+
+       ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
+       if (ret == to && from == 0)
+               return -ENOSPC;
+
+       ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), from, 0);
+       if (ret == from)
+               return -ENOSPC;
+
+       return ret;
 }

 struct video_device *video_device_alloc(void)
@@ -994,10 +1004,8 @@ int __video_register_device(struct video_device *vdev,

        /* Pick a device node number */
        mutex_lock(&videodev_lock);
-       nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
-       if (nr == minor_cnt)
-               nr = devnode_find(vdev, 0, minor_cnt);
-       if (nr == minor_cnt) {
+       nr = devnode_find(vdev, (nr == -1) ? 0 : nr, minor_cnt);
+       if (nr == -ENOSPC) {
                pr_err("could not get a free device node number\n");
                mutex_unlock(&videodev_lock);
                return -ENFILE;


Regards

On Wed, 11 Jun 2025 at 16:06, Haipeng Jiang <haipengjiang@foxmail.com> wrote:
>
> Refactor the device node number selection to:
> 1. Avoid redundant search in auto-allocation case (nr < 0)
> 2. Simplify error handling with unified boundary check
> 3. Maintain identical behavior for both auto and specific allocation
>
> For automatic allocation (start = 0):
> - Only search [0, minor_cnt) once
> - Return -ENFILE if no free node found
>
> For specific node request (start > 0):
> - First search [start, minor_cnt)
> - Then search [0, start) if first fails
> - Return -ENFILE if both ranges have no free node
>
> Signed-off-by: Haipeng Jiang <haipengjiang@foxmail.com>
> ---
>  drivers/media/v4l2-core/v4l2-dev.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index c369235113d9..23d04c890e6b 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -907,6 +907,7 @@ int __video_register_device(struct video_device *vdev,
>         int ret;
>         int minor_offset = 0;
>         int minor_cnt = VIDEO_NUM_DEVICES;
> +       int start;
>         const char *name_base;
>
>         /* A minor value of -1 marks this video device as never
> @@ -994,10 +995,11 @@ int __video_register_device(struct video_device *vdev,
>
>         /* Pick a device node number */
>         mutex_lock(&videodev_lock);
> -       nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
> -       if (nr == minor_cnt)
> -               nr = devnode_find(vdev, 0, minor_cnt);
> -       if (nr == minor_cnt) {
> +       start = (nr < 0) ? 0 : nr;
> +       nr = devnode_find(vdev, start, minor_cnt);
> +       if (nr == minor_cnt && start != 0)
> +               nr = devnode_find(vdev, 0, start);
> +       if (nr == (start != 0 ? start : minor_cnt)) {
>                 pr_err("could not get a free device node number\n");
>                 mutex_unlock(&videodev_lock);
>                 return -ENFILE;
> --
> 2.46.2.windows.1
>


-- 
Ricardo Ribalda

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find
  2025-06-12  9:30 ` Ricardo Ribalda
@ 2025-06-14  6:34   ` Haipeng Jiang
  2025-06-16  6:40     ` Ricardo Ribalda
  0 siblings, 1 reply; 5+ messages in thread
From: Haipeng Jiang @ 2025-06-14  6:34 UTC (permalink / raw)
  To: ribalda
  Cc: bartosz.golaszewski, haipengjiang, hljunggr, hverkuil,
	linux-media, make24, mchehab, sebastian.fricke, viro

Moved wrap-around search logic into devnode_find() to avoid redundant
lookups when nr=0. Returns -ENOSPC when device node numbers are
exhausted.

Signed-off-by: Haipeng Jiang <haipengjiang@foxmail.com>
---
Changes in v2:
- Implemented wrap-around search logic directly in devnode_find()

 drivers/media/v4l2-core/v4l2-dev.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index c369235113d9..39e175d529a4 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -138,10 +138,22 @@ static inline void devnode_clear(struct video_device *vdev)
 	clear_bit(vdev->num, devnode_bits(vdev->vfl_type));
 }
 
-/* Try to find a free device node number in the range [from, to> */
+/* Try to find a free device node number in the range [from, to>, wrapping */
 static inline int devnode_find(struct video_device *vdev, int from, int to)
 {
-	return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
+	int ret;
+
+	ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
+
+	if (ret == to) {
+		if (from == 0)
+			return -ENOSPC;
+		ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), from, 0);
+		if (ret == from)
+			return -ENOSPC;
+	}
+
+	return ret;
 }
 
 struct video_device *video_device_alloc(void)
@@ -995,9 +1007,7 @@ int __video_register_device(struct video_device *vdev,
 	/* Pick a device node number */
 	mutex_lock(&videodev_lock);
 	nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
-	if (nr == minor_cnt)
-		nr = devnode_find(vdev, 0, minor_cnt);
-	if (nr == minor_cnt) {
+	if (nr == -ENOSPC) {
 		pr_err("could not get a free device node number\n");
 		mutex_unlock(&videodev_lock);
 		return -ENFILE;
-- 
2.46.2.windows.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find
  2025-06-14  6:34   ` [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find Haipeng Jiang
@ 2025-06-16  6:40     ` Ricardo Ribalda
  2025-06-17  8:26       ` Hans Verkuil
  0 siblings, 1 reply; 5+ messages in thread
From: Ricardo Ribalda @ 2025-06-16  6:40 UTC (permalink / raw)
  To: Haipeng Jiang
  Cc: bartosz.golaszewski, hljunggr, hverkuil, linux-media, make24,
	mchehab, sebastian.fricke, viro

On Sat, 14 Jun 2025 at 08:35, Haipeng Jiang <haipengjiang@foxmail.com> wrote:
>
> Moved wrap-around search logic into devnode_find() to avoid redundant
> lookups when nr=0. Returns -ENOSPC when device node numbers are
> exhausted.
>
Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
> Signed-off-by: Haipeng Jiang <haipengjiang@foxmail.com>
> ---
> Changes in v2:
> - Implemented wrap-around search logic directly in devnode_find()
>
>  drivers/media/v4l2-core/v4l2-dev.c | 20 +++++++++++++++-----
>  1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
> index c369235113d9..39e175d529a4 100644
> --- a/drivers/media/v4l2-core/v4l2-dev.c
> +++ b/drivers/media/v4l2-core/v4l2-dev.c
> @@ -138,10 +138,22 @@ static inline void devnode_clear(struct video_device *vdev)
>         clear_bit(vdev->num, devnode_bits(vdev->vfl_type));
>  }
>
> -/* Try to find a free device node number in the range [from, to> */
> +/* Try to find a free device node number in the range [from, to>, wrapping */
>  static inline int devnode_find(struct video_device *vdev, int from, int to)
>  {
> -       return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
> +       int ret;
> +
> +       ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
> +
> +       if (ret == to) {
> +               if (from == 0)
> +                       return -ENOSPC;
> +               ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), from, 0);
> +               if (ret == from)
> +                       return -ENOSPC;
> +       }
> +
> +       return ret;
>  }
>

The code is correct, but I would have implemented it a bit differently
to avoid indentation level.
Probably nitpicking.

ret = find_next_zero()
if (ret != to)
  return ret;
if (from == 0)
   return -ENOSPC;
ret = find_next_zero()
if (ret == from)
  return -ENOSPC
return ret;

As I previously said, find_next_zero_bit is really fast, so there is
no big harm to run it twice even if it is not needed. Up to the
maintainer to decide if they need the patch or not :)

Thanks



>  struct video_device *video_device_alloc(void)
> @@ -995,9 +1007,7 @@ int __video_register_device(struct video_device *vdev,
>         /* Pick a device node number */
>         mutex_lock(&videodev_lock);
>         nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
> -       if (nr == minor_cnt)
> -               nr = devnode_find(vdev, 0, minor_cnt);
> -       if (nr == minor_cnt) {
> +       if (nr == -ENOSPC) {
>                 pr_err("could not get a free device node number\n");
>                 mutex_unlock(&videodev_lock);
>                 return -ENFILE;
> --
> 2.46.2.windows.1
>


-- 
Ricardo Ribalda

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find
  2025-06-16  6:40     ` Ricardo Ribalda
@ 2025-06-17  8:26       ` Hans Verkuil
  0 siblings, 0 replies; 5+ messages in thread
From: Hans Verkuil @ 2025-06-17  8:26 UTC (permalink / raw)
  To: Ricardo Ribalda, Haipeng Jiang
  Cc: bartosz.golaszewski, hljunggr, hverkuil, linux-media, make24,
	mchehab, sebastian.fricke, viro

On 16/06/2025 08:40, Ricardo Ribalda wrote:
> On Sat, 14 Jun 2025 at 08:35, Haipeng Jiang <haipengjiang@foxmail.com> wrote:
>>
>> Moved wrap-around search logic into devnode_find() to avoid redundant
>> lookups when nr=0. Returns -ENOSPC when device node numbers are
>> exhausted.
>>
> Reviewed-by: Ricardo Ribalda <ribalda@chromium.org>
>> Signed-off-by: Haipeng Jiang <haipengjiang@foxmail.com>
>> ---
>> Changes in v2:
>> - Implemented wrap-around search logic directly in devnode_find()
>>
>>  drivers/media/v4l2-core/v4l2-dev.c | 20 +++++++++++++++-----
>>  1 file changed, 15 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
>> index c369235113d9..39e175d529a4 100644
>> --- a/drivers/media/v4l2-core/v4l2-dev.c
>> +++ b/drivers/media/v4l2-core/v4l2-dev.c
>> @@ -138,10 +138,22 @@ static inline void devnode_clear(struct video_device *vdev)
>>         clear_bit(vdev->num, devnode_bits(vdev->vfl_type));
>>  }
>>
>> -/* Try to find a free device node number in the range [from, to> */
>> +/* Try to find a free device node number in the range [from, to>, wrapping */
>>  static inline int devnode_find(struct video_device *vdev, int from, int to)
>>  {
>> -       return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
>> +       int ret;
>> +
>> +       ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from);
>> +
>> +       if (ret == to) {
>> +               if (from == 0)
>> +                       return -ENOSPC;
>> +               ret = find_next_zero_bit(devnode_bits(vdev->vfl_type), from, 0);
>> +               if (ret == from)
>> +                       return -ENOSPC;
>> +       }
>> +
>> +       return ret;
>>  }
>>
> 
> The code is correct, but I would have implemented it a bit differently
> to avoid indentation level.
> Probably nitpicking.
> 
> ret = find_next_zero()
> if (ret != to)
>   return ret;
> if (from == 0)
>    return -ENOSPC;
> ret = find_next_zero()
> if (ret == from)
>   return -ENOSPC
> return ret;
> 
> As I previously said, find_next_zero_bit is really fast, so there is
> no big harm to run it twice even if it is not needed. Up to the
> maintainer to decide if they need the patch or not :)

I don't see a compelling reason to take this patch. It is a very slight improvement
if you run out of available minor numbers, which is exceedingly rare. And you have
bigger problems if you hit that.

So I'm dropping this patch, it just makes the code longer without any real benefits.

Sorry,

	Hans

> 
> Thanks
> 
> 
> 
>>  struct video_device *video_device_alloc(void)
>> @@ -995,9 +1007,7 @@ int __video_register_device(struct video_device *vdev,
>>         /* Pick a device node number */
>>         mutex_lock(&videodev_lock);
>>         nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt);
>> -       if (nr == minor_cnt)
>> -               nr = devnode_find(vdev, 0, minor_cnt);
>> -       if (nr == minor_cnt) {
>> +       if (nr == -ENOSPC) {
>>                 pr_err("could not get a free device node number\n");
>>                 mutex_unlock(&videodev_lock);
>>                 return -ENFILE;
>> --
>> 2.46.2.windows.1
>>
> 
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-06-17  8:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-11 13:59 [PATCH] media: v4l2-dev: optimize device node number allocation logic Haipeng Jiang
2025-06-12  9:30 ` Ricardo Ribalda
2025-06-14  6:34   ` [PATCH v2] media: v4l2-dev: implement wrap-around search in devnode_find Haipeng Jiang
2025-06-16  6:40     ` Ricardo Ribalda
2025-06-17  8:26       ` Hans Verkuil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).