<font size=3>Hello Ben</font>
<br>
<br><font size=3>Thank you for your patience again.</font>
<br>
<br><font size=3>I'll modify code according to your suggestion as this:</font>
<br><font size=3>1) add configuration in the defaults section</font>
<br><font size=3>   uid_attrs "sd:ID_SERIAL dasd:ID_UID"</font>
<br><font size=3>   it would override any other configurations
if this </font>
<br><font size=3>   filed is configured and matched;</font>
<br>
<br><font size=3>2) In uevent processing thread, we will assign merge_id
</font>
<br><font size=3>   according the label in uevents by this configuration;</font>
<br>
<br><font size=3>3) this patch will take back:</font>
<br><font size=3>   [PATCH 12/12] libmultipath: use existing
wwid when</font>
<br><font size=3>   wwid has already been existed in uevent</font>
<br>
<br><font size=3>4) if this field is not configured, only do filtering
and </font>
<br><font size=3>   no merging works.</font>
<br>
<br><font size=3>Please confirm whether this modification is feasible.</font>
<br>
<br><font size=3>Regards,</font>
<br><font size=3>Tang Junhui</font>
<br>
<br>
<br>
<br><font size=1 color=#5f5f5f face="sans-serif">发件人:    
    </font><font size=1 face="sans-serif">"Benjamin
Marzinski" <bmarzins@redhat.com></font>
<br><font size=1 color=#5f5f5f face="sans-serif">收件人:    
    </font><font size=1 face="sans-serif">tang.junhui@zte.com.cn,
</font>
<br><font size=1 color=#5f5f5f face="sans-serif">抄送:    
   </font><font size=1 face="sans-serif">christophe.varoqui@opensvc.com,
hare@suse.de, mwilck@suse.com, bart.vanassche@sandisk.com, dm-devel@redhat.com,
zhang.kai16@zte.com.cn, tang.wenjun3@zte.com.cn</font>
<br><font size=1 color=#5f5f5f face="sans-serif">日期:    
    </font><font size=1 face="sans-serif">2017/01/17
05:38</font>
<br><font size=1 color=#5f5f5f face="sans-serif">主题:    
   </font><font size=1 face="sans-serif">Re: [PATCH 04/11]
multipathd: add need_do_map to indicate whether need calling domap() in
ev_add_path()</font>
<br>
<hr noshade>
<br>
<br>
<br><tt><font size=2>On Thu, Jan 12, 2017 at 01:52:20PM +0800, tang.junhui@zte.com.cn
wrote:<br>
> From: tang.junhui <tang.junhui@zte.com.cn><br>
> <br>
> Usually calling domap() in ev_add_path() is needed, but only last
path<br>
> need to call domap() in processing for merged uevents to reduce the<br>
> count of calling domap() and promote efficiency. So add input parameter<br>
> need_do_map to indicate whether need calling domap() in ev_add_path().<br>
<br>
With the addition of checking if the merge_id equals the wwid, you are<br>
protected against accidentially merging paths that shouldn't be merged,<br>
which is great.  But setting need_do_map for these paths doesn't<br>
completely make sure that if the wwid and merge_id differ, you will<br>
always call domap.<br>
<br>
A contrived situation where this fails would look like:<br>
<br>
add path1, path2, path3<br>
<br>
where merge_id equals the wwid for path1 and path2, but there is a<br>
different wwid for path3.  In this case, you would call domap on just<br>
the multipath device for path3, but since path1 and path2 matched the<br>
merge_id, they wouldn't force a call to domap.<br>
<br>
A less contrived example would be<br>
<br>
add path1, path2, path3, path4<br>
<br>
Where these were devices that were actually pointing at two different<br>
LUNs, but all set ID_SERIAL the same. path1 and path2 pointed to one<br>
LUN, while path3 and path4 pointed to another LUN.  In this case the<br>
wwid of path1 and path2 matched the merge_id, while the wwid of path3<br>
and path4 was different. In this case you would call domap twice, on<br>
both path3 and path4, but nothing would call domap to create a multipath<br>
device for path1 and path2.<br>
<br>
In general, the code to set need_do_map if the wwid and merge_id don't<br>
match only works if either none of the device in a merged set have wwids<br>
that match the merge_id, or if the last device has a wwid that matches<br>
the merge_id. If there are devices with wwids that match the merge_id,<br>
but the last device in the set isn't one of them, then some devices will<br>
not get a multipath device created for them.<br>
<br>
Now, I don't know of any device that works like my above example, so<br>
your code will likely work fine for all real-world devices.  Also,<br>
fixing this is a pain, as you don't find out until processing the last<br>
path in a set that things went wrong, and then you would have to go back<br>
and run the skipped functions on one of the paths you have already<br>
processed.<br>
<br>
The easy way to fix it is to use the other possibility that I mentioned<br>
before, which is to not have the merge_id, and just use the udev<br>
provided wwid, instead of fetching it from pathinfo.  Like I mentioned,<br>
if you do this, you want to make sure that you only try to grab the wwid<br>
from the udev events for devices with the correct kernel name: ID_SERIAL<br>
only for "sd.*" devices, and ID_UID only for "dasd.*"
devices. I also<br>
think that this should be configurable.<br>
<br>
Otherwise, you can either go through the messy work of calling domap<br>
correctly when the last device of a set has a wwid that doesn't match<br>
the merge_id, or we can decide that this won't acutally cause problems<br>
with any known device, and punt fixing it for now. And if it causes<br>
problems with some future devices, we can deal with it then.<br>
<br>
-Ben<br>
<br>
> <br>
> Change-Id: I7f33de49a1d89d91180dcb95cd94e4944ae7ff36<br>
> Signed-off-by: tang.wenjun <tang.wenjun3@zte.com.cn><br>
> ---<br>
>  multipathd/cli_handlers.c |  3 ++-<br>
>  multipathd/main.c         | 47 ++++++++++++++++++++++++++++++++++++-----------<br>
>  multipathd/main.h         |  2 +-<br>
>  3 files changed, 39 insertions(+), 13 deletions(-)<br>
> <br>
> diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c<br>
> index b0eeca6..3a46c09 100644<br>
> --- a/multipathd/cli_handlers.c<br>
> +++ b/multipathd/cli_handlers.c<br>
> @@ -670,7 +670,8 @@ cli_add_path (void * v, char ** reply, int * len,
void * data)<br>
>                  
                 pp->checkint
= conf->checkint;<br>
>                  
}<br>
>                  
put_multipath_config(conf);<br>
> -                
return ev_add_path(pp, vecs);<br>
> +                
return ev_add_path(pp, vecs, 1);<br>
> +<br>
>  blacklisted:<br>
>                  
*reply = strdup("blacklisted\n");<br>
>                  
*len = strlen(*reply) + 1;<br>
> diff --git a/multipathd/main.c b/multipathd/main.c<br>
> index adc3258..ebd7de1 100644<br>
> --- a/multipathd/main.c<br>
> +++ b/multipathd/main.c<br>
> @@ -608,7 +608,7 @@ ev_remove_map (char * devname, char * alias, int
minor, struct vectors * vecs)<br>
>  }<br>
>  <br>
>  static int<br>
> -uev_add_path (struct uevent *uev, struct vectors * vecs)<br>
> +uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map)<br>
>  {<br>
>                  
struct path *pp;<br>
>                  
int ret = 0, i;<br>
> @@ -640,9 +640,18 @@ uev_add_path (struct uevent *uev, struct vectors
* vecs)<br>
>                  
                 
               
r = pathinfo(pp, conf,<br>
>                  
                 
               
                 
    DI_ALL | DI_BLACKLIST);<br>
>                  
                 
               
put_multipath_config(conf);<br>
> -                
                 
               
if (r == PATHINFO_OK)<br>
> -                
                 
               
                 ret
= ev_add_path(pp, vecs);<br>
> -                
                 
               
else if (r == PATHINFO_SKIPPED) {<br>
> +                
                 
               
if (r == PATHINFO_OK) {<br>
> +                
                 
               
                 /*<br>
> +                
                 
               
                 
* Make sure merging use the correct wwid<br>
> +                
                 
               
                 
* Othterwise calling domap()<br>
> +                
                 
               
                 
*/<br>
> +                
                 
               
                 if
(!need_do_map &&<br>
> +                
                 
               
                 
   uev->merge_id &&<br>
> +                
                 
               
                 
   strcmp(uev->merge_id, pp->wwid))<br>
> +                
                 
               
                 
               
need_do_map = 1;<br>
> +<br>
> +                
                 
               
                 ret
= ev_add_path(pp, vecs, need_do_map);<br>
> +                
                 
               
} else if (r == PATHINFO_SKIPPED) {<br>
>                  
                 
               
                 condlog(3,
"%s: remove blacklisted path",<br>
>                  
                 
               
                 
               
uev->kernel);<br>
>                  
                 
               
                 i
= find_slot(vecs->pathvec, (void *)pp);<br>
> @@ -681,7 +690,16 @@ uev_add_path (struct uevent *uev, struct vectors
* vecs)<br>
>                  
                 conf
= get_multipath_config();<br>
>                  
                 pp->checkint
= conf->checkint;<br>
>                  
                 put_multipath_config(conf);<br>
> -                
                 ret
= ev_add_path(pp, vecs);<br>
> +                
                 /*<br>
> +                
                 
* Make sure merging use the correct wwid<br>
> +                
                 
* Othterwise calling domap()<br>
> +                
                 
*/<br>
> +                
                 if
(!need_do_map &&<br>
> +                
                 
   uev->merge_id &&<br>
> +                
                 
   strcmp(uev->merge_id, pp->wwid))<br>
> +                
                 
               
need_do_map = 1;<br>
> +<br>
> +                
                 ret
= ev_add_path(pp, vecs, need_do_map);<br>
>                  
} else {<br>
>                  
                 condlog(0,
"%s: failed to store path info, "<br>
>                  
                 
               
"dropping event",<br>
> @@ -699,7 +717,7 @@ uev_add_path (struct uevent *uev, struct vectors
* vecs)<br>
>   * 1: error<br>
>   */<br>
>  int<br>
> -ev_add_path (struct path * pp, struct vectors * vecs)<br>
> +ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)<br>
>  {<br>
>                  
struct multipath * mpp;<br>
>                  
char params[PARAMS_SIZE] = {0};<br>
> @@ -767,6 +785,13 @@ rescan:<br>
>                  
/* persistent reservation check*/<br>
>                  
mpath_pr_event_handle(pp);<br>
>  <br>
> +                
if (!need_do_map)<br>
> +                
                 return
0;<br>
> +<br>
> +                
if (!dm_map_present(mpp->alias)) {<br>
> +                
                 mpp->action
= ACT_CREATE;<br>
> +                
                 start_waiter
= 1;<br>
> +                
}<br>
>                  
/*<br>
>                  
 * push the map to the device-mapper<br>
>                  
 */<br>
> @@ -995,7 +1020,7 @@ uev_update_path (struct uevent *uev, struct vectors
* vecs)<br>
>                  
                 }<br>
>  <br>
>                  
                 if
(pp->initialized == INIT_REQUESTED_UDEV)<br>
> -                
                 
               
retval = uev_add_path(uev, vecs);<br>
> +                
                 
               
retval = uev_add_path(uev, vecs, 1);<br>
>                  
                 else
if (mpp && ro >= 0) {<br>
>                  
                 
               
condlog(2, "%s: update path write_protect to '%d' (uevent)",
uev->kernel, ro);<br>
>  <br>
> @@ -1150,7 +1175,7 @@ uev_trigger (struct uevent * uev, void * trigger_data)<br>
>                  
put_multipath_config(conf);<br>
>  <br>
>                  
if (!strncmp(uev->action, "add", 3)) {<br>
> -                
                 r
= uev_add_path(uev, vecs);<br>
> +                
                 r
= uev_add_path(uev, vecs, 1);<br>
>                  
                 goto
out;<br>
>                  
}<br>
>                  
if (!strncmp(uev->action, "remove", 6)) {<br>
> @@ -1570,7 +1595,7 @@ check_path (struct vectors * vecs, struct path
* pp, int ticks)<br>
>                  
                 
               
conf = get_multipath_config();<br>
>                  
                 
               
ret = pathinfo(pp, conf, DI_ALL | DI_BLACKLIST);<br>
>                  
                 
               
if (ret == PATHINFO_OK) {<br>
> -                
                 
               
                 ev_add_path(pp,
vecs);<br>
> +                
                 
               
                 ev_add_path(pp,
vecs, 1);<br>
>                  
                 
               
                 pp->tick
= 1;<br>
>                  
                 
               
} else if (ret == PATHINFO_SKIPPED) {<br>
>                  
                 
               
                 put_multipath_config(conf);<br>
> @@ -1686,7 +1711,7 @@ check_path (struct vectors * vecs, struct path
* pp, int ticks)<br>
>                  
                 }<br>
>                  
                 if
(!disable_reinstate && reinstate_path(pp, add_active)) {<br>
>                  
                 
               
condlog(3, "%s: reload map", pp->dev);<br>
> -                
                 
               
ev_add_path(pp, vecs);<br>
> +                
                 
               
ev_add_path(pp, vecs, 1);<br>
>                  
                 
               
pp->tick = 1;<br>
>                  
                 
               
return 0;<br>
>                  
                 }<br>
> @@ -1709,7 +1734,7 @@ check_path (struct vectors * vecs, struct path
* pp, int ticks)<br>
>                  
                 
               
/* Clear IO errors */<br>
>                  
                 
               
if (reinstate_path(pp, 0)) {<br>
>                  
                 
               
                 condlog(3,
"%s: reload map", pp->dev);<br>
> -                
                 
               
                 ev_add_path(pp,
vecs);<br>
> +                
                 
               
                 ev_add_path(pp,
vecs, 1);<br>
>                  
                 
               
                 pp->tick
= 1;<br>
>                  
                 
               
                 return
0;<br>
>                  
                 
               
}<br>
> diff --git a/multipathd/main.h b/multipathd/main.h<br>
> index f72580d..f810d41 100644<br>
> --- a/multipathd/main.h<br>
> +++ b/multipathd/main.h<br>
> @@ -22,7 +22,7 @@ void exit_daemon(void);<br>
>  const char * daemon_status(void);<br>
>  int need_to_delay_reconfig (struct vectors *);<br>
>  int reconfigure (struct vectors *);<br>
> -int ev_add_path (struct path *, struct vectors *);<br>
> +int ev_add_path (struct path *, struct vectors *, int);<br>
>  int ev_remove_path (struct path *, struct vectors *);<br>
>  int ev_add_map (char *, char *, struct vectors *);<br>
>  int ev_remove_map (char *, char *, int, struct vectors *);<br>
> -- <br>
> 2.8.1.windows.1<br>
> <br>
</font></tt>
<br>