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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Sep 3 15:42:56 CDT 2004


Author: mfasheh
Date: 2004-09-03 15:42:54 -0500 (Fri, 03 Sep 2004)
New Revision: 1420

Modified:
   trunk/src/alloc.c
   trunk/src/file.c
   trunk/src/inode.c
   trunk/src/journal.c
   trunk/src/namei.c
   trunk/src/ocfs_journal.h
Log:
* allow us to take cluster locks outside of transactions. This is the
  right way to do thing, and paves the way for a number of enhancements,
  including less starvation potential, and fewer journal / dlm
  deadlocks. We still have system files left to do.



Modified: trunk/src/alloc.c
===================================================================
--- trunk/src/alloc.c	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/alloc.c	2004-09-03 20:42:54 UTC (rev 1420)
@@ -341,7 +341,7 @@
 
 	/* start the transaction here to preserve ordering with the
 	 * bitmap io_sems... */
-	handle = ocfs_start_trans(osb, credits);
+	handle = ocfs_start_trans(osb, NULL, credits);
 	if (!handle) {
 		status = -ENOMEM;
 		LOG_ERROR_STATUS(status);

Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/file.c	2004-09-03 20:42:54 UTC (rev 1420)
@@ -424,7 +424,6 @@
 {
 	int status = 0;
 	ocfs2_dinode *fileEntry = NULL;
-	u32 lock_flags = 0;
 	struct buffer_head *bh = NULL;
 	ocfs_journal_handle *handle = NULL;
 
@@ -436,21 +435,29 @@
 	}
 #endif
 
-	/* Start a transaction - need a minimal amount of block credits (1) */
-	handle = ocfs_start_trans(osb, 1);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS(status);
 		goto leave;
 	}
 
-	status = ocfs_acquire_lock (osb, OCFS_LKM_EXMODE, lock_flags,
-				    &bh, inode);
+	status = ocfs_acquire_lock (osb, OCFS_LKM_EXMODE, 0, &bh, inode);
 	if (status < 0) {
 		if (status != -EINTR)
 			LOG_ERROR_STATUS (status);
 		goto leave;
 	}
 
+	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, FLAG_FILE_UPDATE_OIN, 
+			     inode);
+
+	/* Start a transaction - need a minimal amount of block credits (1) */
+	handle = ocfs_start_trans(osb, handle, 1);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
 	fileEntry = (ocfs2_dinode *) bh->b_data;
 
 	if (!IS_VALID_FILE_ENTRY(fileEntry)) {
@@ -481,12 +488,6 @@
 leave:
 
 	if (handle) {
-		if (!status)
-			lock_flags |= FLAG_FILE_UPDATE_OIN;
-
-		ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 
-				     lock_flags, inode);
-
 		if (status < 0)
 			ocfs_abort_trans(handle);
 		else
@@ -863,8 +864,7 @@
 
 	LOG_TRACE_ARGS("new_alloc_size = %llu\n", new_alloc_size);
 
-	/* start a journal transaction */
-	handle = ocfs_start_trans(osb, OCFS_FILE_TRUNCATE_CREDITS);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
 		goto leave;
@@ -889,6 +889,12 @@
 		goto leave;
 	}
 
+	handle = ocfs_start_trans(osb, handle, OCFS_FILE_TRUNCATE_CREDITS);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
 	/* add this fe to the journal transaction */
 	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
@@ -1062,8 +1068,7 @@
 		credits = ocfs_calc_extend_credits(osb->sb,
 						   (__u32) alloc_size); 
 
-		/* cannot call start_trans with a locked buffer head. */
-		handle = ocfs_start_trans(osb, credits);
+		handle = ocfs_alloc_handle(osb);
 		if (handle == NULL) {
 			LOG_ERROR_STATUS(status = -ENOMEM);
 			goto leave;
@@ -1080,6 +1085,12 @@
 				     OCFS_LKM_EXMODE,
 				     FLAG_FILE_EXTEND|FLAG_FILE_UPDATE_OIN,
 				     inode);
+
+		handle = ocfs_start_trans(osb, handle, credits);
+		if (handle == NULL) {
+			LOG_ERROR_STATUS(status = -ENOMEM);
+			goto leave;
+		}
 	} else {
 		handle = passed_handle;
 	}

Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/inode.c	2004-09-03 20:42:54 UTC (rev 1420)
@@ -604,27 +604,6 @@
 		goto clear_inode;
 	}
 
-	lock_kernel();
-
-	/* Oop, lets be carefull of lock / trans ordering here... */
-	handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
-	if (handle == NULL) {
-		unlock_kernel();
-		LOG_ERROR_STATUS(-ENOMEM);
-		goto clear_inode;
-	}
-
-	ocfs_handle_add_inode(handle, orphan_dir_inode);
-
-	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, FLAG_DIR,
-				   &orphan_dir_bh, orphan_dir_inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail_locked;
-	}
-	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, FLAG_DIR,
-			     orphan_dir_inode);
-
 	/* acquire_lock and friends will igrab / iput this guy, so we
 	 * take an extra ref. to avoid recursive calls to
 	 * delete_inode. */
@@ -641,30 +620,51 @@
 		 * about deleting it. */
 		if (status != -EBUSY)
 			LOG_ERROR_STATUS(status);
-		goto bail_locked;
+		goto clear_inode;
 	}
 
-	/* check OCFS_SYNC_FLAG_ORPHANED */
 	fe = (ocfs2_dinode *) fe_bh->b_data;
 	if (!(fe->i_flags & OCFS2_ORPHANED_FL)) {
 		/* for lack of a better error? */
 		status = -EEXIST;
 		LOG_ERROR_STATUS(status);
-		goto bail_locked;
+		goto clear_inode;
 	}
 
 	/* has someone already deleted us?! baaad... */
 	if (fe->i_dtime) {
 		status = -EEXIST;
 		LOG_ERROR_STATUS(status);
-		goto bail_locked;
+		goto clear_inode;
 	}
 
 	if (fe->i_links_count) {
 		status = -EBUSY;
 		LOG_ERROR_STATUS(status);
+		goto clear_inode;
+	}
+
+	/* Oop, lets be carefull of lock / trans ordering here... */
+	handle = ocfs_start_trans(osb, NULL, OCFS_FILE_DELETE_CREDITS);
+	if (handle == NULL) {
+		unlock_kernel();
+		LOG_ERROR_STATUS(-ENOMEM);
+		goto clear_inode;
+	}
+
+	ocfs_handle_add_inode(handle, orphan_dir_inode);
+
+	lock_kernel();
+
+	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, FLAG_DIR,
+				   &orphan_dir_bh, orphan_dir_inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
 		goto bail_locked;
 	}
+	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, FLAG_DIR,
+			     orphan_dir_inode);
+
 	status = ocfs_orphan_del(osb, handle, orphan_dir_inode, inode, 
 				 orphan_dir_bh);
 
@@ -706,13 +706,14 @@
 
 	unlock_kernel();
 
+clear_inode:
 	if (orphan_dir_bh)
 		brelse(orphan_dir_bh);
 	if (fe_bh)
 		brelse(fe_bh);
+	if (orphan_dir_inode)
+		iput(orphan_dir_inode);
 
-	iput(orphan_dir_inode);
-clear_inode:
 	/* we must clear inode. */
 	clear_inode(inode);
 	LOG_EXIT();

Modified: trunk/src/journal.c
===================================================================
--- trunk/src/journal.c	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/journal.c	2004-09-03 20:42:54 UTC (rev 1420)
@@ -66,6 +66,7 @@
 static void ocfs_handle_move_locks(ocfs_journal *journal, 
 				   ocfs_journal_handle *handle);
 static void ocfs_journal_optimize_lock_list(ocfs_journal *journal);
+static void ocfs_commit_unstarted_handle(ocfs_journal_handle *handle);
 
 static void ocfs_journal_optimize_lock_list(ocfs_journal *journal)
 {
@@ -152,6 +153,8 @@
 static int ocfs_commit_cache(ocfs_super *osb)
 {
 	int status = 0, tmpstat;
+	unsigned int flushed  = 0;
+	unsigned int cmt_locks;
 	ocfs_journal * journal = NULL;
 	struct list_head *p, *n;
 	ocfs_journal_lock *lock = NULL;
@@ -167,15 +170,17 @@
 	down_write(&journal->trans_barrier);
 
 	if (atomic_read(&journal->num_trans) == 0) {
-		up_write(&journal->trans_barrier);
 		LOG_TRACE_STR("No transactions for me to flush!");
-		goto finally;
+		/* now, we may have locks left to drop even though no
+		 * transactions are in the journal. */
+
+		goto drop_locks;
 	}
 
 	journal_lock_updates(journal->k_journal);
 	status = journal_flush(journal->k_journal);
+	journal_unlock_updates(journal->k_journal);
 	if (status < 0) {
-		journal_unlock_updates(journal->k_journal);
 		up_write(&journal->trans_barrier);
 		LOG_ERROR_STATUS(status);
 		goto finally;
@@ -183,19 +188,18 @@
 
 	ocfs_inc_trans_id(journal);
 
-#ifdef VERBOSE_COMMIT_THREAD
-	printk("(%u) commit_thread: flushed %u transactions, releasing %u "
-	       "locks\n", current->pid, atomic_read(&journal->num_trans),
-	       atomic_read(&journal->num_cmt_locks));
-#endif
+drop_locks:
+	flushed = atomic_read(&journal->num_trans);
 	atomic_set(&journal->num_trans, 0);
 
 	/* Step 2: Drop any locks acquired during transactions which
 	 * have just been checkpointed.  */
 	spin_lock(&journal->cmt_lock);
 
+	cmt_locks = atomic_read(&journal->num_cmt_locks);
+
 	atomic_add(atomic_read(&journal->num_cmt_locks),
-		    &journal->num_chkpt_locks);
+		   &journal->num_chkpt_locks);
 	atomic_set(&journal->num_cmt_locks, 0);
 
 	/* move the locks off each inode onto the commit threads list. */
@@ -221,13 +225,21 @@
 	 * Once we've got cmt_lock, we can let
 	 * transactions start again -- it should protect us against
 	 * people mucking with the committed list... */
-	journal_unlock_updates(journal->k_journal);
 	up_write(&journal->trans_barrier);
 
+#ifdef VERBOSE_COMMIT_THREAD
+	if (flushed || cmt_locks)
+		printk("(%u) commit_thread: flushed %u transactions, "
+		       "releasing %u locks\n", current->pid, flushed, 
+		       cmt_locks);
+#endif
+
 	ocfs_journal_optimize_lock_list(journal);
 #ifdef VERBOSE_COMMIT_THREAD
-	printk("(%u) commit_thread: after optimization, %u locks to release\n",
-	       current->pid, atomic_read(&journal->num_chkpt_locks));
+	if (flushed || cmt_locks)
+		printk("(%u) commit_thread: after optimization, %u locks "
+		       "to release\n", current->pid, 
+		       atomic_read(&journal->num_chkpt_locks));
 #endif
 
 	p = n = NULL;
@@ -370,9 +382,42 @@
 	ocfs_journal_get_undo_access(handle, bh)
 #endif
 
-ocfs_journal_handle * ocfs_start_trans(ocfs_super *osb, int max_buffs) 
+ocfs_journal_handle * ocfs_alloc_handle(ocfs_super *osb)
 {
 	ocfs_journal_handle * retval = NULL;
+
+	retval = ocfs_malloc(sizeof(*retval));
+	if (!retval) {
+		LOG_ERROR_STR("Failed to allocate memory for journal handle!");
+		return(NULL);
+	}
+	memset(retval, 0, sizeof(*retval));
+
+	retval->max_buffs = 0;
+	retval->num_buffs = 0;
+	retval->num_locks = 0;
+	retval->num_co = 0;
+	retval->commit_bits = NULL;
+	retval->buffs = NULL;
+	retval->co_buffs = NULL;
+	retval->k_handle = NULL;
+
+	INIT_LIST_HEAD(&(retval->h_list));
+	INIT_LIST_HEAD(&(retval->locks));
+	INIT_LIST_HEAD(&(retval->inode_list));
+	retval->journal = osb->journal;
+	retval->osb = osb;
+
+	return(retval);
+}
+
+/* pass it NULL and it will allocate a new handle object for you.  If
+ * you pass it a handle however, it may still return NULL, in which
+ * case it has free'd the passed handle for you. */
+ocfs_journal_handle * ocfs_start_trans(ocfs_super *osb, 
+				       ocfs_journal_handle *handle, 
+				       int max_buffs) 
+{
 	journal_t * journal = osb->journal->k_journal;
 
 	LOG_ENTRY_ARGS ("(max_buffs = %d)\n", max_buffs);
@@ -388,63 +433,56 @@
 		BUG();
 	}
 
-	retval = ocfs_malloc(sizeof(*retval));
-	if (!retval) {
+	if (!handle)
+		handle = ocfs_alloc_handle(osb);
+	if (!handle) {
 		LOG_ERROR_STR("Failed to allocate memory for journal handle!");
 		goto done_free;
 	}
-	memset(retval, 0, sizeof(*retval));
 
-	retval->buffs = ocfs_malloc(sizeof(struct buffer_head *) * max_buffs);
-	if (!retval->buffs) {
+	handle->buffs = ocfs_malloc(sizeof(struct buffer_head *) * max_buffs);
+	if (!handle->buffs) {
 		LOG_ERROR_STR("Failed to allocate memory for journal buffs!");
 		goto done_free;
 	}
-	memset(retval->buffs, 0, sizeof(struct buffer_head *) * max_buffs);
+	memset(handle->buffs, 0, sizeof(struct buffer_head *) * max_buffs);
 
-	retval->co_buffs = ocfs_malloc(sizeof(ocfs_journal_copyout)*max_buffs);
-	if (!retval->co_buffs) {
+	handle->co_buffs = ocfs_malloc(sizeof(ocfs_journal_copyout)*max_buffs);
+	if (!handle->co_buffs) {
 		LOG_ERROR_STR("Failed to allocate memory for journal co_buffs!");
 		goto done_free;
 	}
-	memset(retval->co_buffs, 0, sizeof(ocfs_journal_copyout) * max_buffs);
+	memset(handle->co_buffs, 0, sizeof(ocfs_journal_copyout) * max_buffs);
 
-	INIT_LIST_HEAD(&(retval->h_list));
-	INIT_LIST_HEAD(&(retval->locks));
-	INIT_LIST_HEAD(&(retval->inode_list));
-	retval->max_buffs = max_buffs;
-	retval->num_buffs = 0;
-	retval->num_locks = 0;
-	retval->num_co = 0;
+	handle->max_buffs = max_buffs;
 
-	retval->journal = osb->journal;
-	retval->osb = osb;
-	retval->commit_bits = NULL;
-
 	down_read(&osb->journal->trans_barrier);
 
 	/* actually start the transaction now */
-	retval->k_handle = journal_start(journal, max_buffs);
-	if (IS_ERR(retval->k_handle)) {
+	handle->k_handle = journal_start(journal, max_buffs);
+	if (IS_ERR(handle->k_handle)) {
 		up_read(&osb->journal->trans_barrier);
 
 		LOG_ERROR_STR("journal_start() failed!");
-		LOG_ERROR_STATUS((int)PTR_ERR(retval->k_handle));
-		retval->k_handle = NULL;
+		LOG_ERROR_STATUS((int)PTR_ERR(handle->k_handle));
+		handle->k_handle = NULL;
 		goto done_free;
 	}
 
 	atomic_inc(&(osb->journal->num_trans));
+	handle->flags |= OCFS_HANDLE_STARTED;
 
-	LOG_EXIT_PTR(retval);
-	return(retval);
+	LOG_EXIT_PTR(handle);
+	return(handle);
 
 done_free:
 
-	if (retval) {
-		if (retval->buffs)
-			kfree(retval->buffs);
-		kfree(retval);
+	if (handle) {
+		ocfs_commit_unstarted_handle(handle);
+
+		if (handle->buffs)
+			kfree(handle->buffs);
+		kfree(handle);
 	}
 	LOG_EXIT_PTR(NULL);
 	return(NULL);
@@ -452,12 +490,10 @@
 
 void ocfs_handle_add_inode(ocfs_journal_handle *handle, struct inode *inode)
 {
-	if (!handle)
-		BUG();
+	OCFS_ASSERT(handle);
+	OCFS_ASSERT(inode);
+	OCFS_ASSERT((handle->flags & OCFS_HANDLE_STARTED));
 
-	if (!inode)
-		BUG();
-
 	if (OCFS_I(inode)->ip_handle == handle) {
 		/* sanity check */
 		if (list_empty(&OCFS_I(inode)->ip_handle_list))
@@ -522,6 +558,32 @@
 	}								\
 } while (0)
 
+/* This is trivial so we do it out of the main commit/abort
+ * paths. Beware, it can be called from start_trans too! */
+static void ocfs_commit_unstarted_handle(ocfs_journal_handle *handle)
+{
+	ocfs_super *osb;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT(!(handle->flags & OCFS_HANDLE_STARTED));
+	OCFS_ASSERT(!handle->commit_bits);
+	OCFS_ASSERT(!handle->num_co);
+	OCFS_ASSERT(!handle->num_buffs);
+
+	osb = handle->osb;
+	/* You are allowed to add journal locks before the transaction
+	 * has started. */
+	ocfs_handle_move_locks(osb->journal, handle);
+	spin_lock(&osb->journal->cmt_lock);
+	osb->needs_flush = 1;
+	spin_unlock(&osb->journal->cmt_lock);
+
+	kfree(handle);
+	LOG_EXIT();
+	return;
+}
+
 /*
  * ocfs_commit_trans
  */
@@ -535,9 +597,13 @@
 	ocfs_bitmap_free_head *commit_head;
 	LOG_ENTRY();
 
-	if (!handle)
-		BUG();
+	OCFS_ASSERT(handle);
 
+	if (!(handle->flags & OCFS_HANDLE_STARTED)) {
+		ocfs_commit_unstarted_handle(handle);
+		goto bail;
+	}
+
 	osb = handle->osb;
 	kern_handle = handle->k_handle;
 	kern_trans = kern_handle->h_transaction;
@@ -597,6 +663,7 @@
 
 	kfree(handle);
 
+bail:
 	LOG_EXIT();
 
 	return;
@@ -622,6 +689,11 @@
 	OCFS_ASSERT(handle);
 	OCFS_ASSERT(!(handle->flags & OCFS_HANDLE_ALWAYS_COMMITS));
 
+	if (!(handle->flags & OCFS_HANDLE_STARTED)) {
+		ocfs_commit_unstarted_handle(handle);
+		goto bail;
+	}
+
 	osb = handle->osb;
 	journal = osb->journal;
 
@@ -724,6 +796,7 @@
 		kfree(handle->buffs);
 	kfree(handle);
 
+bail:
 	LOG_EXIT();
 	return;
 } /* ocfs_abort_trans */
@@ -737,6 +810,8 @@
 	int i;
 	int found = 0;
 
+	OCFS_ASSERT((handle->flags & OCFS_HANDLE_STARTED));
+
 	LOG_ENTRY_ARGS("(bh->b_blocknr=%llu, type=%d (\"%s\"), "
 		       "bh->b_size = %hu)\n", 
 		       (unsigned long long)bh->b_blocknr, type, 
@@ -855,6 +930,8 @@
 	int status = -1;
 	int i;
 
+	OCFS_ASSERT((handle->flags & OCFS_HANDLE_STARTED));
+
 	LOG_ENTRY_ARGS("(bh->b_blocknr=%llu)\n",
 			(unsigned long long)bh->b_blocknr);
 
@@ -940,7 +1017,9 @@
 
 	list_add_tail(&(lock->lock_list), &(handle->locks));
 	handle->num_locks++;
+	spin_lock(&handle->journal->cmt_lock);
 	atomic_inc(&handle->journal->num_cmt_locks);
+	spin_unlock(&handle->journal->cmt_lock);
 
 	LOG_EXIT();
 	return;
@@ -1728,7 +1807,6 @@
 
 static int ocfs_wait_on_mount(ocfs_super *osb)
 {
-
 retry:
 	if (atomic_read(&osb->vol_state) == VOLUME_MOUNTED)
 		return 0;
@@ -1858,12 +1936,15 @@
 			/* we can trust num_trans here because we're
 			 * in shutdown and nobody other than ourselves
 			 * should be able to start more. */
-			if (atomic_read(&journal->num_trans) == 0)
+			if ((atomic_read(&journal->num_trans) == 0)
+			    && (atomic_read(&journal->num_cmt_locks) == 0))
 				break;
 #ifdef VERBOSE_COMMIT_THREAD
-			printk("(%u) commit_thread: %u transactions pending "
-			       "on shutdown\n",
-			       current->pid, atomic_read(&journal->num_trans));
+			printk("(%u) commit_thread: %u transactions, %u locks"
+			       "pending on shutdown\n", 
+			       current->pid, 
+			       atomic_read(&journal->num_trans),
+			       atomic_read(&journal->num_cmt_locks));
 #endif
 			goto skip_sleep;
 		}

Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/namei.c	2004-09-03 20:42:54 UTC (rev 1420)
@@ -231,8 +231,7 @@
 		goto leave;
 	}
 
-	/* start the transaction */
-	handle = ocfs_start_trans(osb, OCFS_MKNOD_CREDITS);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
 		goto leave;
@@ -257,6 +256,12 @@
 		goto leave;
 	}
 
+	handle = ocfs_start_trans(osb, handle, OCFS_MKNOD_CREDITS);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
 	/* do the real work now. */
 	status = ocfs_mknod_locked(osb, dir, dentry, mode, dev,
 				   &new_fe_bh, parent_fe_bh, handle, inode);
@@ -354,9 +359,8 @@
 	else if (status < 0 && status != -EINTR)
 		LOG_ERROR_STATUS(status);
 
-	if (new_fe_bh) {
+	if (new_fe_bh) 
 		brelse(new_fe_bh);
-	}
 
 	if (parent_fe_bh != NULL) 
 		brelse(parent_fe_bh);
@@ -582,13 +586,11 @@
 		goto bail;
 	}
 
-	/* mknod credits is a bit heavy, but we can tune this later. */
-	handle = ocfs_start_trans(osb, OCFS_MKNOD_CREDITS);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		err = -ENOMEM;
 		goto bail;
 	}
-	ocfs_handle_set_always_commits(handle, 1);
 
 	down_write(&OCFS_I(dir)->ip_io_sem);
 	drop_dir_sem = 1;
@@ -619,6 +621,14 @@
 		goto bail;
 	}
 
+	/* mknod credits is a bit heavy, but we can tune this later. */
+	handle = ocfs_start_trans(osb, handle, OCFS_MKNOD_CREDITS);
+	if (handle == NULL) {
+		err = -ENOMEM;
+		goto bail;
+	}
+	ocfs_handle_set_always_commits(handle, 1);
+
 	err = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
 	if (err < 0) {
 		LOG_ERROR_STATUS(err);
@@ -703,17 +713,16 @@
 		status = -EPERM;
 		goto bail;
 	}
-	status = -EFAIL;
 
-	down_write(&OCFS_I(dir)->ip_io_sem);
-	down_write(&OCFS_I(inode)->ip_io_sem);
-
-	handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
-		goto leave;
+		goto bail;
 	}
 
+	down_write(&OCFS_I(dir)->ip_io_sem);
+	down_write(&OCFS_I(inode)->ip_io_sem);
+
 	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, FLAG_DIR, 
 				   &parent_node_bh, parentInode);
 	if (status < 0) {
@@ -755,6 +764,12 @@
 		}
 	}
 
+	handle = ocfs_start_trans(osb, handle, OCFS_FILE_DELETE_CREDITS);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto leave;
+	}
+
 	status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
@@ -763,7 +778,8 @@
 
 	fe = (ocfs2_dinode *) fe_bh->b_data;
 	if (fe->i_links_count != inode->i_nlink) {
-		printk("ocfs_unlink: hmm, inode has nlink = %u, fe has link_cnt = %u. Setting inode from fe.\n",
+		printk("ocfs_unlink: hmm, inode has nlink = %u, fe has "
+		       "link_cnt = %u. Setting inode from fe.\n",
 		       inode->i_nlink, fe->i_links_count);
 		inode->i_nlink = fe->i_links_count;
 	}
@@ -1017,8 +1033,7 @@
 		goto bail;
 	}
 
-	/* start our transaction */
-	handle = ocfs_start_trans(osb, OCFS_FILE_RENAME_CREDITS);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS(status = -ENOMEM);
 		goto bail;
@@ -1161,7 +1176,15 @@
 			       "new_blkno=%llu newfebh=%p bhblocknr=%llu\n",
 			       new_de, newfe_blkno, newfe_bh, newfe_bh ?
 			       (unsigned long long)newfe_bh->b_blocknr : 0ULL);
+	}
 
+	handle = ocfs_start_trans(osb, handle, OCFS_FILE_RENAME_CREDITS);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS(status = -ENOMEM);
+		goto bail;
+	}
+
+	if (new_de) {
 		status = ocfs_journal_access(handle, newfe_bh, 
 					     OCFS_JOURNAL_ACCESS_WRITE);
 		if (status < 0) {
@@ -1212,7 +1235,6 @@
 			LOG_ERROR_STATUS(status);
 			goto finally;
 		}
-
 	} else {
 		/* if the name was not found in new_dir, add it now */
 		status = ocfs_add_entry (handle, new_dentry, old_inode, 
@@ -1498,8 +1520,7 @@
 
 	credits = ocfs_calc_symlink_credits(sb, newsize);
 
-	/* start the transaction */
-	handle = ocfs_start_trans(osb, credits);
+	handle = ocfs_alloc_handle(osb);
 	if (handle == NULL) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
 		goto bail;
@@ -1523,6 +1544,12 @@
 		goto abort_trans;
 	}
 
+	handle = ocfs_start_trans(osb, handle, credits);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS (status = -ENOMEM);
+		goto bail;
+	}
+
 	status = ocfs_mknod_locked(osb, dir, dentry, 
  				   S_IFLNK | S_IRWXUGO, 0,
  				   &new_fe_bh, parent_fe_bh, handle,

Modified: trunk/src/ocfs_journal.h
===================================================================
--- trunk/src/ocfs_journal.h	2004-09-03 20:41:38 UTC (rev 1419)
+++ trunk/src/ocfs_journal.h	2004-09-03 20:42:54 UTC (rev 1420)
@@ -212,13 +212,14 @@
 	struct list_head     inode_list;
 };
 
+#define OCFS_HANDLE_STARTED			1
 /* should we sync-commit this handle? */
-#define OCFS_HANDLE_SYNC			1
+#define OCFS_HANDLE_SYNC			2
 /* This is really the right way to do things, but until we fix all the
  * code, it's a performance improvement for a handle which never
  * aborts. Should be set before passing any buffers to
  * journal_access! */
-#define OCFS_HANDLE_ALWAYS_COMMITS		2
+#define OCFS_HANDLE_ALWAYS_COMMITS		4
 
 static inline void ocfs_handle_free_all_copyout(ocfs_journal_handle *handle)
 {
@@ -289,12 +290,18 @@
 /*
  *  Transaction Handling:
  *  Manage the lifetime of a transaction handle.
- *
+ *  
+ *  ocfs_alloc_handle     - Only allocate a handle so we can start putting 
+ *                          cluster locks on it. To actually change blocks, 
+ *                          call ocfs_start_trans with the handle returned 
+ *                          from this function. You may call ocfs_commit_trans
+ *                          and ocfs_abort_trans at any time in the lifetime 
+ *                          of a handle.
  *  ocfs_start_trans      - Begin a transaction. Give it an upper estimate of 
  *                          the number of blocks that will be changed during 
  *                          this handle.
  *  ocfs_commit_trans     - Complete a handle.
- *  ocfs_abort_trans      - Abort a running handle.
+ *  ocfs_abort_trans      - Abort a handle.
  *  ocfs_journal_access   - Notify the handle that we want to journal this 
  *                          buffer. Will have to call ocfs_journal_dirty once
  *                          we've actually dirtied it. Type is one of . or .
@@ -309,7 +316,10 @@
 /* You must always start_trans with a number of buffs > 0, but it's
  * perfectly legal to go through an entire transaction without having
  * dirtied any buffers. */
-ocfs_journal_handle *ocfs_start_trans(struct _ocfs_super *osb, int max_buffs);
+ocfs_journal_handle *ocfs_alloc_handle(ocfs_super *osb);
+ocfs_journal_handle *ocfs_start_trans(struct _ocfs_super *osb, 
+				      ocfs_journal_handle *handle, 
+				      int max_buffs);
 void                 ocfs_commit_trans(ocfs_journal_handle *handle);
 void                 ocfs_abort_trans(ocfs_journal_handle *handle);
 /*



More information about the Ocfs2-commits mailing list