The attached patch fixes a bug that's been lurking for a long time,
first in the lan plugin and then propagated to the lanplus plugin. If
there are multiple entries on the ipmi_req_entries linked list, and
ipmi_req_remove_entry() is called to remove the first entry, all
additional entries are also removed from the list, causing problems when
those requests complete. This condition is rather rare but seems to
occur more frequently under high latency conditions on the network.
-- Roger
The code that remove entries from the request list in both the lan and lanplus
plugins incorrectly removes all entries when attempting to remove the first
entry from the list, which can result in "IPMI Request Match NOT FOUND" errors
when requests come back from the BMC for which ipmitool has lost the entry.
This tends to only happen in conjunction with high network latency, and can
cause SOL sessions to close with the error "SOL session closed by BMC". This
patch fixes the problem and adds some comments to make the code easier to
understand.
Signed-off-by: Roger Mach <bigm...@us.ibm.com>
diff -Nurp ipmitool.orig/src/plugins/lan/lan.c ipmitool/src/plugins/lan/lan.c
--- ipmitool.orig/src/plugins/lan/lan.c 2007-08-27 23:16:14.000000000 -0700
+++ ipmitool/src/plugins/lan/lan.c 2008-12-09 15:11:19.000000000 -0800
@@ -146,7 +146,7 @@ ipmi_req_lookup_entry(uint8_t seq, uint8
static void
ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
{
- struct ipmi_rq_entry * p, * e;
+ struct ipmi_rq_entry * p, * e, * saved_next_entry;
e = p = ipmi_req_entries;
@@ -157,13 +157,16 @@ ipmi_req_remove_entry(uint8_t seq, uint8
if (e) {
lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
seq, cmd);
+ saved_next_entry = e->next;
p->next = (p->next == e->next) ? NULL : e->next;
+ /* If entry being removed is first in list, fix up list head */
if (ipmi_req_entries == e) {
if (ipmi_req_entries != p)
ipmi_req_entries = p;
else
- ipmi_req_entries = NULL;
+ ipmi_req_entries = saved_next_entry;
}
+ /* If entry being removed is last in list, fix up list tail */
if (ipmi_req_entries_tail == e) {
if (ipmi_req_entries_tail != p)
ipmi_req_entries_tail = p;
diff -Nurp ipmitool.orig/src/plugins/lanplus/lanplus.c
ipmitool/src/plugins/lanplus/lanplus.c
--- ipmitool.orig/src/plugins/lanplus/lanplus.c 2008-11-19 08:45:40.000000000
-0800
+++ ipmitool/src/plugins/lanplus/lanplus.c 2008-12-09 15:10:01.000000000
-0800
@@ -321,7 +321,7 @@ ipmi_req_lookup_entry(uint8_t seq, uint8
static void
ipmi_req_remove_entry(uint8_t seq, uint8_t cmd)
{
- struct ipmi_rq_entry * p, * e;
+ struct ipmi_rq_entry * p, * e, * saved_next_entry;
e = p = ipmi_req_entries;
@@ -332,13 +332,16 @@ ipmi_req_remove_entry(uint8_t seq, uint8
if (e) {
lprintf(LOG_DEBUG+3, "removed list entry seq=0x%02x cmd=0x%02x",
seq, cmd);
+ saved_next_entry = e->next;
p->next = (p->next == e->next) ? NULL : e->next;
+ /* If entry being removed is first in list, fix up list head */
if (ipmi_req_entries == e) {
if (ipmi_req_entries != p)
ipmi_req_entries = p;
else
- ipmi_req_entries = NULL;
+ ipmi_req_entries = saved_next_entry;
}
+ /* If entry being removed is last in list, fix up list tail */
if (ipmi_req_entries_tail == e) {
if (ipmi_req_entries_tail != p)
ipmi_req_entries_tail = p;
------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you. Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Ipmitool-devel mailing list
Ipmitool-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ipmitool-devel