[Ocfs2-commits] mfasheh commits r1211 - trunk/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Jun 25 13:50:06 CDT 2004


Author: mfasheh
Date: 2004-06-25 12:50:04 -0500 (Fri, 25 Jun 2004)
New Revision: 1211

Modified:
   trunk/src/journal.c
Log:
* Commit the last of my 2.4 BKL fixes against our journalling stuff.



Modified: trunk/src/journal.c
===================================================================
--- trunk/src/journal.c	2004-06-24 23:22:45 UTC (rev 1210)
+++ trunk/src/journal.c	2004-06-25 17:50:04 UTC (rev 1211)
@@ -66,19 +66,120 @@
 static int __ocfs_recovery_thread(void *arg);
 static int ocfs_commit_cache (ocfs_super * osb, int data_flush);
 static int ocfs_wait_on_mount(ocfs_super *osb);
+static int ocfs_journal_flush(ocfs_journal *journal);
 
+static int ocfs_journal_flush(ocfs_journal *journal) 
+{
+	int retval;
+
+	down_write(&journal->trans_barrier);
+	journal_lock_updates(journal->k_journal);
+
+	retval = journal_flush(journal->k_journal);
+
+	journal_unlock_updates(journal->k_journal);
+	up_write(&journal->trans_barrier);
+
+	return(retval);
+}
+
 /* 
- * JBD in 2.4 kernels has a bug in that it doesn't do any locking of
- * the t_updates transaction variable. If we don't serialize calls to
- * journal_start/journal_stop, then it can get way out of whack,
- * resulting in either a crash or a lockup. As far as I can tell, they
- * never hit this bug in ext3 because those calls somehow manage to
- * get serialized. I wish I didn't have to use lock_kernel here, but
- * we actually want the "drop on sleep" behavior which we can't get
- * with any other lock.
- * 
- * 2.6 does it the right way by spinlocking around it's structures.
+ * ocfs_commit_cache()
  *
+ * This is in journal.c for lack of a better place.
+ *
+ */
+static int ocfs_commit_cache(ocfs_super *osb, int data_flush)
+{
+	int status = 0, tmpstat;
+	ocfs_journal * journal = NULL;
+	struct list_head *p, *n;
+	ocfs_journal_handle *handle = NULL;
+	ocfs_commit_task *commit = osb->commit;
+
+	LOG_ENTRY_ARGS("(data_flush = %u)\n", data_flush);
+
+	journal = osb->journal;
+
+	if (atomic_read(&journal->num_trans) == 0) {
+		LOG_TRACE_STR("No transactions for me to flush!");
+		goto flush_data;
+	}
+
+	/* flush all pending commits and checkpoint the journal. */
+	down_write(&journal->trans_barrier);
+
+	/* check again, this time locked :) */
+	if (atomic_read(&journal->num_trans) == 0) {
+		up_write(&journal->trans_barrier);
+		goto flush_data;
+	}
+
+	journal_lock_updates(journal->k_journal);
+	status = journal_flush(journal->k_journal);
+
+	up_write(&journal->trans_barrier);
+	if (status < 0) {
+		journal_unlock_updates(journal->k_journal);
+
+		LOG_ERROR_STATUS(status);
+		goto finally;
+	}
+
+	LOG_TRACE_ARGS("flushing %d transactions\n", 
+		       atomic_read(&journal->num_trans));
+
+	/* now we can run an unlock against any pending handles and
+	 * release them. */
+	down(&journal->commit_sem);
+	down(&commit->c_lock);
+
+	/* Once we've got commit_sem, we can let transactions start
+	 * again -- it should protect us against people mucking with
+	 * the commited list... */
+	journal_unlock_updates(journal->k_journal);
+
+	/* we want to take everything off the commited list and
+	 * process it independently, so we can drop the trans_lock
+	 * earlier. */
+	if (!list_empty(&journal->commited)) {
+		list_splice(&journal->commited , &commit->c_list);
+		INIT_LIST_HEAD(&journal->commited);
+	}
+	up(&commit->c_lock);
+	up(&journal->commit_sem);
+
+	osb->needs_flush = 0;
+
+	down(&commit->c_lock);
+	list_for_each_safe(p, n, &commit->c_list) {
+		handle = list_entry(p, ocfs_journal_handle, h_list);
+		tmpstat = ocfs_handle_release_locks(handle, TRANS_CACHE);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS((status = tmpstat));
+		list_del(&(handle->h_list));
+		kfree(handle);
+
+		atomic_dec(&journal->num_trans);
+	}
+	up(&commit->c_lock);
+
+flush_data:
+	/* flush data buffers if asked. */
+	if (data_flush)
+		ocfs_sync_blockdev(osb->sb);
+
+finally:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_commit_cache */
+
+/* 
+ * JBD in 2.4 kernels uses lock_kernel pretty heavily. Most of the
+ * time we get that from the VFS, but we do transactions without BKL
+ * sometimes. 2.6 does things right and spinlocks around it's
+ * structures so at least this junk won't last too long...
+ *
  * These aren't in ocfs_compat.h because they require wayyyy to much
  * #included.
  */
@@ -118,14 +219,50 @@
 /* these two gained another argument during 2.6 */
 static inline int ocfs_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
 {
-	return journal_get_write_access(handle, bh);
+	int ret;
+
+	lock_kernel();
+	ret = journal_get_write_access(handle, bh);
+	unlock_kernel();
+	return ret;
 }
 
 static inline int ocfs_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
 {
-	return journal_get_undo_access(handle, bh);
+	int ret;
+
+	lock_kernel();
+	ret = journal_get_undo_access(handle, bh);
+	unlock_kernel();
+	return ret;
 }
 
+static inline int ocfs_commit_cache24 (ocfs_super * osb, int data_flush)
+{
+	int ret;
+
+	lock_kernel();
+	ret = ocfs_commit_cache(osb, data_flush);
+	unlock_kernel();
+	return ret;
+}
+
+static inline int ocfs_journal_flush24(ocfs_journal *journal)
+{
+	int ret;
+
+	lock_kernel();
+	ret = ocfs_journal_flush(journal);
+	unlock_kernel();
+	return ret;
+}
+
+#undef ocfs_commit_cache
+#undef ocfs_journal_flush
+
+#define ocfs_commit_cache  ocfs_commit_cache24
+#define ocfs_journal_flush ocfs_journal_flush24
+
 #undef journal_get_write_access
 #undef journal_get_undo_access
 
@@ -135,8 +272,6 @@
 	ocfs_journal_get_undo_access(handle, bh)
 #endif
 
-
-/* DO NOT EVER CALL THIS FUNCTION WITH A LOCKED BUFFER HEAD! */
 ocfs_journal_handle * ocfs_start_trans(ocfs_super *osb, int max_buffs) 
 {
 	ocfs_journal_handle * retval = NULL;
@@ -379,21 +514,6 @@
 	}								\
 } while (0)
 
-static inline int ocfs_journal_flush(ocfs_journal *journal) 
-{
-	int retval;
-
-	down_write(&journal->trans_barrier);
-	journal_lock_updates(journal->k_journal);
-
-	retval = journal_flush(journal->k_journal);
-
-	journal_unlock_updates(journal->k_journal);
-	up_write(&journal->trans_barrier);
-
-	return(retval);
-}
-
 /*
  * ocfs_commit_trans
  */
@@ -1636,97 +1756,3 @@
 	return 0;
 }
 
-/* 
- * ocfs_commit_cache()
- *
- * This is in journal.c for lack of a better place.
- *
- * This function must be called with the trans_lock held.
- * No, really this function MUST be called with the trans_lock held!
- *
- * In any case, it will release the trans lock for you.
- */
-static int ocfs_commit_cache(ocfs_super *osb, int data_flush)
-{
-	int status = 0, tmpstat;
-	ocfs_journal * journal = NULL;
-	struct list_head *p, *n;
-	ocfs_journal_handle *handle = NULL;
-	ocfs_commit_task *commit = osb->commit;
-
-	LOG_ENTRY_ARGS("(data_flush = %u)\n", data_flush);
-
-	journal = osb->journal;
-
-	if (atomic_read(&journal->num_trans) == 0) {
-		LOG_TRACE_STR("No transactions for me to flush!");
-		goto flush_data;
-	}
-
-	/* flush all pending commits and checkpoint the journal. */
-	down_write(&journal->trans_barrier);
-
-	/* check again, this time locked :) */
-	if (atomic_read(&journal->num_trans) == 0) {
-		up_write(&journal->trans_barrier);
-		goto flush_data;
-	}
-
-	journal_lock_updates(journal->k_journal);
-	status = journal_flush(journal->k_journal);
-
-	up_write(&journal->trans_barrier);
-	if (status < 0) {
-		journal_unlock_updates(journal->k_journal);
-
-		LOG_ERROR_STATUS(status);
-		goto finally;
-	}
-
-	LOG_TRACE_ARGS("flushing %d transactions\n", 
-		       atomic_read(&journal->num_trans));
-
-	/* now we can run an unlock against any pending handles and
-	 * release them. */
-	down(&journal->commit_sem);
-	down(&commit->c_lock);
-
-	/* Once we've got commit_sem, we can let transactions start
-	 * again -- it should protect us against people mucking with
-	 * the commited list... */
-	journal_unlock_updates(journal->k_journal);
-
-	/* we want to take everything off the commited list and
-	 * process it independently, so we can drop the trans_lock
-	 * earlier. */
-	if (!list_empty(&journal->commited)) {
-		list_splice(&journal->commited , &commit->c_list);
-		INIT_LIST_HEAD(&journal->commited);
-	}
-	up(&commit->c_lock);
-	up(&journal->commit_sem);
-
-	osb->needs_flush = 0;
-
-	down(&commit->c_lock);
-	list_for_each_safe(p, n, &commit->c_list) {
-		handle = list_entry(p, ocfs_journal_handle, h_list);
-		tmpstat = ocfs_handle_release_locks(handle, TRANS_CACHE);
-		if (tmpstat < 0)
-			LOG_ERROR_STATUS((status = tmpstat));
-		list_del(&(handle->h_list));
-		kfree(handle);
-
-		atomic_dec(&journal->num_trans);
-	}
-	up(&commit->c_lock);
-
-flush_data:
-	/* flush data buffers if asked. */
-	if (data_flush)
-		ocfs_sync_blockdev(osb->sb);
-
-finally:
-	LOG_EXIT_STATUS (status);
-	return status;
-}				/* ocfs_commit_cache */



More information about the Ocfs2-commits mailing list