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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Apr 13 18:32:50 CDT 2005


Author: mfasheh
Signed-off-by: khackel
Date: 2005-04-13 18:32:49 -0500 (Wed, 13 Apr 2005)
New Revision: 2142

Modified:
   trunk/fs/ocfs2/dlmglue.c
   trunk/fs/ocfs2/inode.c
   trunk/fs/ocfs2/ocfs.h
Log:
* We had missed using the lockres flag set functions in a couple places.     
 
* ocfs2_recover_from_dlm_error was forgetting to wake_up after clearing the 
  busy flag.

* Don't clear the OCFS2_LOCK_LOCAL flag in ocfs2_create_new_inode_locks,
  have the ast do it instead.

* Genericize more of the drop_lock path, have ocfs2_drop_lock actually wait
  on busy locks instead of stampeding forward regardless.

* Don't let drop_lock exit on a signal... it needs to wait until the lock   
  has been destroyed, otherwise we'll be referencing memory that doesn't
  belong to us in the ast handler.

* Clear the inode initialized flag later in ocfs_clear_inode. This allows us 
  to assert on it in a few more paths, including the inode ast function.

Signed-off-by: khackel



Modified: trunk/fs/ocfs2/dlmglue.c
===================================================================
--- trunk/fs/ocfs2/dlmglue.c	2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/dlmglue.c	2005-04-13 23:32:49 UTC (rev 2142)
@@ -84,9 +84,11 @@
 				 char **ret);
 
 static void ocfs2_inode_ast_func(void *opaque);
-static void ocfs2_inode_bast_func(void *opaque, int level);
+static void ocfs2_inode_bast_func(void *opaque,
+				  int level);
 static void ocfs2_super_ast_func(void *opaque);
-static void ocfs2_super_bast_func(void *opaque, int level);
+static void ocfs2_super_bast_func(void *opaque,
+				  int level);
 /* so far, all locks have gotten along with the same unlock ast */
 static void ocfs2_unlock_ast_func(void *opaque,
 				  dlm_status status);
@@ -204,8 +206,6 @@
 				       int new_level);
 static int ocfs2_meta_lock_update(struct inode *inode,
 				  struct buffer_head **bh);
-static int __ocfs2_drop_lock(ocfs_super *osb,
-			     ocfs2_lock_res *lockres);
 static void ocfs2_drop_super_lock(ocfs_super *osb);
 static inline int ocfs2_highest_compat_lock_level(int level);
 static int __ocfs2_downconvert_lock(ocfs_super *osb,
@@ -316,7 +316,6 @@
 				       enum ocfs2_lock_type type,
 				       void *priv)
 {
-	LOG_ENTRY();
 	memset(res, 0, sizeof(ocfs2_lock_res));
 	spin_lock_init(&res->l_lock);
 	init_waitqueue_head(&res->l_event);
@@ -325,7 +324,6 @@
 	INIT_LIST_HEAD(&res->l_blocked_list);
 	INIT_LIST_HEAD(&res->l_flag_cb_list);
 	res->l_priv = priv;
-	LOG_EXIT();
 }
 
 int ocfs2_inode_lock_res_init(ocfs2_lock_res *res,
@@ -601,6 +599,8 @@
 
 	OCFS_ASSERT(ocfs2_is_inode_lock(lockres));
 
+	OCFS_ASSERT(OCFS_I(inode)->ip_flags & OCFS_INODE_INITIALIZED);
+
 	spin_lock(&lockres->l_lock);
 
 	lksb = &(lockres->l_lksb);
@@ -621,6 +621,7 @@
 			ocfs2_inc_inode_seq(osb, inode);
 
 		ocfs2_generic_handle_attach_action(lockres);
+		lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
 		break;
 	case OCFS2_AST_CONVERT:
 		if (lockres->l_type == OCFS_TYPE_META)
@@ -655,7 +656,7 @@
 
 	assert_spin_locked(&lockres->l_lock);
 
-	lockres->l_flags |= OCFS2_LOCK_BLOCKED;
+	lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
 
 	if (level > lockres->l_blocking) {
 		/* only schedule a downconvert if we haven't already scheduled
@@ -682,6 +683,8 @@
 
 	LOG_ENTRY();
 
+	OCFS_ASSERT(ocfs2_is_inode_lock(lockres));
+
 	inode = ocfs2_lock_res_inode(lockres);
 	osb = OCFS2_SB(inode->i_sb);
 
@@ -782,12 +785,15 @@
 	else
 		lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
 	spin_unlock(&lockres->l_lock);
+
+	wake_up(&lockres->l_event);
 	LOG_EXIT();
 }
 
 /* Note: If we detect another process working on the lock (i.e.,
  * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller
- * to do the right thing in that case. */
+ * to do the right thing in that case. 
+ */
 static int ocfs2_lock_create(ocfs_super *osb,
 			     ocfs2_lock_res *lockres,
 			     int level,
@@ -838,39 +844,33 @@
 					int flag)
 {
 	int ret;
-	LOG_ENTRY();
+
 	spin_lock(&lockres->l_lock);
 	ret = lockres->l_flags & flag;
 	spin_unlock(&lockres->l_lock);
-	LOG_EXIT_STATUS(ret);
+
 	return ret;
 }
 
 static inline void ocfs2_wait_on_busy_lock(ocfs2_lock_res *lockres)
 
 {
-	LOG_ENTRY();
 	wait_event(lockres->l_event,
 		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY));
-	LOG_EXIT();
 }
 
 static inline void ocfs2_wait_on_blocked_lock(ocfs2_lock_res *lockres)
 
 {
-	LOG_ENTRY();
 	wait_event(lockres->l_event,
 		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BLOCKED));
-	LOG_EXIT();
 }
 
 static inline void ocfs2_wait_on_refreshing_lock(ocfs2_lock_res *lockres)
 
 {
-	LOG_ENTRY();
 	wait_event(lockres->l_event,
 		   !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING));
-	LOG_EXIT();
 }
 
 static void lockres_add_flag_callback(ocfs2_lock_res *lockres,
@@ -967,6 +967,7 @@
 	if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
 		/* lock has not been created yet. */
 		spin_unlock(&lockres->l_lock);
+
 		ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
 		if (ret < 0) {
 			LOG_ERROR_STATUS(ret);
@@ -987,7 +988,7 @@
 	if (level > lockres->l_level) {
 		lockres->l_action = OCFS2_AST_CONVERT;
 		lockres->l_requested = level;
-		lockres->l_flags |= OCFS2_LOCK_BUSY;
+		lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
 		spin_unlock(&lockres->l_lock);
 
 		OCFS_ASSERT(level != LKM_IVMODE);
@@ -1091,7 +1092,6 @@
 	lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
 
 	status = ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL);
-	lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -1102,7 +1102,6 @@
 	lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
 
 	status = ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL);
-	lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -1687,7 +1686,8 @@
 	LOG_EXIT();
 }
 
-/* BEWARE: called with lockres lock, and always drops it. */
+/* BEWARE: called with lockres lock, and always drops it. Caller
+ * should not be calling us with a busy lock... */
 static int __ocfs2_drop_lock(ocfs_super *osb,
 			     ocfs2_lock_res *lockres)
 {
@@ -1729,63 +1729,99 @@
 		ret = -ENOENT;
 		goto bail;
 	}
-
 	dprintk("lock %s, successfull return from dlmunlock\n",
 		lockres->l_name);
 
 	ocfs2_wait_on_busy_lock(lockres);
-	if (signal_pending(current)) {
-		LOG_TRACE_STR("Signal caught!\n");
-		ret = -EINTR;
-	}
 bail:
 	LOG_EXIT_STATUS(ret);
 	return ret;
 }
 
+typedef void (ocfs2_pre_drop_cb_t)(ocfs2_lock_res *, void *);
+
+struct drop_lock_cb {
+	ocfs2_pre_drop_cb_t	*drop_func;
+	void			*drop_data;
+};
+
+static int ocfs2_drop_lock(ocfs_super *osb,
+			   ocfs2_lock_res *lockres,
+			   struct drop_lock_cb *dcb)
+{
+	spin_lock(&lockres->l_lock);
+
+	while (lockres->l_flags & OCFS2_LOCK_BUSY) {
+		dprintk("waiting on busy lock \"%s\": flags = %lx, action = "
+			"%u, unlock_action = %u\n",
+			lockres->l_name, lockres->l_flags, lockres->l_action,
+			lockres->l_unlock_action);
+
+		spin_unlock(&lockres->l_lock);
+
+		/* XXX: Today we just wait on any busy
+		 * locks... Perhaps we need to cancel converts in the
+		 * future? */
+		ocfs2_wait_on_busy_lock(lockres);
+
+		spin_lock(&lockres->l_lock);
+	}
+
+	if (dcb)
+		dcb->drop_func(lockres, dcb->drop_data);
+
+	/* This will drop the spinlock for us. Dur de dur, at least we
+	 * keep the ugliness in one place :) */
+	return  __ocfs2_drop_lock(osb, lockres);
+}
+
 static void ocfs2_drop_super_lock(ocfs_super *osb)
 {
 	int status;
-	ocfs2_lock_res *lockres;
 
 	LOG_ENTRY();
-	lockres = &osb->super_lockres;
 
-	spin_lock(&lockres->l_lock);
-	status = __ocfs2_drop_lock(osb, lockres);
+	status = ocfs2_drop_lock(osb, &osb->super_lockres, NULL);
 	if (status < 0)
 		LOG_ERROR_STATUS(status);
+
 	LOG_EXIT_STATUS(status);
 }
 
-int ocfs2_drop_inode_locks(struct inode *inode)
+static void ocfs2_meta_pre_drop(ocfs2_lock_res *lockres, void *data)
 {
-	int status, err;
-	ocfs2_lock_res *lockres;
+	struct inode *inode = data;
 
-	LOG_ENTRY();
-	lockres = &OCFS_I(inode)->ip_data_lockres;
-	spin_lock(&lockres->l_lock);
-	err = __ocfs2_drop_lock(OCFS2_SB(inode->i_sb), lockres);
-	if (err < 0)
-		LOG_ERROR_STATUS(err);
-
-	status = err;
-
 	/* the metadata lock requires a bit more work as we have an
 	 * LVB to worry about. */
-	lockres = &OCFS_I(inode)->ip_meta_lockres;
-
-	spin_lock(&lockres->l_lock);
 	if (lockres->l_flags & OCFS2_LOCK_ATTACHED) {
 		if (lockres->l_level == LKM_EXMODE)
 			__ocfs2_stuff_meta_lvb(inode);
 		/* fake an NLMODE downconvert for the lvb code. */
 		__ocfs2_lvb_on_downconvert(lockres, LKM_NLMODE);
 	}
-	err = __ocfs2_drop_lock(OCFS2_SB(inode->i_sb), lockres);
+}
+
+int ocfs2_drop_inode_locks(struct inode *inode)
+{
+	int status, err;
+	struct drop_lock_cb meta_dcb = { ocfs2_meta_pre_drop, inode, };
+
+	LOG_ENTRY();
+
+	err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+			      &OCFS_I(inode)->ip_data_lockres,
+			      NULL);
 	if (err < 0)
 		LOG_ERROR_STATUS(err);
+
+	status = err;
+
+	err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+			      &OCFS_I(inode)->ip_meta_lockres,
+			      &meta_dcb);
+	if (err < 0)
+		LOG_ERROR_STATUS(err);
 	if (err < 0 && !status)
 		status = err;
 
@@ -1836,6 +1872,7 @@
 		ocfs2_recover_from_dlm_error(lockres, 1);
 		goto bail;
 	}
+
 	status = 0;
 bail:
 	LOG_EXIT_STATUS(status);

Modified: trunk/fs/ocfs2/inode.c
===================================================================
--- trunk/fs/ocfs2/inode.c	2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/inode.c	2005-04-13 23:32:49 UTC (rev 2142)
@@ -834,8 +834,6 @@
 	if (!INODE_DELETED(inode))
 		ocfs2_checkpoint_inode(inode);
 
-	OCFS_I(inode)->ip_flags &= ~OCFS_INODE_INITIALIZED;
-
 	if (OCFS_I(inode)->ip_blkno == -1)
 		BUG();
 
@@ -856,6 +854,9 @@
 
 	ocfs2_lock_res_free(&OCFS_I(inode)->ip_meta_lockres);
 	ocfs2_lock_res_free(&OCFS_I(inode)->ip_data_lockres);
+
+	OCFS_I(inode)->ip_flags &= ~OCFS_INODE_INITIALIZED;
+
 	/* clean out the inode private ... why?! */
 	memset(inode->u.generic_ip, 0, sizeof(ocfs_inode_private));
 
@@ -868,7 +869,6 @@
 	LOG_EXIT ();
 
 	LOG_CLEAR_CONTEXT();
-	return;
 }				/* ocfs_clear_inode */
 
 /*

Modified: trunk/fs/ocfs2/ocfs.h
===================================================================
--- trunk/fs/ocfs2/ocfs.h	2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/ocfs.h	2005-04-13 23:32:49 UTC (rev 2142)
@@ -174,8 +174,7 @@
 	int                      l_requested;
 	int                      l_blocking;
 
-	wait_queue_head_t l_event;
-
+	wait_queue_head_t        l_event;
 } ocfs2_lock_res;
 
 /* OCFS2 Inode Private Data */



More information about the Ocfs2-commits mailing list