[Ocfs2-commits] mfasheh commits r1889 - trunk/fs/ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Feb 17 17:52:43 CST 2005


Author: mfasheh
Date: 2005-02-17 17:52:41 -0600 (Thu, 17 Feb 2005)
New Revision: 1889

Modified:
   trunk/fs/ocfs2/dlmglue.c
Log:
* only do lvb updates on a metadata lock if it's inode resource has
  been refreshed. Fixes a potential race with this where we might
  never get to actually update the inode before releasing it's lock.

* better handling of signals.



Modified: trunk/fs/ocfs2/dlmglue.c
===================================================================
--- trunk/fs/ocfs2/dlmglue.c	2005-02-10 19:59:00 UTC (rev 1888)
+++ trunk/fs/ocfs2/dlmglue.c	2005-02-17 23:52:41 UTC (rev 1889)
@@ -794,9 +794,8 @@
 
 {
 	LOG_ENTRY();
-	wait_event_interruptible(lockres->l_event,
-				 !ocfs2_check_wait_flag(lockres,
-							OCFS2_LOCK_BUSY));
+	wait_event(lockres->l_event,
+		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY));
 	LOG_EXIT();
 }
 
@@ -804,9 +803,8 @@
 
 {
 	LOG_ENTRY();
-	wait_event_interruptible(lockres->l_event,
-				 !ocfs2_check_wait_flag(lockres,
-							OCFS2_LOCK_BLOCKED));
+	wait_event(lockres->l_event,
+		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BLOCKED));
 	LOG_EXIT();
 }
 
@@ -814,9 +812,8 @@
 
 {
 	LOG_ENTRY();
-	wait_event_interruptible(lockres->l_event,
-				 !ocfs2_check_wait_flag(lockres,
-							OCFS2_LOCK_REFRESHING));
+	wait_event(lockres->l_event,
+		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING));
 	LOG_EXIT();
 }
 
@@ -837,12 +834,13 @@
 			      int lkm_flags)
 {
 	int ret;
+	int catch_signals = 1;
 	dlm_status status;
 
 	LOG_ENTRY();
 
 again:
-	if (signal_pending(current)) {
+	if (catch_signals && signal_pending(current)) {
 		ret = -EINTR;
 		goto bail;
 	}
@@ -920,6 +918,10 @@
 			lockres->l_name);
 
 		ocfs2_wait_on_busy_lock(lockres);
+
+		/* At this point we've gone inside the dlm and need to
+		 * complete our work regardless. */
+		catch_signals = 0;
 		goto again;
 	}
 
@@ -1071,24 +1073,6 @@
 	LOG_EXIT();
 }
 
-static inline int ocfs2_wait_on_recovery(ocfs_super *osb)
-{
-	int ret;
-
-	LOG_ENTRY();
-
-	wait_event_interruptible(osb->recovery_event,
-				 ocfs_node_map_is_empty(osb,
-							&osb->recovery_map));
-
-	ret = 0;
-	if (signal_pending(current))
-		ret = -EINTR;
-
-	LOG_EXIT_STATUS(ret);
-	return ret;
-}
-
 /* Call this with the lockres locked. I am reasonably sure we don't
  * need ip_lock in this function as anyone who would be changing those
  * values is supposed to be blocked in ocfs2_meta_lock right now.
@@ -1203,9 +1187,10 @@
 /* Determine whether a lock resource needs to be refreshed, and
  * arbitrate who gets to refresh it.
  *
- * < 0 means error, 0 means no refresh needed, > 0 means you need to
- *   refresh this and you MUST call ocfs2_complete_lock_res_refresh
- *   afterwards. */
+ *   0 means no refresh needed.
+ *
+ *   > 0 means you need to refresh this and you MUST call
+ *   ocfs2_complete_lock_res_refresh afterwards. */
 static int ocfs2_should_refresh_lock_res(ocfs2_lock_res *lockres)
 {
 
@@ -1221,10 +1206,7 @@
 
 	if (lockres->l_flags & OCFS2_LOCK_REFRESHING) {
 		spin_unlock(&lockres->l_lock);
-		if (signal_pending(current)) {
-			status = -EINTR;
-			goto bail;
-		}
+
 		ocfs2_wait_on_refreshing_lock(lockres);
 		goto refresh_check;
 	}
@@ -1262,7 +1244,6 @@
 				  struct buffer_head **bh)
 {
 	int status = 0;
-	int needs_refresh;
 	u32 trustable_clusters = 0;
 	ocfs2_lock_res *lockres;
 	ocfs2_dinode *fe;
@@ -1271,15 +1252,8 @@
 
 	lockres = &OCFS_I(inode)->ip_meta_lockres;
 
-	needs_refresh = ocfs2_should_refresh_lock_res(lockres);
-	if (!needs_refresh)
+	if (!ocfs2_should_refresh_lock_res(lockres))
 		goto bail;
-	if (needs_refresh < 0) {
-		status = needs_refresh;
-		if (status != -EINTR)
-			LOG_ERROR_STATUS(status);
-		goto bail;
-	}
 
 	if (ocfs2_lvb_is_trustable(lockres)) {
 		/* yay, fastpath! */
@@ -1294,7 +1268,7 @@
 					 OCFS_BH_CACHED, inode);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
-			goto bail;
+			goto bail_refresh;
 		}
 		fe = (ocfs2_dinode *) (*bh)->b_data;
 
@@ -1319,7 +1293,9 @@
 	ocfs2_set_local_seq_from_lvb(lockres);
 	ocfs2_reset_meta_lvb_values(inode);
 
-	ocfs2_complete_lock_res_refresh(lockres, 0);
+	status = 0;
+bail_refresh:
+	ocfs2_complete_lock_res_refresh(lockres, status);
 bail:
 	LOG_EXIT_STATUS(status);
 	return status;
@@ -1346,12 +1322,14 @@
 	dprintk("inode %llu, take %s META lock\n", OCFS_I(inode)->ip_blkno,
 		ex ? "EXMODE" : "PRMODE");
 
-	if (!(flags & OCFS2_META_LOCK_RECOVERY)) {
-		status = ocfs2_wait_on_recovery(osb);
-		if (status < 0)
-			goto bail;
-	}
+	if (!(flags & OCFS2_META_LOCK_RECOVERY))
+		wait_event_interruptible(osb->recovery_event,
+					 ocfs_node_map_is_empty(osb,
+								&osb->recovery_map));
 
+	if (signal_pending(current))
+		return -EINTR;
+
 	lockres = &OCFS_I(inode)->ip_meta_lockres;
 	level = ex ? LKM_EXMODE : LKM_PRMODE;
 	dlm_flags = 0;
@@ -1365,11 +1343,14 @@
 		goto bail;
 	}
 
-	if (!(flags & OCFS2_META_LOCK_RECOVERY)) {
-		status = ocfs2_wait_on_recovery(osb);
-		if (status < 0)
-			goto bail;
-	}
+	/* We wait twice because a node may have died while we were in
+	 * the lower dlm layers. The second time though, we've
+	 * committed to owning this lock so we don't allow signals to
+	 * abort the operation. */
+	if (!(flags & OCFS2_META_LOCK_RECOVERY))
+		wait_event(osb->recovery_event,
+			   ocfs_node_map_is_empty(osb,
+						  &osb->recovery_map));
 
 	status = ocfs2_meta_lock_update(inode, &bh);
 	if (status < 0) {
@@ -1778,7 +1759,12 @@
 	LOG_ENTRY();
 
 	OCFS_ASSERT(new_level == LKM_NLMODE || new_level == LKM_PRMODE);
-	if (new_level == LKM_PRMODE)
+
+	if (lockres->l_flags & OCFS2_LOCK_REFRESHING) {
+		ret = 0;
+		dprintk("lockres %s currently being refreshed -- backing "
+			"off!\n", lockres->l_name);
+	} else if (new_level == LKM_PRMODE)
 		ret = !lockres->l_ex_holders && 
 			ocfs_inode_fully_checkpointed(inode);
 	else /* Must be NLMODE we're converting to. */
@@ -1833,11 +1819,21 @@
 		       lockres->l_level, lockres->l_blocking, new_level);
 
 	if (ocfs2_can_downconvert_meta_lock(inode, lockres, new_level)) {
-		if (lockres->l_level == LKM_EXMODE) {
-			__ocfs2_stuff_meta_lvb(inode);
+		if (lockres->l_level == LKM_EXMODE)
 			set_lvb = 1;
-		}
-		__ocfs2_lvb_on_downconvert(lockres, new_level);
+
+		/* If the lock hasn't been refreshed yet (rare), then our
+		 * memory inode values are old and we skip stuffing
+		 * the lvb. Additionally we cannot incrememnt the lvb
+		 * sequence numbers */
+		if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) {
+			if (set_lvb)
+				__ocfs2_stuff_meta_lvb(inode);
+			__ocfs2_lvb_on_downconvert(lockres, new_level);
+		} else
+			dprintk("lockres %s: downconverting stale lock!\n",
+				lockres->l_name);
+
 		LOG_TRACE_ARGS("calling __ocfs2_downconvert_lock with "
 			       "l_level=%d, l_blocking=%d, new_level=%d\n",
 			       lockres->l_level, lockres->l_blocking,



More information about the Ocfs2-commits mailing list