diff mbox

[6/6] libmultipath: fixup dm_rename to complete cookie on failure

Message ID 1462341450-5507-7-git-send-email-hare@suse.de (mailing list archive)
State Not Applicable, archived
Delegated to: Mike Snitzer
Headers show

Commit Message

Hannes Reinecke May 4, 2016, 5:57 a.m. UTC
>From my understanding we should be calling udev_complete() on
a cookie if dm_task_set_cookie() failed.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
 libmultipath/devmapper.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Benjamin Marzinski May 6, 2016, 8:29 p.m. UTC | #1
On Wed, May 04, 2016 at 07:57:30AM +0200, Hannes Reinecke wrote:
> >From my understanding we should be calling udev_complete() on
> a cookie if dm_task_set_cookie() failed.

I was wrong when I said that this will sometimes be helpful to us. It is
true that it won't hurt things. But that is because it will never do
anything.  There does appear to be a bug in dm_task_set_cookie(), where
it can fail without cleaning up the cookie.  However, when it does that,
it will always zero out the cookie value before returning, so we will
never be able to clean up the cookie ourselves. Also, like I mentioned,
dm_udev_complete doesn't actually clean up the cookie completely. It
needs to be waited on for that.

I don't think that there is ever a time when we should be calling
dm_udev_complete(). None of the dmsetup cookie handling code does. If we
fail to set the cookie, we should just act like the cookie has been
cleaned up by device-mapper (and we need to make device-mapper actually
do that).  Once we call dm_task_run() after setting a cookie, we should
always call dm_udev_wait(), regardless of the whether or not
dm_task_run() fails. And we should never call dm_task_set_cookie()
cookie in the first place for tasks that will not generate a udev event.
That should make this all work correctly.

-Ben

> 
> Signed-off-by: Hannes Reinecke <hare@suse.com>
> ---
>  libmultipath/devmapper.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
> index 0ae72fc..5396521 100644
> --- a/libmultipath/devmapper.c
> +++ b/libmultipath/devmapper.c
> @@ -1442,8 +1442,10 @@ dm_rename (const char * old, char * new)
>  	dm_task_no_open_count(dmt);
>  
>  	if (!dm_task_set_cookie(dmt, &cookie,
> -				DM_UDEV_DISABLE_LIBRARY_FALLBACK))
> +				DM_UDEV_DISABLE_LIBRARY_FALLBACK)) {
> +		dm_udev_complete(cookie);
>  		goto out;
> +	}
>  	r = dm_task_run(dmt);
>  
>  	if (!r)
> -- 
> 2.6.6

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
Alasdair G Kergon May 6, 2016, 9:59 p.m. UTC | #2
The library functions and return states are supposed to be well-defined.

If you think you've found a cookie leak on an error path within a library
function, we can investigate that and fix the library if need be.

Alasdair

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
Benjamin Marzinski May 6, 2016, 10:45 p.m. UTC | #3
On Fri, May 06, 2016 at 10:59:01PM +0100, Alasdair G Kergon wrote:
> The library functions and return states are supposed to be well-defined.
> 
> If you think you've found a cookie leak on an error path within a library
> function, we can investigate that and fix the library if need be.

In _udev_notify_sem_create(), after dm creates the semaphore and sets
it's value, it calls

semctl(gen_semid, 0, GETVAL) to get the value.  I don't know how likely
this call is to ever fail, but if it does, _udev_notify_sem_create()
sets the cookie pointer to 0, so the caller has no access to the
semaphore, and returns an error, leaving the semaphore to just sit
there.

Conversely, if setting the value fails, dm destroys the semaphore before
returning, so that everything is the same as before the call happened.

There's a similar issue in _udev_notify_sem_inc, but in this case the
cookie is returned along with the error.  However, from the caller's
perspective, the cookie is still in an indeterminate state.

I'll open a bugzilla for it.

-Ben


> 
> Alasdair

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
diff mbox

Patch

diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 0ae72fc..5396521 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -1442,8 +1442,10 @@  dm_rename (const char * old, char * new)
 	dm_task_no_open_count(dmt);
 
 	if (!dm_task_set_cookie(dmt, &cookie,
-				DM_UDEV_DISABLE_LIBRARY_FALLBACK))
+				DM_UDEV_DISABLE_LIBRARY_FALLBACK)) {
+		dm_udev_complete(cookie);
 		goto out;
+	}
 	r = dm_task_run(dmt);
 
 	if (!r)