Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Steven Whitehouse <swhiteho@redhat.com>
Subject: [RHEL 5.1] [GFS2] bz #236069, GFS2: deadlock running 	d_rwdirectlarge
Date: Thu, 10 May 2007 11:00:28 +0100
Bugzilla: 236069
Message-Id: <1178791228.7476.32.camel@quoit>
Changelog: [GFS2] deadlock running d_rwdirectlarge


Hi,

This patch fixes bz #236069. It is NOT upstream. The upstream fix for
this particular bug is in the shape of Nick Piggin's patch series
relating to new address space operations. This is not a suitable fix for
RHEL because it would require extensive modification of the VFS and all
the other filesystems write paths which seems to be a rather high risk
operation for the potential gain.

Instead this patch provides a fix for GFS2 which is the only filesystem
which is affected by this particular bug.

It has been tested with QE's test suite (which reliably reproduces the
bug) and the bug no longer happens with this patch applied.

Steve.

-------------------------------------------------------------------------

--- linux-rhel-base/fs/gfs2/ops_address.c	2007-05-10 10:36:31.000000000 +0100
+++ linux-2.6.18.noarch/fs/gfs2/ops_address.c	2007-05-10 10:41:39.000000000 +0100
@@ -324,6 +324,24 @@
 	goto out;
 }
 
+static int gfs2_write_lock_start(struct gfs2_inode *ip, struct page *page)
+{
+	struct gfs2_holder *gh = &ip->i_gh;
+	int ret = 0;
+	if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
+		gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME, gh);
+		unlock_page(page);
+		ret = gfs2_glock_nq_atime(gh);
+		if (unlikely(ret)) {
+			gfs2_holder_uninit(gh);
+			return ret;
+		}
+		ret = AOP_TRUNCATED_PAGE;
+		yield();
+	}
+	return ret;
+}
+
 /**
  * gfs2_prepare_write - Prepare to write a page to a file
  * @file: The file to write to
@@ -348,16 +366,9 @@
 	unsigned int write_len = to - from;
 
 
-	gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ATIME|LM_FLAG_TRY_1CB, &ip->i_gh);
-	error = gfs2_glock_nq_m_atime(1, &ip->i_gh);
-	if (unlikely(error)) {
-		if (error == GLR_TRYFAILED) {
-			unlock_page(page);
-			error = AOP_TRUNCATED_PAGE;
-			yield();
-		}
-		goto out_uninit;
-	}
+	error = gfs2_write_lock_start(ip, page);
+	if (error)
+		return error;
 
 	gfs2_write_calc_reserv(ip, write_len, &data_blocks, &ind_blocks);
 
@@ -419,7 +430,6 @@
 		}
 out_unlock:
 		gfs2_glock_dq_m(1, &ip->i_gh);
-out_uninit:
 		gfs2_holder_uninit(&ip->i_gh);
 	}