linux-watchdog.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister
@ 2015-11-24 23:45 Damien Riegel
  2015-11-24 23:45 ` [PATCH v2 2/2] watchdog: core: factorize register error paths Damien Riegel
  2015-11-25  2:20 ` [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Guenter Roeck
  0 siblings, 2 replies; 7+ messages in thread
From: Damien Riegel @ 2015-11-24 23:45 UTC (permalink / raw)
  To: linux-watchdog; +Cc: Wim Van Sebroeck, Guenter Roeck, kernel, Damien Riegel

device_create is called after watchdog_dev_register, so it makes more
sense to call the cleanup functions in reverse order, ie. device_destroy
before watchdog_dev_unregister.

Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
---
 drivers/watchdog/watchdog_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 551af04..e70b6e8 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -264,8 +264,8 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
 		if (ret) {
 			dev_err(wdd->dev, "Cannot register reboot notifier (%d)\n",
 				ret);
-			watchdog_dev_unregister(wdd);
 			device_destroy(watchdog_class, devno);
+			watchdog_dev_unregister(wdd);
 			ida_simple_remove(&watchdog_ida, wdd->id);
 			wdd->dev = NULL;
 			return ret;
@@ -324,10 +324,10 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)
 		unregister_reboot_notifier(&wdd->reboot_nb);
 
 	devno = wdd->cdev.dev;
+	device_destroy(watchdog_class, devno);
 	ret = watchdog_dev_unregister(wdd);
 	if (ret)
 		pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
-	device_destroy(watchdog_class, devno);
 	ida_simple_remove(&watchdog_ida, wdd->id);
 	wdd->dev = NULL;
 }
-- 
2.5.0

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

* [PATCH v2 2/2] watchdog: core: factorize register error paths
  2015-11-24 23:45 [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Damien Riegel
@ 2015-11-24 23:45 ` Damien Riegel
  2015-11-25  2:20   ` Guenter Roeck
  2015-11-25  2:20 ` [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Guenter Roeck
  1 sibling, 1 reply; 7+ messages in thread
From: Damien Riegel @ 2015-11-24 23:45 UTC (permalink / raw)
  To: linux-watchdog; +Cc: Wim Van Sebroeck, Guenter Roeck, kernel, Damien Riegel

The commit adding the reboot notifier in the core introduced a new error
path in __watchdog_register_device, making error paths quite redundant.

This commit factorizes all error paths that do some cleanup.

Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
---
 drivers/watchdog/watchdog_core.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index e70b6e8..3d17c1c1 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -241,20 +241,16 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
 		wdd->id = id;
 
 		ret = watchdog_dev_register(wdd);
-		if (ret) {
-			ida_simple_remove(&watchdog_ida, id);
-			return ret;
-		}
+		if (ret)
+			goto remove_ida;
 	}
 
 	devno = wdd->cdev.dev;
 	wdd->dev = device_create(watchdog_class, wdd->parent, devno,
 					wdd, "watchdog%d", wdd->id);
 	if (IS_ERR(wdd->dev)) {
-		watchdog_dev_unregister(wdd);
-		ida_simple_remove(&watchdog_ida, id);
 		ret = PTR_ERR(wdd->dev);
-		return ret;
+		goto unregister_device;
 	}
 
 	if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
@@ -264,11 +260,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
 		if (ret) {
 			dev_err(wdd->dev, "Cannot register reboot notifier (%d)\n",
 				ret);
-			device_destroy(watchdog_class, devno);
-			watchdog_dev_unregister(wdd);
-			ida_simple_remove(&watchdog_ida, wdd->id);
-			wdd->dev = NULL;
-			return ret;
+			goto destroy_device;
 		}
 	}
 
@@ -282,6 +274,16 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
 	}
 
 	return 0;
+
+destroy_device:
+	device_destroy(watchdog_class, devno);
+unregister_device:
+	watchdog_dev_unregister(wdd);
+	wdd->dev = NULL;
+remove_ida:
+	ida_simple_remove(&watchdog_ida, id);
+
+	return ret;
 }
 
 /**
-- 
2.5.0


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

* Re: [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister
  2015-11-24 23:45 [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Damien Riegel
  2015-11-24 23:45 ` [PATCH v2 2/2] watchdog: core: factorize register error paths Damien Riegel
@ 2015-11-25  2:20 ` Guenter Roeck
  2015-11-25 17:09   ` Damien Riegel
  1 sibling, 1 reply; 7+ messages in thread
From: Guenter Roeck @ 2015-11-25  2:20 UTC (permalink / raw)
  To: Damien Riegel, linux-watchdog; +Cc: Wim Van Sebroeck, kernel

On 11/24/2015 03:45 PM, Damien Riegel wrote:
> device_create is called after watchdog_dev_register, so it makes more
> sense to call the cleanup functions in reverse order, ie. device_destroy
> before watchdog_dev_unregister.
>
> Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>   drivers/watchdog/watchdog_core.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index 551af04..e70b6e8 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -264,8 +264,8 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
>   		if (ret) {
>   			dev_err(wdd->dev, "Cannot register reboot notifier (%d)\n",
>   				ret);
> -			watchdog_dev_unregister(wdd);
>   			device_destroy(watchdog_class, devno);
> +			watchdog_dev_unregister(wdd);
>   			ida_simple_remove(&watchdog_ida, wdd->id);
>   			wdd->dev = NULL;
>   			return ret;
> @@ -324,10 +324,10 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)
>   		unregister_reboot_notifier(&wdd->reboot_nb);
>
>   	devno = wdd->cdev.dev;
> +	device_destroy(watchdog_class, devno);
>   	ret = watchdog_dev_unregister(wdd);
>   	if (ret)
>   		pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
> -	device_destroy(watchdog_class, devno);
>   	ida_simple_remove(&watchdog_ida, wdd->id);
>   	wdd->dev = NULL;
>   }
>


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

* Re: [PATCH v2 2/2] watchdog: core: factorize register error paths
  2015-11-24 23:45 ` [PATCH v2 2/2] watchdog: core: factorize register error paths Damien Riegel
@ 2015-11-25  2:20   ` Guenter Roeck
  0 siblings, 0 replies; 7+ messages in thread
From: Guenter Roeck @ 2015-11-25  2:20 UTC (permalink / raw)
  To: Damien Riegel, linux-watchdog; +Cc: Wim Van Sebroeck, kernel

On 11/24/2015 03:45 PM, Damien Riegel wrote:
> The commit adding the reboot notifier in the core introduced a new error
> path in __watchdog_register_device, making error paths quite redundant.
>
> This commit factorizes all error paths that do some cleanup.
>
> Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>   drivers/watchdog/watchdog_core.c | 26 ++++++++++++++------------
>   1 file changed, 14 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
> index e70b6e8..3d17c1c1 100644
> --- a/drivers/watchdog/watchdog_core.c
> +++ b/drivers/watchdog/watchdog_core.c
> @@ -241,20 +241,16 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
>   		wdd->id = id;
>
>   		ret = watchdog_dev_register(wdd);
> -		if (ret) {
> -			ida_simple_remove(&watchdog_ida, id);
> -			return ret;
> -		}
> +		if (ret)
> +			goto remove_ida;
>   	}
>
>   	devno = wdd->cdev.dev;
>   	wdd->dev = device_create(watchdog_class, wdd->parent, devno,
>   					wdd, "watchdog%d", wdd->id);
>   	if (IS_ERR(wdd->dev)) {
> -		watchdog_dev_unregister(wdd);
> -		ida_simple_remove(&watchdog_ida, id);
>   		ret = PTR_ERR(wdd->dev);
> -		return ret;
> +		goto unregister_device;
>   	}
>
>   	if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) {
> @@ -264,11 +260,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
>   		if (ret) {
>   			dev_err(wdd->dev, "Cannot register reboot notifier (%d)\n",
>   				ret);
> -			device_destroy(watchdog_class, devno);
> -			watchdog_dev_unregister(wdd);
> -			ida_simple_remove(&watchdog_ida, wdd->id);
> -			wdd->dev = NULL;
> -			return ret;
> +			goto destroy_device;
>   		}
>   	}
>
> @@ -282,6 +274,16 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
>   	}
>
>   	return 0;
> +
> +destroy_device:
> +	device_destroy(watchdog_class, devno);
> +unregister_device:
> +	watchdog_dev_unregister(wdd);
> +	wdd->dev = NULL;
> +remove_ida:
> +	ida_simple_remove(&watchdog_ida, id);
> +
> +	return ret;
>   }
>
>   /**
>


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

* Re: [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister
  2015-11-25  2:20 ` [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Guenter Roeck
@ 2015-11-25 17:09   ` Damien Riegel
  2015-11-25 17:57     ` Guenter Roeck
  0 siblings, 1 reply; 7+ messages in thread
From: Damien Riegel @ 2015-11-25 17:09 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: linux-watchdog, Wim Van Sebroeck, kernel

On Tue, Nov 24, 2015 at 06:20:11PM -0800, Guenter Roeck wrote:
> On 11/24/2015 03:45 PM, Damien Riegel wrote:
> >device_create is called after watchdog_dev_register, so it makes more
> >sense to call the cleanup functions in reverse order, ie. device_destroy
> >before watchdog_dev_unregister.
> >
> >Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
> 
> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> 

On second thought, I am wondering if the proper fix would not be to call
device_create before watchdog_dev_register. Consider the following
scenario:

  watchdog_register_device
    __watchdog_register_device
	  watchdog_dev_register returns successfully, char dev is live
      device_create fails, setting wdd->dev to an ERR_PTR
	  ...
	  meanwhile, a user opens the watchdog, hence ops->start is called.
	  If ops->start uses wdd->dev (to print a debug message for
	  instance), it will dereference an invalid pointer.

Admittedly, it should be quite rare, but there is still a chance for a
race condition here.

Damien

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

* Re: [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister
  2015-11-25 17:09   ` Damien Riegel
@ 2015-11-25 17:57     ` Guenter Roeck
  2015-11-25 22:43       ` Damien Riegel
  0 siblings, 1 reply; 7+ messages in thread
From: Guenter Roeck @ 2015-11-25 17:57 UTC (permalink / raw)
  To: Damien Riegel, linux-watchdog, Wim Van Sebroeck, kernel

Hi Damien,

On 11/25/2015 09:09 AM, Damien Riegel wrote:
> On Tue, Nov 24, 2015 at 06:20:11PM -0800, Guenter Roeck wrote:
>> On 11/24/2015 03:45 PM, Damien Riegel wrote:
>>> device_create is called after watchdog_dev_register, so it makes more
>>> sense to call the cleanup functions in reverse order, ie. device_destroy
>>> before watchdog_dev_unregister.
>>>
>>> Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
>>
>> Reviewed-by: Guenter Roeck <linux@roeck-us.net>
>>
>
> On second thought, I am wondering if the proper fix would not be to call
> device_create before watchdog_dev_register. Consider the following
> scenario:
>
>    watchdog_register_device
>      __watchdog_register_device
> 	  watchdog_dev_register returns successfully, char dev is live
>        device_create fails, setting wdd->dev to an ERR_PTR
> 	  ...
> 	  meanwhile, a user opens the watchdog, hence ops->start is called.
> 	  If ops->start uses wdd->dev (to print a debug message for
> 	  instance), it will dereference an invalid pointer.
>
> Admittedly, it should be quite rare, but there is still a chance for a
> race condition here.
>
Only we should not have race conditions, and this might actually happen
if user space listens for a udev event on the character device, and device
creation is delayed for some reasons.

I think you are right, that is a problem. Back to the drawing board.

Ok, next question: Does it hurt to call device_create() first ?
That creates the sysfs entries for the driver.

If that doesn't work either, the only other idea I have would be to reject
an attempt to open the character device with -EAGAIN or similar if the
device node is not yet (or not anymore) available. Or maybe that would
be the correct approach anyway ? Or can we use some lock to synchronize
the two operations ?

Thanks,
Guenter


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

* Re: [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister
  2015-11-25 17:57     ` Guenter Roeck
@ 2015-11-25 22:43       ` Damien Riegel
  0 siblings, 0 replies; 7+ messages in thread
From: Damien Riegel @ 2015-11-25 22:43 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: linux-watchdog, Wim Van Sebroeck, kernel

On Wed, Nov 25, 2015 at 09:57:20AM -0800, Guenter Roeck wrote:
> Hi Damien,
> 
> On 11/25/2015 09:09 AM, Damien Riegel wrote:
> >On Tue, Nov 24, 2015 at 06:20:11PM -0800, Guenter Roeck wrote:
> >>On 11/24/2015 03:45 PM, Damien Riegel wrote:
> >>>device_create is called after watchdog_dev_register, so it makes more
> >>>sense to call the cleanup functions in reverse order, ie. device_destroy
> >>>before watchdog_dev_unregister.
> >>>
> >>>Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
> >>
> >>Reviewed-by: Guenter Roeck <linux@roeck-us.net>
> >>
> >
> >On second thought, I am wondering if the proper fix would not be to call
> >device_create before watchdog_dev_register. Consider the following
> >scenario:
> >
> >   watchdog_register_device
> >     __watchdog_register_device
> >	  watchdog_dev_register returns successfully, char dev is live
> >       device_create fails, setting wdd->dev to an ERR_PTR
> >	  ...
> >	  meanwhile, a user opens the watchdog, hence ops->start is called.
> >	  If ops->start uses wdd->dev (to print a debug message for
> >	  instance), it will dereference an invalid pointer.
> >
> >Admittedly, it should be quite rare, but there is still a chance for a
> >race condition here.
> >
> Only we should not have race conditions, and this might actually happen
> if user space listens for a udev event on the character device, and device
> creation is delayed for some reasons.
> 
> I think you are right, that is a problem. Back to the drawing board.
> 
> Ok, next question: Does it hurt to call device_create() first ?
> That creates the sysfs entries for the driver.

I can't think of a case where it would be an issue to call
device_create() first. After all, watchdog_dev_register just creates
entries in /dev, so it makes sense to create them only when the watchdog
is fully ready. I will send patches tomorrow.

> 
> If that doesn't work either, the only other idea I have would be to reject
> an attempt to open the character device with -EAGAIN or similar if the
> device node is not yet (or not anymore) available. Or maybe that would
> be the correct approach anyway ? Or can we use some lock to synchronize
> the two operations ?
> 
> Thanks,
> Guenter
> 

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

end of thread, other threads:[~2015-11-25 22:43 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-24 23:45 [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Damien Riegel
2015-11-24 23:45 ` [PATCH v2 2/2] watchdog: core: factorize register error paths Damien Riegel
2015-11-25  2:20   ` Guenter Roeck
2015-11-25  2:20 ` [PATCH v2 1/2] watchdog: core: call device_destroy before watchdog_dev_unregister Guenter Roeck
2015-11-25 17:09   ` Damien Riegel
2015-11-25 17:57     ` Guenter Roeck
2015-11-25 22:43       ` Damien Riegel

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).