* [PATCH v2 1/2] libmultipath: prevent memory leak in alloc_path_with_pathinfo() if pp_ptr is NULL
@ 2016-12-13 18:27 Mauricio Faria de Oliveira
2016-12-13 18:27 ` [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths Mauricio Faria de Oliveira
0 siblings, 1 reply; 6+ messages in thread
From: Mauricio Faria de Oliveira @ 2016-12-13 18:27 UTC (permalink / raw)
To: dm-devel, bmarzins, christophe.varoqui
In alloc_path_with_pathinfo(), if the 'pp_ptr' argument is NULL
(which is acceptable and checked in the function in two places)
the 'pp' pointer is lost as it is not referenced anywhere else;
thus the memory allocated for it is leaked.
So, call free_path() in the case 'pp_ptr' is NULL too.
Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
---
libmultipath/discovery.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 7b5b4344b2a1..3c5c808436b2 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -58,7 +58,7 @@ alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
err = pathinfo(pp, conf, flag | DI_BLACKLIST);
}
- if (err)
+ if (err || !pp_ptr)
free_path(pp);
else if (pp_ptr)
*pp_ptr = pp;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths
2016-12-13 18:27 [PATCH v2 1/2] libmultipath: prevent memory leak in alloc_path_with_pathinfo() if pp_ptr is NULL Mauricio Faria de Oliveira
@ 2016-12-13 18:27 ` Mauricio Faria de Oliveira
2016-12-13 21:50 ` Benjamin Marzinski
0 siblings, 1 reply; 6+ messages in thread
From: Mauricio Faria de Oliveira @ 2016-12-13 18:27 UTC (permalink / raw)
To: dm-devel, bmarzins, christophe.varoqui
Currently, multipath still prints the 'spurious uevent, path not found'
message if a path is blacklisted by something different than a devnode
in the 'change' uevent handling. (uev_trigger() calls filter_devnode()).
Thus blacklisting by vendor/product, wwid, and udev property still get
that message in the system log for paths that are explicitly marked to
be ignored (since it's verbosity level 0).
This problem happens on common scenarios such as creating filesystems
on a blacklisted device (e.g., mkfs.* /dev/sdX), which is usually run
several times on test environments, and the error message may mislead
the error checker/monitor tools with false negatives.
This patch resolves this by checking the udev property and path_info()
for PATHINFO_SKIPPED with just enough device information flags for
blacklist verification -- and it prints a debug message (verbosity
level 3) instead of an error message since this case is not an error.
Even though this introduces a bit of overhead (to get the path info),
it only happens in a corner case of an error path; so, not a problem.
Test-cases (on QEMU):
----------
Several versions of /etc/multipath.conf:
blacklist {
devnode "sdb"
}
blacklist {
property "ID_SERIAL"
}
blacklist {
wwid "0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-1"
}
blacklist {
device {
vendor "QEMU"
}
}
Either command can be used to generate a 'change' uevent:
# echo change > /sys/block/sdb/uevent
# mkfs.ext3 -F /dev/sdb
The output of multipathd is monitored with:
# multipathd -d -s
...
Without the patch, only the devnode blacklisting is silent;
all other cases (property, wwid, device) print the message:
sdb: spurious uevent, path not found
With the patch applied, no message is printed by default
(that is, verbosity level 2) in any case.
With verbosity level 3 (debug), the following messages
are printed, according to the performed test-case:
sdb: udev property ID_SERIAL blacklisted
sdb: spurious uevent, path is blacklisted
sdb: wwid 0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-1 blacklisted
sdb: spurious uevent, path is blacklisted
(null): (QEMU:QEMU HARDDISK) vendor/product blacklisted
sdb: spurious uevent, path is blacklisted
Reported-by: Yueh Chyong (Ida) Jackson <idaj@us.ibm.com>
Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
---
multipathd/main.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index d6f081f2f83a..dd7e8d69491e 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1010,8 +1010,38 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
}
out:
lock_cleanup_pop(vecs->lock);
- if (!pp)
+ if (!pp) {
+ /*
+ * If the path is blacklisted, print a debug/non-default verbosity message.
+ * - filter_devnode() - checked by uev_trigger() (caller);
+ * - filter_device() - checked by pathinfo() (DI_BLACKLIST | DI_SYSFS);
+ * - filter_wwid() - checked by pathinfo() (DI_BLACKLIST | DI_WWID);
+ * - filter_property() - checked here).
+ */
+ if (uev->udev) {
+ int flag = DI_SYSFS | DI_WWID;
+ struct udev_device *udevice;
+
+ udevice = udev_device_ref(uev->udev);
+
+ if (filter_property(conf, udevice) > 0)
+ retval = PATHINFO_SKIPPED;
+ else {
+ conf = get_multipath_config();
+ retval = alloc_path_with_pathinfo(conf, udevice, flag, NULL);
+ put_multipath_config(conf);
+ }
+
+ udev_device_unref(uev->udev);
+
+ if (retval == PATHINFO_SKIPPED) {
+ condlog(3, "%s: spurious uevent, path is blacklisted", uev->kernel);
+ return 0;
+ }
+ }
+
condlog(0, "%s: spurious uevent, path not found", uev->kernel);
+ }
return retval;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths
2016-12-13 18:27 ` [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths Mauricio Faria de Oliveira
@ 2016-12-13 21:50 ` Benjamin Marzinski
2016-12-13 23:53 ` Mauricio Faria de Oliveira
2016-12-14 12:53 ` Martin Wilck
0 siblings, 2 replies; 6+ messages in thread
From: Benjamin Marzinski @ 2016-12-13 21:50 UTC (permalink / raw)
To: Mauricio Faria de Oliveira; +Cc: dm-devel
On Tue, Dec 13, 2016 at 04:27:09PM -0200, Mauricio Faria de Oliveira wrote:
Thanks for working on this. I like this version much better, but I still
have some issues. First off, I don't see why the udev_device_ref/unref
is necessary. While servicing uevents, when we first get the udevice
from udev_monitor_receive_device() in uevent_listen() it comes with a
reference. After we finish servicing the uevent, we drop this reference
in service_uevq(). If we attach this udevice to a path (by setting
pp->udev), we need to get another reference, so that the udevice isn't
deleted when we drop the reference after servicing the event in
service_uevq(). Otherwise pp->udev would be pointing to freed memory.
We drop this reference when we free the path in free_path().
When you call alloc_path_with_pathinfo(), it already grabs the second
reference before calling pathinfo. When it exits without pp_ptr being
set, it frees that extra reference in free_path(). But this whole time,
we are still servicing the uevent, and that originl reference is always
held, so we don't ever need to worry about the udevice getting deleted
out from under us. I don't see any possible danger in removing the
udev_device_ref/unref calls from your code. They don't hurt anything,
but grabbing references when we don't need them just confuses other
people who are trying reading the code, and makes the purpose of the
references harder to understand.
My second issue is more for Hannes. Is there a reason why we don't check
filter_property in pathinfo if we call it with (DI_BLACKLIST | DI_WWID).
If we have the information to get the WWID, then we have the information
to check filter_property. Looking at the code, I don't see how we could
be checking filter_property for paths added via uev_add_path. Am I
missing something subtle here, or should we just add a filter_property()
check to pathinfo()?
-Ben
> Reported-by: Yueh Chyong (Ida) Jackson <idaj@us.ibm.com>
> Signed-off-by: Mauricio Faria de Oliveira <mauricfo@linux.vnet.ibm.com>
> ---
> multipathd/main.c | 32 +++++++++++++++++++++++++++++++-
> 1 file changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/multipathd/main.c b/multipathd/main.c
> index d6f081f2f83a..dd7e8d69491e 100644
> --- a/multipathd/main.c
> +++ b/multipathd/main.c
> @@ -1010,8 +1010,38 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
> }
> out:
> lock_cleanup_pop(vecs->lock);
> - if (!pp)
> + if (!pp) {
> + /*
> + * If the path is blacklisted, print a debug/non-default verbosity message.
> + * - filter_devnode() - checked by uev_trigger() (caller);
> + * - filter_device() - checked by pathinfo() (DI_BLACKLIST | DI_SYSFS);
> + * - filter_wwid() - checked by pathinfo() (DI_BLACKLIST | DI_WWID);
> + * - filter_property() - checked here).
> + */
> + if (uev->udev) {
> + int flag = DI_SYSFS | DI_WWID;
> + struct udev_device *udevice;
> +
> + udevice = udev_device_ref(uev->udev);
> +
> + if (filter_property(conf, udevice) > 0)
> + retval = PATHINFO_SKIPPED;
> + else {
> + conf = get_multipath_config();
> + retval = alloc_path_with_pathinfo(conf, udevice, flag, NULL);
> + put_multipath_config(conf);
> + }
> +
> + udev_device_unref(uev->udev);
> +
> + if (retval == PATHINFO_SKIPPED) {
> + condlog(3, "%s: spurious uevent, path is blacklisted", uev->kernel);
> + return 0;
> + }
> + }
> +
> condlog(0, "%s: spurious uevent, path not found", uev->kernel);
> + }
>
> return retval;
> }
> --
> 1.8.3.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths
2016-12-13 21:50 ` Benjamin Marzinski
@ 2016-12-13 23:53 ` Mauricio Faria de Oliveira
2016-12-14 12:53 ` Martin Wilck
1 sibling, 0 replies; 6+ messages in thread
From: Mauricio Faria de Oliveira @ 2016-12-13 23:53 UTC (permalink / raw)
To: Benjamin Marzinski; +Cc: dm-devel
Ben,
On 12/13/2016 07:50 PM, Benjamin Marzinski wrote:
> [snip] I don't see why the udev_device_ref/unref
> is necessary. While servicing uevents, when we first get the udevice
> from udev_monitor_receive_device() in uevent_listen() it comes with a
> reference. After we finish servicing the uevent, we drop this reference
> in service_uevq(). [snip]
Oh, cool. Thanks for the detailed explanation. I hadn't realized about
that first reference. I'll remove the udev_device_ref/unref() in v3.
> My second issue is more for Hannes. Is there a reason why we don't check
> filter_property in pathinfo if we call it with (DI_BLACKLIST | DI_WWID).
> If we have the information to get the WWID, then we have the information
> to check filter_property. [snip]
If I may, I'm not sure that filter_property() has to do w/ DI_WWID.
iiuic, it just checks the /name/ of each udev property of udev_device
against the blacklist/blacklist-exceptions entries for property names
in the conf struct (i.e., it doesn't need the path wwid).
And that information about the udev_device is available upfront,
even before we call pathinfo() (BTW, I guess this is the reason
why it's not called from within it, but rather at a point in
path_discover() that only the udev_device is available, like
filter_devnode() too.)
> [snip] Looking at the code, I don't see how we could
> be checking filter_property for paths added via uev_add_path. Am I
> missing something subtle here, or should we just add a filter_property()
> check to pathinfo()?
You're correct. If a path is added via uev_add_path() it ignores
the property blacklisting, and end up creating/joining a devmap.
It seems like an unhandled case.
So, I'll submit a v3 w/ your suggestion for this too.
Thanks!
Simple test case w/ change/add uevents:
# cat /etc/multipath.conf
blacklist {
property "ID_SERIAL"
}
# multipathd -d -s -v3 &
...
# echo change > /sys/block/sdb/uevent
uevent 'change' from '/devices/vio/2000/host0/target0:0:0/0:0:0:1/block/sdb'
Forwarding 1 uevents
sdb: udev property ID_SERIAL blacklisted
sdb: spurious uevent, path is blacklisted
# echo add > /sys/block/sdb/uevent
uevent 'add' from '/devices/vio/2000/host0/target0:0:0/0:0:0:1/block/sdb'
Forwarding 1 uevents
sdb: add path (uevent)
...
0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-1: load table [0 4194304 multipath 1
retain_attached_hw_handler 0 1 1 service-time 0 1 1 8:16 1]
...
sdb [8:16]: path added to devmap 0QEMU_QEMU_HARDDISK_drive-scsi0-0-0-1
--
Mauricio Faria de Oliveira
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths
2016-12-13 21:50 ` Benjamin Marzinski
2016-12-13 23:53 ` Mauricio Faria de Oliveira
@ 2016-12-14 12:53 ` Martin Wilck
2016-12-20 17:00 ` Benjamin Marzinski
1 sibling, 1 reply; 6+ messages in thread
From: Martin Wilck @ 2016-12-14 12:53 UTC (permalink / raw)
To: dm-devel
On Tue, 2016-12-13 at 15:50 -0600, Benjamin Marzinski wrote:
> On Tue, Dec 13, 2016 at 04:27:09PM -0200, Mauricio Faria de Oliveira
> wrote:
> When you call alloc_path_with_pathinfo(), it already grabs the second
> reference before calling pathinfo. When it exits without pp_ptr being
> set, it frees that extra reference in free_path(). But this whole
> time,
> we are still servicing the uevent, and that originl reference is
> always
> held, so we don't ever need to worry about the udevice getting
> deleted
> out from under us. I don't see any possible danger in removing the
> udev_device_ref/unref calls from your code. They don't hurt anything,
> but grabbing references when we don't need them just confuses other
> people who are trying reading the code, and makes the purpose of the
> references harder to understand.
As someone who has just recently started reading the multipath-tools
code in depth, I tend to disagree. Someone reading the function
including the udev_device_ref()/unref() calls would see that the device
references are handled correctly in the function itself, without having
to know or having to track down how the device references are created
and dropped in other parts of the code. Moreover, if the global ref
handling was ever to be changed in the future, this function would
still be "safe".
If the udev_device_ref/unref calls are removed, at least a comment
explaining why they aren't needed would help new readers of the code.
Regards
Martin
--
Dr. Martin Wilck <mwilck@suse.com>, Tel. +49 (0)911 74053 2107
SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths
2016-12-14 12:53 ` Martin Wilck
@ 2016-12-20 17:00 ` Benjamin Marzinski
0 siblings, 0 replies; 6+ messages in thread
From: Benjamin Marzinski @ 2016-12-20 17:00 UTC (permalink / raw)
To: Martin Wilck; +Cc: dm-devel
On Wed, Dec 14, 2016 at 01:53:09PM +0100, Martin Wilck wrote:
> On Tue, 2016-12-13 at 15:50 -0600, Benjamin Marzinski wrote:
>
> > On Tue, Dec 13, 2016 at 04:27:09PM -0200, Mauricio Faria de Oliveira
> > wrote:
> > When you call alloc_path_with_pathinfo(), it already grabs the second
> > reference before calling pathinfo. When it exits without pp_ptr being
> > set, it frees that extra reference in free_path(). But this whole
> > time,
> > we are still servicing the uevent, and that originl reference is
> > always
> > held, so we don't ever need to worry about the udevice getting
> > deleted
> > out from under us. I don't see any possible danger in removing the
> > udev_device_ref/unref calls from your code. They don't hurt anything,
> > but grabbing references when we don't need them just confuses other
> > people who are trying reading the code, and makes the purpose of the
> > references harder to understand.
>
> As someone who has just recently started reading the multipath-tools
> code in depth, I tend to disagree. Someone reading the function
> including the udev_device_ref()/unref() calls would see that the device
> references are handled correctly in the function itself, without having
> to know or having to track down how the device references are created
> and dropped in other parts of the code. Moreover, if the global ref
> handling was ever to be changed in the future, this function would
> still be "safe".
I would argue that you don't need to track down these reference. Since
uev_update_path is accessing the device, you can assume that it has a
reference (otherwise it would be accessing memory that could be freed at
any moment, and may already be freed). If the code you add doesn't drop
that reference, then it is clearly able to acces the udev device,
without worrying about the memory going away. If the code you add DOES
drop a reference, then you really DO need to track down the ref/unref
calls, because otherwise, you could be breaking things. For instance, if
this patch dropped a reference between those ref/unref calls, that would
break multipathd. After the unref call, the memory could now be freed,
where before, uev_update_path returned with the reference still held.
The only time you ever need to grab a another reference is if your code
stores the udev device, so that it can exist after multipathd finishes
processing the uevent. When your code finally is done with the udev
device, it needs to drop the reference, so the the memory can get freed.
No matter how global ref handling is changed in the future,
uev_update_path will still need to be called with a reference to the
udev device, because it accesses it. So as long as it doesn't store the
device, it doesn't need to grab another reference.
> If the udev_device_ref/unref calls are removed, at least a comment
> explaining why they aren't needed would help new readers of the code.
But then why not comment all the functions that access the udev device,
since most of them don't grab a reference (nor do they need to). If
we're going to comment the code, I'd rather put comments in the small
number of places where we do need to grab or drop extra references,
explaining why it is necessary there.
-Ben
> Regards
> Martin
>
> --
> Dr. Martin Wilck <mwilck@suse.com>, Tel. +49 (0)911 74053 2107
> SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton
> HRB 21284 (AG Nürnberg)
>
> --
> dm-devel mailing list
> dm-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2016-12-20 17:00 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-13 18:27 [PATCH v2 1/2] libmultipath: prevent memory leak in alloc_path_with_pathinfo() if pp_ptr is NULL Mauricio Faria de Oliveira
2016-12-13 18:27 ` [PATCH v2 2/2] multipathd: skip spurious event message for blacklisted paths Mauricio Faria de Oliveira
2016-12-13 21:50 ` Benjamin Marzinski
2016-12-13 23:53 ` Mauricio Faria de Oliveira
2016-12-14 12:53 ` Martin Wilck
2016-12-20 17:00 ` Benjamin Marzinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.