Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 3091

kernel-2.6.18-194.11.1.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Fri, 25 Apr 2008 15:06:48 +0200
Subject: [s390] cio: kernel panic in cm_enable processing
Message-id: 20080425130648.GA22728@redhat.com
O-Subject: [RHEL5 U3 PATCH 1/5] s390 - cio: kernel panic in cm_enable processing
Bugzilla: 442032
RH-Acked-by: Alan Cox <alan@redhat.com>
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>

Description
============

A kernel panic occurs when cm_enable processing is triggered several
times in parallel.

The decision whether to add or to remove cm files and the processing
itself are done separately, which might cause inconsistencies when
this is triggered several times in parallel.

Serializing cm_enable processing by mutex_locks on store level is used to
fix the problem

Bugzilla
=========

BZ 442032
https://bugzilla.redhat.com/show_bug.cgi?id=442032

Upstream status of the patch:
=============================

Patch is contained in linux-2.6 as git commit
8284fb19efa1f11ea8dd213e9e227fc1fcb20586

Test status:
============

The patch has been tested and fixes the problem.
The fix has been verified by the IBM test department.

Please ACK.

With best regards,

Hans

 drivers/s390/cio/chsc.c |    3 ---
 drivers/s390/cio/css.c  |   10 +++++++++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index a89c6f3..8cc32d1 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -969,7 +969,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
 	if (!secm_area)
 		return -ENOMEM;
 
-	mutex_lock(&css->mutex);
 	if (enable && !css->cm_enabled) {
 		css->cub_addr1 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
 		css->cub_addr2 = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
@@ -977,7 +976,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
 			free_page((unsigned long)css->cub_addr1);
 			free_page((unsigned long)css->cub_addr2);
 			free_page((unsigned long)secm_area);
-			mutex_unlock(&css->mutex);
 			return -ENOMEM;
 		}
 	}
@@ -998,7 +996,6 @@ chsc_secm(struct channel_subsystem *css, int enable)
 		free_page((unsigned long)css->cub_addr1);
 		free_page((unsigned long)css->cub_addr2);
 	}
-	mutex_unlock(&css->mutex);
 	free_page((unsigned long)secm_area);
 	return ret;
 }
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 0e04fd3..651117e 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -548,10 +548,14 @@ css_cm_enable_show(struct device *dev, struct device_attribute *attr,
 		   char *buf)
 {
 	struct channel_subsystem *css = to_css(dev);
+	int ret;
 
 	if (!css)
 		return 0;
-	return sprintf(buf, "%x\n", css->cm_enabled);
+	mutex_lock(&css->mutex);
+	ret = sprintf(buf, "%x\n", css->cm_enabled);
+	mutex_unlock(&css->mutex);
+	return ret;
 }
 
 static ssize_t
@@ -561,6 +565,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
 	struct channel_subsystem *css = to_css(dev);
 	int ret;
 
+	mutex_lock(&css->mutex);
 	switch (buf[0]) {
 	case '0':
 		ret = css->cm_enabled ? chsc_secm(css, 0) : 0;
@@ -571,6 +576,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
 	default:
 		ret = -EINVAL;
 	}
+	mutex_unlock(&css->mutex);
 	return ret < 0 ? ret : count;
 }
 
@@ -599,8 +605,10 @@ static int css_reboot_event(struct notifier_block *this,
 
 	ret = 0;
 	for (i = 0; i <= __MAX_CSSID && !ret; i++) {
+		mutex_lock(&css[i]->mutex);
 		if (css[i]->cm_enabled)
 			ret = chsc_secm(css[i], 0);
+		mutex_unlock(&css[i]->mutex);
 	}
 
 	return ret ? NOTIFY_BAD : NOTIFY_DONE;