<font size=2 face="sans-serif">Hello Ben,</font>
<br>
<br><font size=2 face="sans-serif">Yes, </font><tt><font size=2>a *_safe
list traversal method can meet the needs,</font></tt>
<br><tt><font size=2>I will modify it and simplify the codes.</font></tt>
<br>
<br><tt><font size=2>Thanks,</font></tt>
<br><tt><font size=2>Tang Junhui</font></tt>
<br>
<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">tang.wenjun3@zte.com.cn,
zhang.kai16@zte.com.cn, dm-devel@redhat.com, bart.vanassche@sandisk.com,
mwilck@suse.com</font>
<br><font size=1 color=#5f5f5f face="sans-serif">日期:    
    </font><font size=1 face="sans-serif">2017/01/04
08:39</font>
<br><font size=1 color=#5f5f5f face="sans-serif">主题:    
   </font><font size=1 face="sans-serif">Re: [dm-devel]
[PATCH 09/12] multipathd: merge uevents before        proccessing</font>
<br><font size=1 color=#5f5f5f face="sans-serif">发件人:    
   </font><font size=1 face="sans-serif">dm-devel-bounces@redhat.com</font>
<br>
<hr noshade>
<br>
<br>
<br><tt><font size=2>On Tue, Dec 27, 2016 at 04:03:26PM +0800, tang.junhui@zte.com.cn
wrote:<br>
> From: tang.junhui <tang.junhui@zte.com.cn><br>
> <br>
> These uevents are going to be merged:<br>
> 1) uevents come from paths and<br>
> 2) uevents type is same and<br>
> 3) uevents type is addition or deletion and<br>
> 4) uevents wwid is same.<br>
<br>
This is just a nit, and I might be missing something subtle here, but it<br>
seems like instead of adding list_for_some_entry_reverse, and then<br>
breaking the abstraction to manually get previous entries, you could<br>
have just added list_for_some_entry_reverse_safe in your earlier patch,<br>
and hid the work of traversing a list while removing elements behind the<br>
well understood abstraction of a *_safe list traversal method.<br>
<br>
-Ben<br>
<br>
> <br>
> Change-Id: I05ee057391c092aa0c5f989b7a4f9cb550bb4d98<br>
> Signed-off-by: tang.junhui <tang.junhui@zte.com.cn><br>
> ---<br>
>  libmultipath/uevent.c | 125 +++++++++++++++++++++++++++++++++++++++++++++-----<br>
>  1 file changed, 114 insertions(+), 11 deletions(-)<br>
> <br>
> diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c<br>
> index b0b05e9..114068c 100644<br>
> --- a/libmultipath/uevent.c<br>
> +++ b/libmultipath/uevent.c<br>
> @@ -85,6 +85,20 @@ struct uevent * alloc_uevent (void)<br>
>                  
return uev;<br>
>  }<br>
>  <br>
> +void<br>
> +uevq_cleanup(struct list_head *tmpq)<br>
> +{<br>
> +                
struct uevent *uev, *tmp;<br>
> +<br>
> +                
list_for_each_entry_safe(uev, tmp, tmpq, node) {<br>
> +                
                 list_del_init(&uev->node);<br>
> +<br>
> +                
                 if
(uev->udev)<br>
> +                
                 
               
udev_device_unref(uev->udev);<br>
> +                
                 FREE(uev);<br>
> +                
}<br>
> +}<br>
> +<br>
>  bool<br>
>  uevent_can_discard(char *devpath, char *kernel)<br>
>  {<br>
> @@ -125,6 +139,103 @@ uevent_can_discard(char *devpath, char *kernel)<br>
>                  
return false;<br>
>  }<br>
>  <br>
> +bool<br>
> +merge_need_stop(struct uevent *earlier, struct uevent *later)<br>
> +{<br>
> +                
/*<br>
> +                
 * dm uevent do not try to merge with left uevents<br>
> +                
 */<br>
> +                
if (!strncmp(later->kernel, "dm-", 3))<br>
> +                
                 return
true;<br>
> +<br>
> +                
/*<br>
> +                
 * we can not make a jugement without wwid,<br>
> +                
 * so it is sensible to stop merging<br>
> +                
 */<br>
> +                
if (!earlier->wwid || !later->wwid)<br>
> +                
                 return
true;<br>
> +                
/*<br>
> +                
 * uevents merging stoped<br>
> +                
 * when we meet an opposite action uevent from the same LUN to AVOID<br>
> +                
 * "add path1 |remove path1 |add path2 |remove path2 |add path3"<br>
> +                
 * to merge as "remove path1, path2" and "add path1,
path2, path3"<br>
> +                
 * OR<br>
> +                
 * "remove path1 |add path1 |remove path2 |add path2 |remove
path3"<br>
> +                
 * to merge as "add path1, path2" and "remove path1,
path2, path3"<br>
> +                
 * SO<br>
> +                
 * when we meet a non-change uevent from the same LUN<br>
> +                
 * with the same wwid and different action<br>
> +                
 * it would be better to stop merging.<br>
> +                
 */<br>
> +                
if (!strcmp(earlier->wwid, later->wwid) &&<br>
> +                
    strcmp(earlier->action, later->action) &&<br>
> +                
    strcmp(earlier->action, "change") &&<br>
> +                
    strcmp(later->action, "change"))<br>
> +                
                 return
true;<br>
> +<br>
> +                
return false;<br>
> +}<br>
> +<br>
> +bool<br>
> +uevent_can_merge(struct uevent *earlier, struct uevent *later)<br>
> +{<br>
> +                
/* merge paths uevents<br>
> +                
 * whose wwids exsit and are same<br>
> +                
 * and actions are same,<br>
> +                
 * and actions are addition or deletion<br>
> +                
 */<br>
> +                
if (earlier->wwid && later->wwid &&<br>
> +                
    !strcmp(earlier->wwid, later->wwid) &&<br>
> +                
    !strcmp(earlier->action, later->action) &&<br>
> +                
    strncmp(earlier->action, "change", 6) &&<br>
> +                
    strncmp(earlier->kernel, "dm-", 3)) {<br>
> +                
                 return
true;<br>
> +                
}<br>
> +<br>
> +                
return false;<br>
> +}<br>
> +<br>
> +void<br>
> +uevent_merge(struct uevent *later, struct list_head *tmpq)<br>
> +{<br>
> +                
struct uevent *earlier, *temp;<br>
> +                
/*<br>
> +                
 * compare the uevent with earlier uevents<br>
> +                
 */<br>
> +                
list_for_some_entry_reverse(earlier, &later->node, tmpq, node) {<br>
> +next_earlier_node:<br>
> +                
                 if
(merge_need_stop(earlier, later))<br>
> +                
                 
               
break;<br>
> +                
                 /*<br>
> +                
                 
* try to merge earlier uevents to the later uevent<br>
> +                
                 
*/<br>
> +                
                 if
(uevent_can_merge(earlier, later)) {<br>
> +                
                 
               
condlog(3, "merged uevent: %s-%s-%s with uevent: %s-%s-%s",<br>
> +                
                 
               
                 earlier->action,
earlier->kernel, earlier->wwid,<br>
> +                
                 
               
                 later->action,
later->kernel, later->wwid);<br>
> +                
                 
               
temp = earlier;<br>
> +<br>
> +                
                 
               
earlier = list_entry(earlier->node.prev, typeof(struct uevent), node);<br>
> +                
                 
               
list_move(&temp->node, &later->merge_node);<br>
> +<br>
> +                
                 
               
if (earlier ==  list_entry(tmpq, typeof(struct uevent), node))<br>
> +                
                 
               
                 break;<br>
> +                
                 
               
else<br>
> +                
                 
               
                 goto
next_earlier_node;<br>
> +                
                 }<br>
> +                
}<br>
> +}<br>
> +<br>
> +void<br>
> +merge_uevq(struct list_head *tmpq)<br>
> +{<br>
> +                
struct uevent *later;<br>
> +<br>
> +                
list_for_each_entry_reverse(later, tmpq, node) {<br>
> +                
                 uevent_merge(later,
tmpq);<br>
> +                
}<br>
> +}<br>
> +<br>
>  void<br>
>  service_uevq(struct list_head *tmpq)<br>
>  {<br>
> @@ -136,6 +247,8 @@ service_uevq(struct list_head *tmpq)<br>
>                  
                 if
(my_uev_trigger && my_uev_trigger(uev, my_trigger_data))<br>
>                  
                 
               
condlog(0, "uevent trigger error");<br>
>  <br>
> +                
                 uevq_cleanup(&uev->merge_node);<br>
> +<br>
>                  
                 if
(uev->udev)<br>
>                  
                 
               
udev_device_unref(uev->udev);<br>
>                  
                 FREE(uev);<br>
> @@ -150,17 +263,6 @@ static void uevent_cleanup(void *arg)<br>
>                  
udev_unref(udev);<br>
>  }<br>
>  <br>
> -void<br>
> -uevq_cleanup(struct list_head *tmpq)<br>
> -{<br>
> -                
struct uevent *uev, *tmp;<br>
> -<br>
> -                
list_for_each_entry_safe(uev, tmp, tmpq, node) {<br>
> -                
                 list_del_init(&uev->node);<br>
> -                
                 FREE(uev);<br>
> -                
}<br>
> -}<br>
> -<br>
>  /*<br>
>   * Service the uevent queue.<br>
>   */<br>
> @@ -189,6 +291,7 @@ int uevent_dispatch(int (*uev_trigger)(struct
uevent *, void * trigger_data),<br>
>                  
                 pthread_mutex_unlock(uevq_lockp);<br>
>                  
                 if
(!my_uev_trigger)<br>
>                  
                 
               
break;<br>
> +                
                 merge_uevq(&uevq_tmp);<br>
>                  
                 service_uevq(&uevq_tmp);<br>
>                  
}<br>
>                  
condlog(3, "Terminating uev service queue");<br>
> -- <br>
> 2.8.1.windows.1<br>
> <br>
<br>
--<br>
dm-devel mailing list<br>
dm-devel@redhat.com<br>
</font></tt><a href="https://www.redhat.com/mailman/listinfo/dm-devel"><tt><font size=2>https://www.redhat.com/mailman/listinfo/dm-devel</font></tt></a><tt><font size=2><br>
<br>
</font></tt>
<br>