Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1793

kernel-2.6.18-238.el5.src.rpm

From: Jesse Larrew <jlarrew@redhat.com>
Date: Fri, 12 Jun 2009 13:48:44 -0400
Subject: [md] increase pg_init_in_progress only if work is queued
Message-id: 20090612174844.GA18666@squad5-lp1.lab.bos.redhat.com
O-Subject: [PATCH RHEL5.4 12/12 BZ489582] Increase pg_init_in_progress only if work is queued.
Bugzilla: 489582
RH-Acked-by: Mike Christie <mchristi@redhat.com>

RHBZ#:
======
https://bugzilla.redhat.com/show_bug.cgi?id=489582

Description:
===========
This is a bug fix for all archs.

A race condition was discovered where pg_init_in_progress was being
incremented when queue_work() returns without actually queuing the work.
This can lead to an IO hang situation.

This patch fixes the issue by incrementing pg_init_in_progress only when
queue_work() returns success.

RHEL Version Found:
================
RHEL 5.4

kABI Status:
============
No symbols were harmed.

Brew:
=====
Built on all platforms.
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1840550

Upstream Status:
================
This has been posted to dm-devel:
http://marc.info/?l=dm-devel&m=124424663327710&w=2

Test Status:
============
This has been tested by Chandra Seetharaman <sekharan@us.ibm.com> at
IBM.

===============================================================

Jesse Larrew
IBM Onsite Partner
978-392-3183
jlarrew@redhat.com

Proposed Patch:
===============
This patch is based on kernel-2.6.18-153.el5.

diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 5d875dd..653e544 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -441,12 +441,12 @@ static void process_queued_ios(void *data)
 			m->pg_init_in_progress = 1;
 			init_required = 1;
 		} else {
-	 		list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
-				queue_delayed_work(kmpath_handlerd,
+			list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
+				if (queue_delayed_work(kmpath_handlerd,
 				    &tmp->activate_path, m->pg_init_delay ?
-					m->pg_init_delay_secs * HZ : 0);
- 				m->pg_init_in_progress++;
- 			}
+				    m->pg_init_delay_secs * HZ : 0))
+					m->pg_init_in_progress++;
+			}
 		}
 		m->pg_init_delay = 0;
 	}
@@ -966,8 +966,8 @@ static int reinstate_path(struct pgpath *pgpath)
 		m->current_pgpath = NULL;
 		queue_work(kmultipathd, &m->process_queued_ios);
 	} else if (m->hw_handler_name && (m->current_pg == pgpath->pg)) {
- 		m->pg_init_in_progress++;
-		queue_work(kmpath_handlerd, &pgpath->activate_path);
+		if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+			m->pg_init_in_progress++;
 	}
 
 	dm_path_uevent(DM_UEVENT_PATH_REINSTATED, m->ti,