<div class="zcontentRow"> <p>Hello <span style="line-height: 21px;">Martin,</span></p><p><span style="line-height: 21px;"><br></span></p><p><span style="line-height: 21px;">Thanks for your responsible,</span></p><p><span style="line-height: 21px;"><br></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span>I'd like the following better for this check. It uses much less cycles.</span><br style="white-space: normal;"><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span> static bool</span><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span>can_discard_by_devpath(const char *devpath)</span></span></p><p><span style="line-height: 21px;"><br></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span>This would be better readable and faster if you'd put the "kernel"</span><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span>tests first so that you need to check only "action" later:</span><br style="white-space: normal;"><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">> </span>    if (!strncmp(later->kernel, "dm-", 3) ||</span><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">></span>        strcmp(earlier->kernel, later->kernel))</span><br style="white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">></span>        return false;</span></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;"><br></span></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;">Yes, I think these codes can be reworked, but since they have no logical</span></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;">effect, </span></span><span style="line-height: 21px;">and this patch takes too long time, can you commit a </span><span style="line-height: 21px;">new patch </span></p><p><span style="line-height: 21px;">to rework </span><span style="line-height: 21px;">these codes?</span></p><p><br></p><p>> The first case should have been reduced to "remove path1 | remove path2<br></p><p>> | add path3" by filtering beforehand. I suppose you want to avoid this</p><p>> sequence because it could leave us without paths temporarily, causing</p><p>> multipathd to destroy the map. But I don't understand what "stop</p><p>> merging" buys you here - if you process the events one-by-one, you may</p><p>> also have 0 paths at some point. </p><p>> </p><p>> In the second case, we know all events in the sequence have the same</p><p>> WWID; in this case I think it would be safe to filter away "remove"</p><p>> events by subsequent "add" events, ending up with "add path1| add</p><p>> path2| remove path3". But I may be overlooking something here.</p><p><br></p><p>> The dangerous thing if you have simultaneous remove and add events for</p><p>> the same LUN is that processing the "add" events is likely to fail in</p><p>> domap(). If you get "add path1 | remove path2", once you process "add</p><p>> path1", "path2" may not exist in the kernel any more, and "domap" will</p><p>> fail if you try to set up both; you may end up removing the map</p><p>> completely. IMHO the only safe way to process events in this situation</p><p>> is to merge the events into a single domap() call.</p><p><br></p><p><span style="line-height: 21px;">"case 2: </span><span style="line-height: 21px;">remove path1 |add path1 |remove path2 |add path2 |remove path3"</span></p><p>Since the mergering is starting from the latest to the eariest uevent,  so the</p><p>uevent <span style="line-height: 21px;">"</span><span style="line-height: 21px;">remove path3</span><span style="line-height: 21px;">" try to merger other uevents, if we do not stop mergering, </span></p><p><span style="line-height: 21px;"></span></p><p style="line-height: 21px; white-space: normal;">uevent <span style="line-height: 21px;">"<span style="line-height: 21px;">remove path3</span>" would merge  uevent "<span style="line-height: 21px;"><span style="line-height: 21px;">remove </span>path2" and <span style="line-height: 21px;">uevent </span></span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">"</span><span style="line-height: 21px;"><span style="line-height: 21px;">remove </span>path1". </span></span></span><span style="line-height: 21px;">Uevent "</span><span style="line-height: 21px;"><span style="line-height: 21px;">add  </span>path2" would merge "<span style="line-height: 21px;"><span style="line-height: 21px;">add  </span>path1". </span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;">The result is that we </span></span><span style="line-height: 21px;">get two merged uevents:</span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">1)</span><span style="line-height: 21px;"> add </span><span style="line-height: 21px;">path2, <span style="line-height: 21px;">path1</span></span></span></span></span></span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">2) <span style="line-height: 21px;">remove <span style="line-height: 21px;">path3, </span>path2, path1 </span></span></span></span></span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">Then we process the merged uevents from the earlier to later, We try to ”<span style="line-height: 21px;"><span style="line-height: 21px;">add </span></span></span></span></span></span></span></span></span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">path2 </span></span></span></span></span></span></span></span></span><span style="line-height: 21px;">path1“, and we would create or reload a map device with path1 and path2. </span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;">Next we </span><span style="line-height: 21px;">process ”</span><span style="line-height: 21px;"></span><span style="line-height: 21px;"> </span><span style="line-height: 21px;">remove <span style="line-height: 21px;">path3, </span>path2, path1</span><span style="line-height: 21px;"><span style="line-height: 21px;"><span style="line-height: 21px;">“, so path1, path2 and path3 are </span></span></span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;">all removed from the map device, this is wrong,  the correct result is that the path1</span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;">and path2 should be still in the map device.</span></p><p style="line-height: 21px; white-space: normal;"><span style="line-height: 21px;"><br></span></p><p style="line-height: 21px; white-space: normal;">Just as you say, this patch is just a shape, we need more testing, and maybe </p><p style="line-height: 21px; white-space: normal;">more <span style="line-height: 21px;">patches are needed to make it better.</span></p><p style="line-height: 21px; white-space: normal;"><br></p><p style="line-height: 21px; white-space: normal;">Thank you,</p><p style="line-height: 21px; white-space: normal;">Tang Junhui</p><p><span style="line-height: 21px;"><br></span><br></p><p><br></p><p><span style="line-height: 21px;"><br></span></p><p><span style="line-height: 21px;"></span><br></p><p><span style="line-height: 21px;"><span style="line-height: 21px;"><br></span></span></p><p><span style="line-height: 21px;"><span style="line-height: 21px;"> </span></span></p><p><br></p><p><br></p><p><br></p><p><br></p><div><div class="zhistoryRow" style="display:block"><div class="zhistoryDes" style="width: 100%; height: 28px; line-height: 28px; background-color: #E0E5E9; color: #1388FF; text-align: center;" language-data="HistoryOrgTxt">原始邮件</div><div id="zwriteHistoryContainer"><div class="control-group zhistoryPanel"><div class="zhistoryHeader" style="padding: 8px; background-color: #F5F6F8;"><div><strong language-data="HistorySenderTxt">发件人:</strong><span class="zreadUserName"> <mwilck@suse.com>;</span></div><div><strong language-data="HistoryTOTxt">收件人:</strong><span class="zreadUserName" style="display: inline-block;">唐军辉10074136;</span><span class="zreadUserName" style="display: inline-block;"> <christophe.varoqui@opensvc.com>;</span><span class="zreadUserName" style="display: inline-block;"> <bmarzins@redhat.com>;</span><span class="zreadUserName" style="display: inline-block;"> <hare@suse.de>;</span><span class="zreadUserName" style="display: inline-block;"> <bart.vanassche@sandisk.com>;</span></div><div><strong language-data="HistoryCCTxt">抄送人:</strong><span class="zreadUserName" style="display: inline-block;">张凯10072500;</span><span class="zreadUserName" style="display: inline-block;"> <dm-devel@redhat.com>;</span><span class="zreadUserName" style="display: inline-block;">唐文俊10144149;</span></div><div><strong language-data="HistoryDateTxt">日 期 :</strong><span class="">2017年02月17日 05:22</span></div><div><strong language-data="HistorySubjectTxt">主 题 :</strong><span class="zreadTitle"><strong>Re: [dm-devel] [PATCH] multipath-tools: improve processing efficiency for addition and deletion of multipath devices</strong></span></div></div><p class="zhistoryContent"><br></p><div>Hello Tang,<br><br>I'm sorry to reply so late. Thanks a lot for your work, I agree with<br>Ben that the patch is in pretty good shape now. But I have some<br>remarks left, please see below. <br> <br>> +bool<br>> +uevent_can_discard(struct uevent *uev)<br>> +{<br>> +    char *tmp;<br>> +    char a[11], b[11];<br>> +    struct config * conf;<br>> +<br>> +    /*<br>> +     * keep only block devices, discard partitions<br>> +     */<br>> +    tmp = strstr(uev->devpath, "/block/");<br>> +    if (tmp == NULL){<br>> +        condlog(4, "no /block/ in '%s'", uev->devpath);<br>> +        return true;<br>> +    }<br>> +    if (sscanf(tmp, "/block/%10s", a) != 1 ||<br>> +        sscanf(tmp, "/block/%10[^/]/%10s", a, b) == 2) {<br>> +        condlog(4, "discard event on %s", uev->devpath);<br>> +        return true;<br>> +    }<br><br>I'd like the following better for this check. It uses much less cycles.<br><br>static bool<br>can_discard_by_devpath(const char *devpath)<br>{<br>    static const char BLOCK[] = "/block/";<br>    const char *p;<br><br>    p = strstr(pathstr, BLOCK);<br>    if (p == NULL)<br>        /* not a block device */<br>        return true;<br>    p += sizeof(BLOCK) - 1;<br>    p = strchr(p, '/');<br>    if (p == NULL)<br>        /* exactly one path element after "/block/" */<br>        return false;<br>    /* If there are more path elements, it's a partition */<br>    return true;<br>}<br><br>> +bool<br>> +uevent_can_filter(struct uevent *earlier, struct uevent *later)<br>> +{<br>> +<br>> +    /*<br>> +     * filter earlier uvents if path has removed later. Eg:<br>> +     * "add path1 |chang path1 |add path2 |remove path1"<br>> +     * can filter as:<br>> +     * "add path2 |remove path1"<br>> +     * uevents "add path1" and "chang path1" are filtered out<br>> +     */<br>> +    if (!strcmp(earlier->kernel, later->kernel) &&<br>> +        !strcmp(later->action, "remove") &&<br>> +        strncmp(later->kernel, "dm-", 3)) {<br>> +        return true;<br>> +    }<br>> +<br>> +    /*<br>> +     * filter change uvents if add uevents exist. Eg:<br>> +     * "change path1| add path1 |add path2"<br>> +     * can filter as:<br>> +     * "add path1 |add path2"<br>> +     * uevent "chang path1" is filtered out<br>> +     */<br>> +    if (!strcmp(earlier->kernel, later->kernel) &&<br>> +        !strcmp(earlier->action, "change") &&<br>> +        !strcmp(later->action, "add") &&<br>> +        strncmp(later->kernel, "dm-", 3)) {<br>> +        return true;<br>> +    }<br>> +<br>> +    return false;<br>> +}<br><br>This would be better readable and faster if you'd put the "kernel"<br>tests first so that you need to check only "action" later:<br><br>    if (!strncmp(later->kernel, "dm-", 3) ||<br>        strcmp(earlier->kernel, later->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<br>> to AVOID<br>> +     * "add path1 |remove path1 |add path2 |remove path2 |add<br>> path3"<br>> +     * to merge as "remove path1, path2" and "add path1, path2,<br>> path3"<br>> +     * OR<br>> +     * "remove path1 |add path1 |remove path2 |add path2 |remove<br>> path3"<br>> +     * to merge as "add path1, path2" and "remove path1, path2,<br>> 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>I know you discussed this with Ben before, but still have some trouble<br>with it. <br><br>The first case should have been reduced to "remove path1 | remove path2<br>| add path3" by filtering beforehand. I suppose you want to avoid this<br>sequence because it could leave us without paths temporarily, causing<br>multipathd to destroy the map. But I don't understand what "stop<br>merging" buys you here - if you process the events one-by-one, you may<br>also have 0 paths at some point. <br><br>In the second case, we know all events in the sequence have the same<br>WWID; in this case I think it would be safe to filter away "remove"<br>events by subsequent "add" events, ending up with "add path1| add<br>path2| remove path3". But I may be overlooking something here.<br><br>The dangerous thing if you have simultaneous remove and add events for<br>the same LUN is that processing the "add" events is likely to fail in<br>domap(). If you get "add path1 | remove path2", once you process "add<br>path1", "path2" may not exist in the kernel any more, and "domap" will<br>fail if you try to set up both; you may end up removing the map<br>completely. IMHO the only safe way to process events in this situation<br>is to merge the events into a single domap() call.<br><br>I know you want to avoid that in this patch, but I think it will be a<br>logical further improvement.<br><br>Anyway, AFAICS your patch doesn't introduce a regression wrt the<br>current code here; unless I'm overlooking something, my arguments would<br>apply to sequential event processing as well.<br><br>Regards<br>Martin<br><br>-- <br>Dr. Martin Wilck <mwilck@suse.com>, Tel. +49 (0)911 74053 2107<br>SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton<br>HRB 21284 (AG Nürnberg)<br><br>--<br>dm-devel mailing list<br>dm-devel@redhat.com<br>https://www.redhat.com/mailman/listinfo/dm-devel</div><p><br></p></div></div></div></div><p><br></p> </div>