[Ocfs2-commits] mfasheh commits r1618 - branches/dlm-glue/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Nov 2 19:47:39 CST 2004


Author: mfasheh
Date: 2004-11-02 19:47:37 -0600 (Tue, 02 Nov 2004)
New Revision: 1618

Modified:
   branches/dlm-glue/src/dlmglue.c
   branches/dlm-glue/src/ocfs.h
Log:
* teach the dlmglue layer how to cancel an upconvert request



Modified: branches/dlm-glue/src/dlmglue.c
===================================================================
--- branches/dlm-glue/src/dlmglue.c	2004-11-02 20:22:12 UTC (rev 1617)
+++ branches/dlm-glue/src/dlmglue.c	2004-11-03 01:47:37 UTC (rev 1618)
@@ -132,7 +132,8 @@
 				struct inode *inode);
 static void ocfs2_schedule_blocked_inode(struct inode *inode);
 static inline void ocfs2_recover_from_dlm_error(ocfs2_lock_res *lockres,
-						ocfs2_lock *lock);
+						ocfs2_lock *lock,
+						int convert);
 static void ocfs2_vote_on_unlock(ocfs_super *osb,
 				 ocfs2_lock *lock);
 /* Called after we refresh our inode, only has any effect if we have
@@ -153,10 +154,14 @@
 			     ocfs2_lock_res *lockres,
 			     ocfs2_lock *lock);
 static inline int ocfs2_highest_compat_lock_level(int level);
-static int __ocfs2_downconvert_lock(ocfs2_lock_res *lockres,
+static int __ocfs2_downconvert_lock(ocfs_super *osb,
+				    ocfs2_lock_res *lockres,
 				    ocfs2_lock *lock,
 				    int new_level,
 				    int lvb);
+static int __ocfs2_cancel_convert(ocfs_super *osb,
+				  ocfs2_lock_res *lockres,
+				  ocfs2_lock *lock);
 static void ocfs2_process_blocked_inode(struct inode *inode);
 static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
 						  ocfs2_lock *lock,
@@ -493,11 +498,15 @@
 }
 
 static inline void ocfs2_recover_from_dlm_error(ocfs2_lock_res *lockres,
-						ocfs2_lock *lock)
+						ocfs2_lock *lock,
+						int convert)
 {
 	spin_lock(&lockres->lr_lock);
 	lock->l_flags &= ~OCFS2_LOCK_BUSY;
-	lock->l_action = OCFS2_AST_INVALID;
+	if (convert)
+		lock->l_action = OCFS2_AST_INVALID;
+	else
+		lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
 	spin_unlock(&lockres->lr_lock);
 }
 
@@ -536,7 +545,7 @@
 	if (status != DLM_NORMAL) {
 		LOG_ERROR_ARGS("Dlm returns %d\n", status);
 		ret = -ENOENT;
-		ocfs2_recover_from_dlm_error(lockres, lock);
+		ocfs2_recover_from_dlm_error(lockres, lock, 1);
 	}
 
 bail:
@@ -660,7 +669,7 @@
 		if (status != DLM_NORMAL) {
 			LOG_ERROR_ARGS("Dlm returns %d\n", status);
 			ret = -ENOENT;
-			ocfs2_recover_from_dlm_error(lockres, lock);
+			ocfs2_recover_from_dlm_error(lockres, lock, 1);
 			goto bail;
 		}
 
@@ -1131,7 +1140,17 @@
 		LOG_ERROR_ARGS("Dlm returns status %d\n", status);
 
 	spin_lock(&lockres->lr_lock);
-	lock->l_level = LKM_IVMODE;
+	switch(lock->l_unlock_action) {
+	case OCFS2_UNLOCK_CANCEL_CONVERT:
+		lock->l_action = OCFS2_AST_INVALID;
+		break;
+	case OCFS2_UNLOCK_DROP_LOCK:
+		lock->l_level = LKM_IVMODE;
+		break;
+	default:
+		BUG();
+	}
+	lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
 	lock->l_flags &= ~OCFS2_LOCK_BUSY;
 	spin_unlock(&lockres->lr_lock);
 
@@ -1158,8 +1177,13 @@
 
 	lock->l_flags &= ~OCFS2_LOCK_ATTACHED;
 
+	/* make sure we never get here while waiting for an ast to
+	 * fire. */
+	OCFS_ASSERT(lock->l_action == OCFS2_AST_INVALID);
+
 	/* is this necessary? */
 	lock->l_flags |= OCFS2_LOCK_BUSY;
+	lock->l_unlock_action = OCFS2_UNLOCK_DROP_LOCK;
 	spin_unlock(&lockres->lr_lock);
 
 	status = dlmunlock(osb->dlm,
@@ -1232,13 +1256,13 @@
 }
 
 /* called with the spinlock held, and WILL drop it. */
-static int __ocfs2_downconvert_lock(ocfs2_lock_res *lockres,
+static int __ocfs2_downconvert_lock(ocfs_super *osb,
+				    ocfs2_lock_res *lockres,
 				    ocfs2_lock *lock,
 				    int new_level,
 				    int lvb)
 {
 	int status, flags = LKM_CONVERT;
-	struct inode *inode = lockres->lr_inode;
 	enum ocfs2_lock_type type = lock->l_type;
 	OCFS_ASSERT(lock->l_blocking > LKM_NLMODE);
 	OCFS_ASSERT(lock->l_level > new_level);
@@ -1251,7 +1275,7 @@
 	if (lvb)
 		flags |= LKM_VALBLK;
 
-	status = dlmlock(OCFS2_SB(inode->i_sb)->dlm,
+	status = dlmlock(osb->dlm,
 			 new_level,
 			 &lock->l_lksb,
 			 flags,
@@ -1262,7 +1286,7 @@
 	if (status != DLM_NORMAL) {
 		LOG_ERROR_ARGS("Dlm returns %d\n", status);
 		status = -ENOENT;
-		ocfs2_recover_from_dlm_error(lockres, lock);
+		ocfs2_recover_from_dlm_error(lockres, lock, 1);
 		goto bail;
 	}
 	status = 0;
@@ -1270,6 +1294,45 @@
 	return status;
 }
 
+/* called with the spinlock held, and WILL drop it. */
+static int __ocfs2_cancel_convert(ocfs_super *osb,
+				  ocfs2_lock_res *lockres,
+				  ocfs2_lock *lock)
+{
+	int status;
+
+	/* were we in a convert when we got the bast fire? */
+	OCFS_ASSERT(lock->l_action == OCFS2_AST_CONVERT ||
+		    lock->l_action == OCFS2_AST_DOWNCONVERT);
+	/* set things up for the unlockast to know to just
+	 * clear out the ast_action and unset busy, etc. */
+	lock->l_unlock_action = OCFS2_UNLOCK_CANCEL_CONVERT;
+	spin_unlock(&lockres->lr_lock);
+
+	status = dlmunlock(osb->dlm,
+			   &lock->l_lksb,
+			   LKM_CANCEL,
+			   ocfs2_unlock_ast_func,
+			   lock);
+	if (status == DLM_NORMAL)
+		status = 0;
+
+	if (status == DLM_CANCELGRANT) {
+		/* If we got this, then the ast was fired
+		 * before we could cancel. We cleanup our
+		 * state, and restart the function. */
+		spin_lock(&lockres->lr_lock);
+		lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
+		spin_unlock(&lockres->lr_lock);
+	} else {
+		LOG_ERROR_ARGS("Dlm returns %d\n", status);
+		status = -ENOENT;
+		ocfs2_recover_from_dlm_error(lockres, lock, 0);
+	}
+
+	return status;
+}
+
 static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
 						  ocfs2_lock *lock,
 						  int new_level)
@@ -1290,10 +1353,10 @@
 static int ocfs2_process_blocked_meta(struct inode *inode,
 				      int *requeue)
 {
+	int new_level;
+	int set_lvb = 0;
 	ocfs2_lock_res *lockres = &OCFS_I(inode)->ip_lockres;
 	ocfs2_lock *lock = &lockres->lr_meta;
-	int new_level;
-	int set_lvb = 0;
 
 	spin_lock(&lockres->lr_lock);
 	if (!(lock->l_flags & OCFS2_LOCK_BLOCKED)) {
@@ -1301,10 +1364,23 @@
 		return 0;
 	}
 
-	OCFS_ASSERT(!(lock->l_flags & OCFS2_LOCK_BUSY));
 	OCFS_ASSERT(lock->l_level == LKM_EXMODE || 
 		    lock->l_level == LKM_PRMODE);
 
+	if (lock->l_flags & OCFS2_LOCK_BUSY) {
+		*requeue++;
+		if (lock->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+			/* If we're already trying to cancel a lock conversion
+			 * then just drop the spinlock and requeue ourselves
+			 * to check again later. */
+			spin_unlock(&lockres->lr_lock);
+			return 0;
+		}
+
+		return __ocfs2_cancel_convert(OCFS2_SB(inode->i_sb),
+					      lockres, lock);
+	}
+
 	new_level = ocfs2_highest_compat_lock_level(lock->l_blocking);
 	if (ocfs2_can_downconvert_meta_lock(inode, lock, new_level)) {
 		if (lock->l_level == LKM_EXMODE) {
@@ -1312,7 +1388,8 @@
 			set_lvb = 1;
 		}
 		__ocfs2_lvb_on_downconvert(lock, new_level);
-		return __ocfs2_downconvert_lock(lockres, lock, new_level,
+		return __ocfs2_downconvert_lock(OCFS2_SB(inode->i_sb),
+						lockres, lock, new_level,
 						set_lvb);
 	}
 	if (!ocfs_inode_fully_checkpointed(inode))
@@ -1341,6 +1418,20 @@
 	OCFS_ASSERT(!(lock->l_flags & OCFS2_LOCK_BUSY));
 
 recheck:
+	if (lock->l_flags & OCFS2_LOCK_BUSY) {
+		*requeue++;
+		if (lock->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+			/* If we're already trying to cancel a lock conversion
+			 * then just drop the spinlock and requeue ourselves
+			 * to check again later. */
+			spin_unlock(&lockres->lr_lock);
+			return 0;
+		}
+
+		return __ocfs2_cancel_convert(OCFS2_SB(inode->i_sb),
+					      lockres, lock);
+	}
+
 	/* if we're blocking an exclusive and we have *anyone* in I/O,
 	 * then requeue. */
 	if ((lock->l_blocking == LKM_EXMODE) 
@@ -1349,6 +1440,7 @@
 		*requeue++;
 		return 0;
 	}
+
 	/* If it's a PR we're blocking, then only
 	 * requeue if we've got anyone doing write (ex) I/O */
 	if (lock->l_blocking == LKM_PRMODE &&
@@ -1380,7 +1472,8 @@
 	}
 
 	new_level = ocfs2_highest_compat_lock_level(lock->l_blocking);
-	return __ocfs2_downconvert_lock(lockres, lock, new_level, 0);
+	return __ocfs2_downconvert_lock(OCFS2_SB(inode->i_sb), lockres, lock, 
+					new_level, 0);
 }
 
 static void ocfs2_process_blocked_inode(struct inode *inode)

Modified: branches/dlm-glue/src/ocfs.h
===================================================================
--- branches/dlm-glue/src/ocfs.h	2004-11-02 20:22:12 UTC (rev 1617)
+++ branches/dlm-glue/src/ocfs.h	2004-11-03 01:47:37 UTC (rev 1618)
@@ -194,6 +194,13 @@
 	OCFS2_AST_DOWNCONVERT,
 };
 
+/* actions for an unlockast function to take. */
+enum ocfs2_unlock_action {
+	OCFS2_UNLOCK_INVALID = 0,
+	OCFS2_UNLOCK_CANCEL_CONVERT,
+	OCFS2_UNLOCK_DROP_LOCK,
+};
+
 struct _ocfs2_lock_res;
 
 enum ocfs2_lock_type {
@@ -216,6 +223,7 @@
 
 	/* used from AST/BAST funcs. */
 	enum ocfs2_ast_action   l_action;
+	enum ocfs2_unlock_action l_unlock_action;
 	int                     l_requested;
 	int                     l_blocking;
 } ocfs2_lock;



More information about the Ocfs2-commits mailing list