[Ocfs2-commits] rev 19 - in trunk: . src src/inc

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Feb 2 19:29:18 CST 2004


Author: manish
Date: 2004-02-02 19:29:16 -0600 (Mon, 02 Feb 2004)
New Revision: 19

Modified:
   trunk/TODO
   trunk/src/dcache.c
   trunk/src/dir.c
   trunk/src/dlm.c
   trunk/src/file.c
   trunk/src/hash.c
   trunk/src/inc/io.h
   trunk/src/inc/journal.h
   trunk/src/inc/ocfs.h
   trunk/src/inc/proto.h
   trunk/src/inode.c
   trunk/src/io.c
   trunk/src/journal.c
   trunk/src/namei.c
   trunk/src/nm.c
   trunk/src/osb.c
   trunk/src/proc.c
   trunk/src/super.c
   trunk/src/util.c
Log:
Sync


Modified: trunk/TODO
===================================================================
--- trunk/TODO	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/TODO	2004-02-03 01:29:16 UTC (rev 19)
@@ -14,6 +14,9 @@
 
 * finish mkfs to really create a filesystem.
 
+* ocfs_commit_trans should not have a return value -- if we fail at that
+  point, we're in big trouble.
+
 * System files should be locked with cache lock, and we need inodes
   for them so that we can cache our reads to them. This can also count
   for the main bitmap. Data writes to the bitmap files can be

Modified: trunk/src/dcache.c
===================================================================
--- trunk/src/dcache.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/dcache.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -2,6 +2,9 @@
 
 #define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_EXTENT
 
+
+static int ocfs_empty_func(struct dentry *dentry, void *ignore);
+
 /*
  * ocfs_dentry_revalidate()
  *
@@ -118,14 +121,31 @@
 	return ret;
 }				/* ocfs_dentry_revalidate */
 
+
+/* exits if it finds any hashed dentries */
+static int ocfs_empty_func(struct dentry *dentry, void *ignore)
+{
+	return 1;
+}
+
+
 /*
  * ocfs_empty()
  *
  */
 int ocfs_empty (struct dentry *dentry)
 {
+	return ocfs_foreach_child (dentry, ocfs_empty_func, NULL);
+}
+
+/*
+ * ocfs_foreach_child()
+ *
+ */
+int ocfs_foreach_child (struct dentry *dentry, int (*func)(struct dentry *, void *), void *data)
+{
 	struct list_head *list;
-	int ret;
+	int ret, done;
 
 	LOG_ENTRY_ARGS ("(0x%08x, '%*s')\n", dentry,
                         dentry->d_name.len, dentry->d_name.name);
@@ -133,22 +153,23 @@
 	spin_lock (&dcache_lock);
 	list = dentry->d_subdirs.next;
 
+	ret = 1;
 	while (list != &dentry->d_subdirs) {
 		struct dentry *de = list_entry (list, struct dentry, d_child);
 
 		if (de->d_inode && !d_unhashed (de)) {
-			spin_unlock (&dcache_lock);
-			ret = 0;
-			goto bail;
+			done = func(de, data);
+			if (done) {
+				ret = 0;
+				break;
+			}
 		}
 		list = list->next;
 	}
 	spin_unlock (&dcache_lock);
-	ret = 1;
 
-bail:
 	LOG_EXIT_LONG (ret);
 	return ret;
-}				/* ocfs_empty */
+}				/* ocfs_foreach_child */
 
 

Modified: trunk/src/dir.c
===================================================================
--- trunk/src/dir.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/dir.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -806,7 +806,7 @@
 		freeOffset = 0;
 	}
 	
-
+	mark_buffer_uptodate(bhs[freeOffset+1], true);
 	status = ocfs_journal_access(handle, bhs[freeOffset+1], 
 				     OCFS_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
@@ -1026,6 +1026,7 @@
 	__u64 locknode_off, dir_next_node, new_head_del = 0;
 	__u64 locknode_head_del;
 	__u8 dir_num_ent_used;
+	unsigned long blk;
 
 	LOG_ENTRY ();
 
@@ -1227,7 +1228,6 @@
 		} else {
 			/* Allocate a new dir node */
 			__u64 fileOffset = 0;
-			unsigned long blk;
 
 			LOG_TRACE_ARGS("ocfs_insert_file: CASE 2B\n");
 
@@ -1242,16 +1242,14 @@
 				goto leave;
 			}
 
-			status = ocfs_read_bhs(osb, bitmapOffset, osb->vol_layout.dir_node_size,
-					       newbhs, OCFS_BH_COND_CACHED, dir_inode);
-			if (status < 0) {
-				ocfs_safefree(newbhs);
-				LOG_ERROR_STATUS (status);
-				goto leave;
-			}
 			dirtyall = true;
-			/* clear all 128k, all garbage currently */
-			for (i=0; i<numbhs; i++) {
+			blk = (unsigned long)(bitmapOffset >> 9);
+			for (i = 0; i < numbhs; i++) {
+				newbhs[i] = getblk(OCFS_GET_BLOCKDEV(osb->sb),
+						   blk++, 
+						   osb->sb->s_blocksize);
+				mark_buffer_uptodate(newbhs[i], true);
+				/* clear all 128k, all garbage currently */
 				status = ocfs_journal_access(handle, newbhs[i],
 						    OCFS_JOURNAL_ACCESS_WRITE);
 				if (status < 0) {

Modified: trunk/src/dlm.c
===================================================================
--- trunk/src/dlm.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/dlm.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -47,6 +47,7 @@
 int ocfs_update_disk_lock (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, struct buffer_head **bh, struct inode *inode);
 static int ocfs_update_master_on_open (ocfs_super * osb, ocfs_lock_res * lockres, struct inode *inode);
 int ocfs_disk_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, struct inode *inode);
+static int ocfs_zap_child_buffers_func(struct dentry *dentry, void *data);
 
 /*
  * ocfs_insert_cache_link()
@@ -123,6 +124,8 @@
 	}
 
 vote_success:
+	ocfs_break_cache_lock_zap_buffers(osb, inode);
+
 	jif = jiffies - jif;
 	LOG_TRACE_ARGS ("Lock time:%u\n", jif);
 
@@ -405,6 +408,12 @@
 			DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
 			lock_level = OCFS_DLM_NO_LOCK;
 			OCFS_BH_PUT_DATA(bh);
+			tmpstat = ocfs_write_bh (osb, bh, 0, inode);
+			if (tmpstat < 0) {
+				LOG_ERROR_STATUS (tmpstat);
+				status = tmpstat;
+				goto finally;
+			}
 		}
 
 		if (lock_level <= lock_type)
@@ -2120,13 +2129,14 @@
 	lockres->lock_type = (__u8) OCFS_DLM_NO_LOCK;
 
 	LOG_TRACE_STR ("okie dokie... ocfs_break_cache_lock voting done\n");
-#if 0
-	status = ocfs_break_cache_lock_drop_buffers(osb, lockres->sector_num, inode);
 	
-	LOG_TRACE_STR ("okie dokie... ocfs_break_cache_lock drop buffers done\n");
-#endif
 
 finally:
+	if (status >= 0) {
+		ocfs_break_cache_lock_zap_buffers(osb, inode);
+		LOG_TRACE_STR ("okie dokie... ocfs_break_cache_lock zap buffers done\n");
+	}
+
 	jif = jiffies - jif;
 	LOG_TRACE_ARGS ("Lock time: %u\n", jif);
 
@@ -2142,36 +2152,28 @@
 	return (status);
 }				/* ocfs_break_cache_lock */
 
-#if 0
-int ocfs_break_cache_lock_drop_buffers(ocfs_super * osb, __u64 lock_id, struct inode * inode)
+
+static int ocfs_zap_child_buffers_func(struct dentry *dentry, void *data)
 {
-	unsigned long blk, startblk;
-	__u64 next_node_ptr;
-	int i, status;
-	struct buffer_head *bh;
-	ocfs_dir_node *dir;
-	
-	next_node_ptr = lock_id;
-	do {
-		bh = NULL;
-		startblk = next_node_ptr >> 9;
-		status = ocfs_read_bh (osb, next_node_ptr, bh, 0, inode);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			break;
-		}
-		dir = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bh);
-		next_node_ptr = dir->next_node_ptr;
-		OCFS_BH_PUT_DATA(bh);
-		brelse(bh);
-		for (blk = startblk + 1; blk < startblk + 256; blk++) {
-			bh = getblk(OCFS_GET_BLOCKDEV(osb->sb), blk, 512);
-			mark_buffer_uptodate(bh, false);
-			CLEAR_BH_SEQNUM(bh);
-			brelse(bh);
-		}
-	} while ((__s64)next_node_ptr != -1LL);
+	struct inode *inode = dentry->d_inode;
+	ocfs_super *osb = (ocfs_super *)data;
 
-	return status;
+	ocfs_inc_inode_seq(osb, inode, false);
+	return 0;
 }
-#endif
+
+int ocfs_break_cache_lock_zap_buffers(ocfs_super * osb, struct inode * inode)
+{
+	struct list_head *iter;
+	struct dentry *dentry;
+
+	if (inode==NULL) 
+		return 0;
+
+	list_for_each(iter, &(inode->i_dentry)) {
+		dentry = list_entry (iter, struct dentry, d_alias);
+		ocfs_foreach_child (dentry, ocfs_zap_child_buffers_func, osb);
+	}
+	ocfs_inc_inode_seq(osb, inode, false);
+	return 0;
+}

Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/file.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -1,7 +1,7 @@
 #include  <ocfs.h>
 #define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_EXTENT
 
-static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, struct iattr *attr, struct inode *inode);
+static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 file_off, struct iattr *attr, struct inode *inode);
 static int ocfs_truncate_file (ocfs_super * osb, __u64 file_off, __u64 file_size, ocfs_inode * oin, struct inode *inode);
 
 #define OCFS_FE_SET_ATTRIBUTES(fe, attr) 				     \
@@ -332,6 +332,21 @@
 	}
 	if (oin == NULL)
 		goto do_parent_dec;
+	  
+	if (oin->obj_id.type != OCFS_TYPE_OIN ||
+	    oin->obj_id.size != sizeof (ocfs_inode) ||
+	    oin->main_res.magic != OCFS_SEM_MAGIC) {
+		int i;
+		
+		LOG_ERROR_ARGS("oin appears to have been freed!  oin=%p, ofile=%p, inode->oin=%p\n",
+			       oin, ofile, GET_INODE_OIN(inode));
+		for (i=0; i<sizeof (ocfs_inode); i++) {
+			printk("%03x ", ((char *)oin)[i]);
+		}
+		printk("\n");
+		goto do_parent_dec;
+	}
+		
 
         ocfs_down_sem (&(oin->main_res), true);
         oin->open_hndl_cnt--;
@@ -431,7 +446,7 @@
 /* ocfs_change_file_attrib()
  *
  */
-static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, struct iattr *attr, struct inode *inode)
+static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 file_off, struct iattr *attr, struct inode *inode)
 {
 	int status = 0;
 	int tmpstat;
@@ -451,7 +466,7 @@
 
 	changeSeqNum = osb->curr_trans_id;
 
-	status = ocfs_read_bh (osb, *file_off, &bh, OCFS_BH_CACHED, inode);
+	status = ocfs_read_bh (osb, file_off, &bh, OCFS_BH_CACHED, inode);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto leave;
@@ -460,7 +475,7 @@
 	fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA_READ(bh); /* read */
 
 	if (!IS_VALID_FILE_ENTRY(fileEntry)) {
-		LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO (*file_off));
+		LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO (file_off));
 		OCFS_BH_PUT_DATA(bh);
 		status = -EFAIL;
 		goto leave;
@@ -543,9 +558,8 @@
 			ocfs_journal_add_lock(handle, lockId, locktype, lockFlags, 
 					      pLockResource, bh);
 			bAcquiredLock = false;
-			status = ocfs_commit_trans(handle);
-			if (status < 0)
-				LOG_ERROR_STATUS(status);
+
+			ocfs_commit_trans(handle);
 		}
 	}
 	if (bAcquiredLock) {
@@ -974,8 +988,8 @@
 
 leave:
 	if (handle && (status == 0)) {
-		status = ocfs_commit_trans(handle);
-		if ((status == 0) && free_head)
+		ocfs_commit_trans(handle);
+		if (free_head)
 			ocfs_process_bitmap_free_head(osb, free_head);
 	} else if (handle)
 		ocfs_abort_trans(handle);
@@ -1236,9 +1250,8 @@
 						      lockFlags, pLockResource,
 						      bh);
 				bAcquiredLock = false;
-				status = ocfs_commit_trans(handle);
-				if (status < 0)
-					LOG_ERROR_STATUS(status);
+
+				ocfs_commit_trans(handle);
 			}
 		}
 	}
@@ -1375,14 +1388,12 @@
 
 	/* if directory, put FILE_ENTRY ptr into fileOff */
 	if (S_ISDIR (inode->i_mode))
-		ocfs_linux_get_dir_entry_offset(osb, &fileOff, parentOff, 
-						&(dentry->d_name), NULL, 
-						parentInode);
+		fileOff = GET_INODE_FEOFF(inode);
 
 	status = -EFAIL;
 	if ((fileOff != -1) && !extended) {
 		status = ocfs_change_file_attrib(osb, parentOff, NULL, newsize,
-					       &fileOff, attr, inode);
+					       fileOff, attr, inode);
 		if (status < 0) {
 			if (status != -EINTR)
 				LOG_ERROR_STATUS (status);

Modified: trunk/src/hash.c
===================================================================
--- trunk/src/hash.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/hash.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -692,8 +692,6 @@
 {
 	int i, ret;
 
-	LOG_ENTRY();
-	
 	spin_lock_init (&OcfsGlobalCtxt.bh_sem_hash_lock);
 	OcfsGlobalCtxt.bh_sem_hash = (struct list_head *)__get_free_pages(GFP_KERNEL, 2);
 	if (!OcfsGlobalCtxt.bh_sem_hash) {
@@ -707,9 +705,9 @@
 		INIT_LIST_HEAD(&OcfsGlobalCtxt.bh_sem_hash[i]);
 
 	atomic_set(&OcfsGlobalCtxt.bh_sem_hash_target_bucket, -1);
+	atomic_set(&OcfsGlobalCtxt.bh_sem_hash_num_iters, 0);
 	ret = 0;
 bail:
-	LOG_EXIT();
 	return ret;
 }
 
@@ -717,8 +715,6 @@
 {
 	int missed;
 
-	LOG_ENTRY();
-
 	while (1) {
 		missed = ocfs_bh_sem_hash_prune_all();
 		if (missed == 0)
@@ -730,7 +726,6 @@
 	free_pages((unsigned long)OcfsGlobalCtxt.bh_sem_hash, 2);
 	OcfsGlobalCtxt.bh_sem_hash = NULL;
 	
-	LOG_EXIT();
 	return 0;
 }
 
@@ -741,9 +736,6 @@
 	struct list_head *head, *iter = NULL;
 	ocfs_bh_sem *sem = NULL, *newsem = NULL;
 
-#ifdef VERBOSE_BH_SEM
-	LOG_ENTRY();
-#endif
 	bucket = ocfs_bh_sem_hash_fn(bh);
 	head = &OcfsGlobalCtxt.bh_sem_hash[bucket];
 again:
@@ -827,9 +819,6 @@
 	}
 
 bail:	
-#ifdef VERBOSE_BH_SEM
-	LOG_EXIT_PTR(sem);
-#endif
 	return sem;
 }
 
@@ -841,9 +830,6 @@
 	ocfs_bh_sem *sem;
 	int ret;
 
-#ifdef VERBOSE_BH_SEM
-	LOG_ENTRY_ARGS("(blocknr=%u)\n", bh->b_blocknr);
-#endif
 	sem = ocfs_bh_sem_lookup(bh);
 	if (!sem)
 		BUG();
@@ -861,9 +847,6 @@
 		ret = OCFS_BH_SEM_GOT_LOCK;
 	}
 
-#ifdef VERBOSE_BH_SEM
-	LOG_EXIT_ULONG(ret);
-#endif
 	return ret;
 }
 
@@ -872,9 +855,6 @@
 	ocfs_bh_sem *sem;
 	int ret;
 
-#ifdef VERBOSE_BH_SEM
-	LOG_ENTRY_ARGS("(blocknr=%u)\n", bh->b_blocknr);
-#endif
 	sem = ocfs_bh_sem_lookup(bh);
 	if (!sem)
 		BUG();
@@ -908,9 +888,6 @@
 		set_buffer_modified(bh);
 	}
 
-#ifdef VERBOSE_BH_SEM
-	LOG_EXIT_ULONG(ret);
-#endif
 	return ret;
 }
 
@@ -920,9 +897,6 @@
 {
 	ocfs_bh_sem *sem;
 
-#ifdef VERBOSE_BH_SEM
-	LOG_ENTRY();
-#endif	
 	sem = ocfs_bh_sem_lookup(bh);
 	if (!sem)
 		BUG();
@@ -935,9 +909,6 @@
 	/* take away another ref from the lock lookup */
 	ocfs_bh_sem_put(sem);
 
-#ifdef VERBOSE_BH_SEM
-	LOG_EXIT();
-#endif
 	return 0;
 }
 
@@ -945,18 +916,28 @@
 /* returns number of pruned entries */
 int ocfs_bh_sem_hash_prune()
 {
-	int bucket, pruned;
+	unsigned int bucket;
+	int pruned = 0, mandatory=0;
 	struct list_head *head, *iter = NULL, *tmpiter = NULL;
 	ocfs_bh_sem *sem = NULL;
 	LIST_HEAD(tmp);
 
-	LOG_ENTRY();
+	atomic_inc(&OcfsGlobalCtxt.bh_sem_hash_num_iters);
+       	if (atomic_read(&OcfsGlobalCtxt.bh_sem_hash_num_iters) > 10) {
+		mandatory = 1;
+		atomic_sub(10, &OcfsGlobalCtxt.bh_sem_hash_num_iters);
+	}
 
 	/* The better to prune you with, my dear! */
 	bucket = atomic_read(&OcfsGlobalCtxt.bh_sem_hash_target_bucket);
 	if (bucket == -1) {
-		pruned = 0;
-		goto bail;
+		if (mandatory) {
+			get_random_bytes(&bucket, sizeof(bucket));
+			bucket %= OcfsGlobalCtxt.bh_sem_hash_sz;
+		} else {
+			pruned = 0;
+			goto bail;
+		}
 	}
 
 	spin_lock(&OcfsGlobalCtxt.bh_sem_hash_lock);
@@ -996,7 +977,6 @@
 		ocfs_bh_sem_free(sem);
 	}
 bail:
-	LOG_EXIT_ULONG(pruned);
 	return pruned;
 }
 
@@ -1011,8 +991,6 @@
 	struct list_head *head, *iter = NULL;
 	ocfs_bh_sem *sem = NULL;
 
-	LOG_ENTRY_ARGS("(pid = %d)\n", pid);
-
 	bucket = 0;
 again:
 	spin_lock(&OcfsGlobalCtxt.bh_sem_hash_lock);
@@ -1047,7 +1025,6 @@
 	if (found)
 		LOG_ERROR_ARGS("Found %d modified buffers!\n", found);
 
-	LOG_EXIT_ULONG(found);
 	return found;
 } /* ocfs_bh_sem_hash_cleanup_pid() */
 
@@ -1059,8 +1036,6 @@
 	ocfs_bh_sem *sem = NULL;
 	LIST_HEAD(tmp);
 
-	LOG_ENTRY();
-	
 	missed = 0;
 	bucket = 0;
 	spin_lock(&OcfsGlobalCtxt.bh_sem_hash_lock);
@@ -1101,12 +1076,14 @@
 		ocfs_bh_sem_free(sem);
 	}
 
-	LOG_EXIT_ULONG(missed);
 	return missed;
 }
 
+#define BUFFER_MODIFIED_TIMEOUT   HZ
+
 void wait_on_buffer_modified(struct buffer_head * bh)
 {
+	int do_timeout = 1;
 	ocfs_bh_sem *sem = ocfs_bh_sem_lookup(bh);
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -1116,14 +1093,24 @@
 
 	add_wait_queue(&sem->s_wait, &wait);
 	do {
-		run_task_queue(&tq_disk);
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!buffer_modified(bh) ||
 		    sem->s_pid == current->pid)
 			break;
-		schedule();
+		run_task_queue(&tq_disk);
+		if (!do_timeout) {
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			schedule();
+		} else {
+			do_timeout = 0;
+			set_task_state(tsk, TASK_INTERRUPTIBLE);
+			schedule_timeout(BUFFER_MODIFIED_TIMEOUT);
+			if (buffer_modified(bh) && 
+			    sem->s_pid != current->pid)
+				LOG_ERROR_ARGS("possible deadlock: block=%lu, owner=%d, this=%d\n",
+				       bh->b_blocknr, sem->s_pid, current->pid);
+		}
 	} while (buffer_modified(bh) && sem->s_pid != current->pid);
-	tsk->state = TASK_RUNNING;
+	set_task_state(tsk, TASK_RUNNING);
 	remove_wait_queue(&sem->s_wait, &wait);
 	ocfs_bh_sem_put(sem);
 
@@ -1155,27 +1142,11 @@
 	LOG_EXIT();
 }
 
-typedef struct _ocfs_inode_num {
-	enum {
-		INUM_UNBOUND = 0,  /* unbound to an inode*/
-		INUM_BOUND         /* we have an inode attached. */
-	}                 i_state;
-	struct list_head  i_list;
-	unsigned long     i_ino;
-	__u64             i_voteoff;/* fe->this_sector OR
-				     * fe->extents[0].disk_off */
-	__u64             i_feoff;  /* used only for directory inodes,
-				     * points to parent fe of
-				     * dirnode. for files i_voteoff == i_feoff,
-				     * for root directory this is 0 */
-	struct inode     *i_inode;  /* may be null! */
-} ocfs_inode_num;
-
 static inline ocfs_inode_num *ocfs_create_inode_num(void)
 {
 	ocfs_inode_num *inum = NULL;
 
-	inum = ocfs_malloc(sizeof(ocfs_inode_num));
+	inum = kmem_cache_alloc(OcfsGlobalCtxt.inum_cache, GFP_NOFS);
 	if (inum == NULL) {
 		LOG_ERROR_STATUS(-ENOMEM);
 		goto bail;
@@ -1190,8 +1161,10 @@
 bail:
 	return(inum);
 }
-#define ocfs_free_inode_num(inum) (ocfs_free(inum))
 
+#define ocfs_free_inode_num(inum)					      \
+	kmem_cache_free(OcfsGlobalCtxt.inum_cache, inum)
+
 /* 
  * ocfs_inode_hash_init()
  *
@@ -1269,6 +1242,16 @@
 		inum = list_entry(iter, ocfs_inode_num, i_list);
 		list_del(&inum->i_list);
 
+		/* this log_error_args is mainly for debugging */
+		if (atomic_read(&inum->i_inode->i_count) > 2)
+			LOG_ERROR_ARGS("inode (%lu) with i_count = %u left in "
+				       "system, (voteoff = %u.%u, "
+				       "fileoff = %u.%u)\n", 
+				       inum->i_inode->i_ino,
+				       atomic_read(&inum->i_inode->i_count),
+				       HILO(inum->i_voteoff), 
+				       HILO(inum->i_feoff));
+
 		if (inum->i_inode)
 			iput(inum->i_inode);
 		ocfs_free_inode_num(inum);
@@ -1317,9 +1300,6 @@
 	struct list_head *head;
 	struct list_head *iter = NULL;
 
-	if (spin_trylock(&h->lock))
-		BUG();
-
 	bucket = OCFS_INODE_HASH(h, off);
 
 	head = &h->hash[bucket];
@@ -1347,9 +1327,6 @@
 	struct list_head *head;
 	struct list_head *iter = NULL;
 
-	if (spin_trylock(&h->lock))
-		BUG();
-
 	for(bucket = 0; bucket < h->size; bucket++) {
 		head = &h->hash[bucket];
 
@@ -1487,13 +1464,16 @@
 	/* we created a new one to add, but someone added it before we
 	 * could start our second pass, so just clean up. */
 	if (inum && new_inum) {
-		ocfs_free(new_inum);
+		ocfs_free_inode_num(new_inum);
 		new_inum = NULL;
 	}
 
 	/* if we never did an insert, then return the looked up ino. */
-	if (inum)
+	if (inum) {
 		ino = inum->i_ino;
+		LOG_TRACE_ARGS("Returning an inum that was already in the "
+			       "hash (%lu)\n", ino);
+	}
 
 	LOG_EXIT_ULONG(ino);
 
@@ -1607,7 +1587,7 @@
 	if (inum->i_inode)
 		iput(inum->i_inode);
 
-	ocfs_free(inum);
+	ocfs_free_inode_num(inum);
 
 	LOG_EXIT();
 	return;
@@ -1687,7 +1667,7 @@
 		list_del(&inum->i_list);
 		h->num_ents--;
 		spin_unlock(&h->lock);
-		ocfs_free(inum);
+		ocfs_free_inode_num(inum);
 	}
 
 	return(free);

Modified: trunk/src/inc/io.h
===================================================================
--- trunk/src/inc/io.h	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/inc/io.h	2004-02-03 01:29:16 UTC (rev 19)
@@ -49,30 +49,6 @@
 
 #define OCFS_NONCACHED(osb,off)  ((off) < (osb)->vol_layout.data_start_off)
 
-#ifdef DEBUG_LOCK_BUFFER
-#define LOCK_BUFFER_STR(bh)						      \
-	if (buffer_locked(bh) && current->pid!=debug_exclude)		      \
-		printk("ocfs2: (%d) BUFFER LOCKED! blocknr=%u\n",	      \
-			current->pid, (bh)->b_blocknr)
-#else
-#define LOCK_BUFFER_STR(bh)         
-#endif
-
-#ifdef VERBOSE_DEBUG_LOCK_BUFFER
-#define VERBOSE_LOCK_BUFFER_STR(bh)					      \
-	if (current->pid!=debug_exclude)				      \
-		printk("ocfs2: (%d) locking buffer %u\n", current->pid,	      \
-			(bh)->b_blocknr)
-#define VERBOSE_UNLOCK_BUFFER_STR(bh)					      \
-	if (current->pid!=debug_exclude)				      \
-		printk("ocfs2: (%d) unlocking buffer %u\n", current->pid,     \
-		       (bh)->b_blocknr)
-#else 
-#define VERBOSE_LOCK_BUFFER_STR(bh) 
-#define VERBOSE_UNLOCK_BUFFER_STR(bh) 
-#endif
-
-
 #define BH_Modified 18
 #define buffer_modified(bh)		__buffer_state((bh),Modified)
 #define set_buffer_modified(bh)		set_bit(BH_Modified, &(bh)->b_state);
@@ -83,8 +59,6 @@
 {
 	unsigned char *kaddr;
 
-	LOCK_BUFFER_STR(bh);
-	VERBOSE_LOCK_BUFFER_STR(bh);
 	while (1) {
 		if (ocfs_bh_sem_lock(bh)==OCFS_BH_SEM_WAIT_ON_MODIFY) {
 			ocfs_bh_sem_unlock(bh);
@@ -102,8 +76,6 @@
 {
 	unsigned char *kaddr;
 
-	LOCK_BUFFER_STR(bh);
-	VERBOSE_LOCK_BUFFER_STR(bh);
 	while (1) {
 		if (ocfs_bh_sem_lock_modify(bh) == OCFS_BH_SEM_WAIT_ON_MODIFY) {
 #ifdef VERBOSE_BH_SEM
@@ -125,7 +97,6 @@
 static inline void OCFS_BH_PUT_DATA(struct buffer_head *bh)
 {
 	kunmap((bh)->b_page);
-	VERBOSE_UNLOCK_BUFFER_STR(bh);
 	ocfs_bh_sem_unlock(bh);
 }
 

Modified: trunk/src/inc/journal.h
===================================================================
--- trunk/src/inc/journal.h	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/inc/journal.h	2004-02-03 01:29:16 UTC (rev 19)
@@ -263,7 +263,7 @@
  * 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);
-int                  ocfs_commit_trans(ocfs_journal_handle *handle);
+void                 ocfs_commit_trans(ocfs_journal_handle *handle);
 void                 ocfs_abort_trans(ocfs_journal_handle *handle);
 /*
  * Create access is for when we get a newly created buffer and we're
@@ -333,8 +333,8 @@
 
 /* locknode + new fe + dirnode head + new dirnode for parent directory
  * + extending (diralloc, filealloc, dirallocbitmap, fileallocbitmap)
- * and some fuzz. */
-#define OCFS_MKNOD_CREDITS (1 + 1 + OCFS_DEFAULT_DIR_NODE_SECTS +	      \
+ * + a second dirnode for handling mkdir + some fuzz. */
+#define OCFS_MKNOD_CREDITS (1 + 1 + (OCFS_DEFAULT_DIR_NODE_SECTS*2) +	      \
 			    (OCFS_SINGLE_FILE_EXTEND_CREDITS * 4) +	      \
 			    OCFS_JOURNAL_FUZZ_CREDITS)
 

Modified: trunk/src/inc/ocfs.h
===================================================================
--- trunk/src/inc/ocfs.h	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/inc/ocfs.h	2004-02-03 01:29:16 UTC (rev 19)
@@ -211,7 +211,7 @@
 {
 	void *           generic_ip;
 	__u64            voteoff;
-//	__u64            feoff;
+	__u64            feoff;
 //	struct list_head i_clean_buffers;
 	atomic_t         i_clean_buffer_seq;
 	__u8             deleted; /* this can be a generic flags field later */
@@ -236,6 +236,13 @@
 
 #define GET_INODE_VOTEOFF(i) OCFS_GENERIC_IP(i)->voteoff
 
+#define SET_INODE_FEOFF(i,o)						      \
+do {									      \
+	OCFS_GENERIC_IP(i)->feoff = o;					      \
+} while (0)
+
+#define GET_INODE_FEOFF(i) OCFS_GENERIC_IP(i)->feoff
+
 #define CLEAR_INODE_OIN(i)						      \
 do {									      \
 	GET_INODE_OIN(i)= (void *)NULL;					      \
@@ -546,7 +553,7 @@
 
 
 #define OCFS_BH_SEM_HASH_PRUNE_TRIGGER  50      /* trigger nm to prune the hash when list size is > this */
-#define OCFS_BH_SEM_HASH_PRUNE_MAX      20      /* nm will prune at most this many in one cycle */
+#define OCFS_BH_SEM_HASH_PRUNE_MAX      100     /* nm will prune at most this many in one cycle */
 
 	
 #ifndef O_DIRECT
@@ -1906,10 +1913,26 @@
 typedef struct _ocfs_inode_hash {
 	spinlock_t        lock;     /* protects the whole hash */
 	int               size;     /* number of lists in the hash */
-	int               num_ents; /* global number of offsets in there */
+	unsigned int      num_ents; /* global number of offsets in there */
 	struct list_head  *hash; 
 } ocfs_inode_hash;
 
+typedef struct _ocfs_inode_num {
+	enum {
+		INUM_UNBOUND = 0,  /* unbound to an inode*/
+		INUM_BOUND         /* we have an inode attached. */
+	}                 i_state;
+	struct list_head  i_list;
+	unsigned long     i_ino;
+	__u64             i_voteoff;/* fe->this_sector OR
+				     * fe->extents[0].disk_off */
+	__u64             i_feoff;  /* used only for directory inodes,
+				     * points to parent fe of
+				     * dirnode. for files i_voteoff == i_feoff,
+				     * for root directory this is 0 */
+	struct inode     *i_inode;  /* may be null! */
+} ocfs_inode_num;
+
 /*
  * ocfs_super
  *
@@ -2021,6 +2044,7 @@
 	kmem_cache_t *lockres_cache;
 	kmem_cache_t *extent_cache;
 	kmem_cache_t *bh_sem_cache;
+	kmem_cache_t *inum_cache;
 	__u32 flags;
 	__u32 pref_node_num;		/* preferred... osb has the real one */
 	ocfs_guid guid;			/* uniquely identifies a node */
@@ -2039,6 +2063,7 @@
 	spinlock_t bh_sem_hash_lock;
 	int bh_sem_hash_sz;
 	atomic_t bh_sem_hash_target_bucket;
+	atomic_t bh_sem_hash_num_iters;
 }
 ocfs_global_ctxt;
 
@@ -2467,45 +2492,7 @@
 
 #define ocfs_acquire_lockres(a)         ocfs_acquire_lockres_ex(a, 0)
 
-static void ocfs_timeout_func(unsigned long data)
-{
-	ocfs_timeout *to = (ocfs_timeout *)data; 
 
-	to->timed_out = 1;
-	wake_up(&to->wait);
-}
-
-static inline void ocfs_init_timeout(ocfs_timeout *to)
-{
-	init_timer(&to->timer);
-	to->timer.data = (unsigned long)to;
-	to->timer.function = ocfs_timeout_func;
-	to->timed_out = 0;
-	init_waitqueue_head(&to->wait);
-}
-
-static inline void ocfs_set_timeout(ocfs_timeout *to, __u32 timeout)
-{
-	__u32 how_long;
-
-	if (!timeout) {
-		to->timed_out = 1;
-		return ;
-	}
-
-	how_long = (timeout * HZ / 1000);
-	if (how_long < 1)
-		how_long = 1;
-
-	to->timer.expires = jiffies + how_long;
-	add_timer(&to->timer);
-}
-
-static inline void ocfs_clear_timeout(ocfs_timeout *to)
-{
-	del_timer_sync(&to->timer);
-}
-
 #define __ocfs_wait(wq, condition, timeo, ret)			\
 do {								\
 	ocfs_timeout __to;					\
@@ -2582,6 +2569,8 @@
 	return ret;
 }
 
+#define ocfs_trace(p) do { printk("Trace in %s line %d called from [<%lx>]\n", __FILE__, __LINE__, __builtin_return_address(0) ); ocfs_show_trace(NULL); } while (0)
+
 #include "proto.h"
 
 #endif /* !OCFS_H */

Modified: trunk/src/inc/proto.h
===================================================================
--- trunk/src/inc/proto.h	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/inc/proto.h	2004-02-03 01:29:16 UTC (rev 19)
@@ -21,6 +21,7 @@
 int ocfs_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, struct inode *inode);
 int ocfs_init_dlm (void);
 void ocfs_process_one_vote_reply(ocfs_super *osb, ocfs_vote_reply_ctxt *ctxt, __u32 node_num);
+int ocfs_break_cache_lock_zap_buffers(ocfs_super * osb, struct inode * inode);
 
 
 int ocfs_create_log_extent_map (ocfs_super * osb, __u64 diskOffset, __u64 ByteCount);
@@ -184,6 +185,7 @@
 
 int ocfs_empty (struct dentry *dentry);
 int ocfs_dentry_revalidate (struct dentry *dentry, int flags);
+int ocfs_foreach_child (struct dentry *dentry, int (*func)(struct dentry *, void *), void *data);
 
 int ocfs_readdir (struct file *filp, void *dirent, filldir_t filldir);
 struct dentry *ocfs_lookup (struct inode *dir, struct dentry *dentry);
@@ -209,6 +211,7 @@
 void ocfs_recover_oin_locks(ocfs_super *osb, __u32 node_num);
 int ocfs_process_vote (ocfs_super * osb, ocfs_vote_request_ctxt *ctxt);
 int ocfs_find_update_res (ocfs_super * osb, __u64 lock_id, ocfs_lock_res ** lockres, struct buffer_head **bh, __u32 * updated, __u32 timeout, struct inode *inode);
+void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode, bool sync_buffers);
 
 
 int ocfs_follow_link(struct dentry *dentry, struct nameidata *nd);
@@ -240,3 +243,9 @@
 struct inode *ocfs_inode_hash_lookup(ocfs_super *osb, 
 				     __u64 voteoff, 
 				     bool reverse);
+
+void ocfs_init_timeout(ocfs_timeout *to);
+void ocfs_set_timeout(ocfs_timeout *to, __u32 timeout);
+void ocfs_clear_timeout(ocfs_timeout *to);
+void ocfs_show_stack(unsigned long * esp);
+void ocfs_show_trace(unsigned long * stack);

Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/inode.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -241,6 +241,7 @@
 		CLEAR_INODE_OIN(inode);
 
 	SET_INODE_VOTEOFF(inode, offset);
+	SET_INODE_FEOFF(inode, fe_off);
 
 	if (create_ino) {
 		uniq_ino = ocfs_inode_hash_insert(osb, offset, fe_off);
@@ -325,6 +326,7 @@
 		inode->i_gid = osb->vol_layout.gid;
 		SET_INODE_OIN (inode, osb->oin_root_dir);
 		SET_INODE_VOTEOFF(inode, osb->vol_layout.root_start_off);
+		SET_INODE_FEOFF(inode, 0);
 		goto bail;
 	}
 
@@ -417,6 +419,7 @@
 		inode->i_gid = osb->vol_layout.gid;
 		SET_INODE_OIN (inode, osb->oin_root_dir);
 		SET_INODE_VOTEOFF(inode, osb->vol_layout.root_start_off);
+		SET_INODE_FEOFF(inode, 0);
 		ocfs_inode_hash_bind(osb, GET_INODE_VOTEOFF(inode), inode);
 		goto bail;
 	}
@@ -636,7 +639,6 @@
 	     oin = GET_INODE_OIN(inode);
 	     ocfs_extent_map_destroy (&oin->map);
 	     ocfs_extent_map_init (&oin->map);
-	     //dump_inode_clean_queue_buffers(inode);
 	} 
 	/* Ok, if after this iput we would be the last holder of the
 	 * root inode, then we know we're unmounting so just dump it

Modified: trunk/src/io.c
===================================================================
--- trunk/src/io.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/io.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -77,8 +77,6 @@
 {
 	int status, i;
 	struct inode **arr = NULL;
-	struct inode *inode;
-	__u64 tmpoff;
 	
 	LOG_ENTRY();
 
@@ -165,8 +163,10 @@
 	}
 	
 	/* fill in the remainder of the blocks not read from disk */
-	for (i=total, blk = ((unsigned long)(off >> 9) + total); i<256; i++, blk++)
+	for (i=total, blk = ((unsigned long)(off >> 9) + total); i<256; i++, blk++) {
 		bhs[i] = getblk (OCFS_GET_BLOCKDEV(osb->sb), blk, 512);
+		memset(bhs[i]->b_data, 'P', 512);
+	}
 bail:
 	LOG_EXIT_STATUS(status);
 	return status;
@@ -262,8 +262,6 @@
 			continue;
 		}
 
-		LOCK_BUFFER_STR(bh);
-		VERBOSE_LOCK_BUFFER_STR(bh);
 		lock_buffer(bh);
 
 #ifdef LINUX_2_5
@@ -417,8 +415,6 @@
 				continue;
 			}
 
-			LOCK_BUFFER_STR(bh);
-			VERBOSE_LOCK_BUFFER_STR(bh);
 			lock_buffer(bh);
 #ifdef LINUX_2_5
 			clear_buffer_uptodate(bh);
@@ -547,8 +543,6 @@
 			continue;
 		}
 
-		LOCK_BUFFER_STR(bh);
-		VERBOSE_LOCK_BUFFER_STR(bh);
 		lock_buffer(bh);
 
 #ifdef LINUX_2_5
@@ -573,7 +567,8 @@
 		else
 			CLEAR_BH_SEQNUM(bh);
 
-		if (!(flags & OCFS_BH_CONCURRENT_WRITE))
+		if (!(flags & OCFS_BH_CONCURRENT_WRITE) 
+		    && (!buffer_jbd(bh) || (flags & OCFS_BH_IGNORE_JBD)))
 			ocfs_clear_buffer_modified(bh);
 	}
 	
@@ -701,8 +696,6 @@
 				continue;
 			}
 
-			LOCK_BUFFER_STR(bh);
-			VERBOSE_LOCK_BUFFER_STR(bh);
 			lock_buffer(bh);
 #ifdef LINUX_2_5
 			clear_buffer_uptodate(bh);

Modified: trunk/src/journal.c
===================================================================
--- trunk/src/journal.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/journal.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -306,13 +306,12 @@
 /*
  * ocfs_commit_trans
  */
-int ocfs_commit_trans(ocfs_journal_handle * handle) 
+void ocfs_commit_trans(ocfs_journal_handle * handle) 
 {
 	ocfs_super *osb;
 	handle_t *kern_handle;
 	transaction_t *kern_trans;
-	int retval = 0, i;
-	struct buffer_head *bh;
+	int retval, i;
 	bool checkpoint, sync;
 	ocfs_journal *journal;
 
@@ -352,13 +351,12 @@
 		BUG();
 	}
 
-	/* for now we manually checkpoint and force out our revoke
-	 * records. In the future we'll try to queue up as many
+	handle->k_handle = NULL; /* it's been free'd in journal_stop */
+
+	/* In the future we'll try to queue up as many
 	 * buffer_heads as possible so that a single callback call
 	 * will checkpoint and revoke everything from that
 	 * transaction. */
-	handle->k_handle = NULL; /* it's been free'd in journal_stop */
-
 	if (checkpoint) {
 		/* checkpoint from buffer_head list */
 		retval = ocfs_checkpoint_handle(handle);
@@ -377,19 +375,16 @@
 	} else { 
 		/* If we're not checkpointing, we have to be careful
 		 * to also clear the modified bits. */
-		for(i = 0; i < handle->num_buffs; i++) {
-			bh = handle->buffs[i];
-			handle->buffs[i] = NULL;
-
-			ocfs_clear_buffer_modified(bh);
-		}
+		for(i = 0; i < handle->num_buffs; i++)
+			ocfs_clear_buffer_modified(handle->buffs[i]);
 	}
 
 /* done: */
 	for(i = 0; i < handle->num_buffs; i++) {
-		bh = handle->buffs[i];
-		brelse(bh);
+		brelse(handle->buffs[i]);
+		handle->buffs[i] = NULL;
 	}
+	handle->num_buffs = 0;
 
 	down(&journal->commit_sem);
 	journal->curr = NULL;
@@ -419,7 +414,6 @@
 	if (handle->buffs) {
 		ocfs_free(handle->buffs);
 		handle->buffs = NULL;
-		handle->num_buffs = 0;
 	}
 
 	/* This has to happen after we release the other locks. */
@@ -436,9 +430,9 @@
 	if (checkpoint)
 		ocfs_free(handle);
 
-	LOG_EXIT_STATUS(retval);
+	LOG_EXIT();
 
-	return(retval);
+	return;
 } /* ocfs_commit_trans */
 
 /*
@@ -613,6 +607,12 @@
 		       "OCFS_JOURNAL_ACCESS_CREATE" : 
 		       "OCFS_JOURNAL_ACCESS_WRITE", bh->b_size);
 
+	/* we can safely remove this assertion after testing. */
+	if (!buffer_uptodate(bh)) {
+		printk("ocfs: giving me a buffer that's not uptodate!\n");
+		printk("ocfs: b_blocknr=%lu\n", bh->b_blocknr);
+		BUG();
+	}
 	/* by taking a "read" lock, we prevent anyone from doing any
 	 * IO on the buffers while in journal_get_*_access */
 	data = OCFS_BH_GET_DATA_READ(bh);

Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/namei.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -212,13 +212,6 @@
 			LOG_ERROR_STATUS(status);
 		ocfs_abort_trans(handle);
 		goto leave;
-	} else {
-		fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(new_fe_bh); /* read */
-		handle->new_file_lockid = fe->this_sector;
-		OCFS_BH_PUT_DATA(new_fe_bh);
-		fe = NULL;
-		if (ocfs_commit_trans(handle) < 0)
-			LOG_ERROR_STR("Could not complete create!");
 	}
 
 	status = ocfs_create_new_oin (&oin, 0ULL, osb);
@@ -262,22 +255,27 @@
 	if (S_ISDIR (mode)) 
 		oin->dir_disk_off = fe->extents[0].disk_off;
 
-	LOG_TRACE_ARGS("new_fe_bh: this_sector = %u.%u, "
+	LOG_TRACE_ARGS("ocfs_mknod: new_fe_bh: this_sector = %u.%u, "
 		       "extents[0].disk_off = %u.%u\n",
 		       HILO(fe->this_sector), HILO(fe->extents[0].disk_off));
 	
-	status = 0;
+	oin->inode = inode;
+	ocfs_populate_inode (inode, fe, mode, oin, true);
+	insert_inode_hash (inode);
+	ocfs_inode_hash_bind(osb, GET_INODE_VOTEOFF(inode), inode);
+	d_instantiate (dentry, inode);
 
+	handle->new_file_lockid = fe->this_sector;
+	OCFS_BH_PUT_DATA(new_fe_bh);
+	fe = NULL;
+
+	ocfs_commit_trans(handle);
+
+	status = 0;
 leave:
-	if (status >= 0 && !IS_ERR (inode)) {
-		oin->inode = inode;
-		ocfs_populate_inode (inode, fe, mode, oin, true);
-		insert_inode_hash (inode);
-		ocfs_inode_hash_bind(osb, GET_INODE_VOTEOFF(inode), inode);
-		d_instantiate (dentry, inode);
-	} else if (status == -ENOSPC)
+	if (status == -ENOSPC)
 		LOG_TRACE_STR ("Disk is full");
-	else if (status != -EINTR)
+	else if (status < 0 && status != -EINTR)
 		LOG_ERROR_STATUS(status);
 
 	if (new_fe_bh) {
@@ -390,7 +388,6 @@
 	cache_lock = (DISK_LOCK_FILE_LOCK (pLockNode) == OCFS_DLM_ENABLE_CACHE_LOCK);
 	OCFS_BH_PUT_DATA(lock_bh);
 
-
 	if (S_ISDIR (mode)) {
 		__u64 bitmapOffset;
 		__u64 fileOffset = 0;
@@ -422,16 +419,34 @@
 		fe->extents[0].disk_off = bitmapOffset;
 		fe->file_size = osb->vol_layout.dir_node_size;
 		fe->next_del = INVALID_DIR_NODE_INDEX;
-
-//		if (!cache_lock)
-//			DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
 		
 		blk = (unsigned long)(bitmapOffset >> 9);
 		for (i = 0; i < numblks; i++) {
-			dirbhs[i] = getblk (OCFS_GET_BLOCKDEV(osb->sb), blk++, osb->sb->s_blocksize);
+			dirbhs[i] = getblk (OCFS_GET_BLOCKDEV(osb->sb), 
+					    blk++, osb->sb->s_blocksize);
+
+			mark_buffer_uptodate(dirbhs[i], true);
+			status = ocfs_journal_access(handle, dirbhs[i], 
+					     OCFS_JOURNAL_ACCESS_WRITE);
+			if (status < 0) {
+				while (i >= 0)
+					brelse(dirbhs[i--]);
+				ocfs_safefree(dirbhs);
+				LOG_ERROR_STATUS(status);
+				goto leave;
+			}
 			tmp = OCFS_BH_GET_DATA_WRITE(dirbhs[i]); /* write */
 			memset(tmp, 0, osb->sect_size);
 			OCFS_BH_PUT_DATA(dirbhs[i]);
+			status = ocfs_journal_dirty(handle, dirbhs[i]);
+			if (status < 0) {
+				while (i >= 0)
+					brelse(dirbhs[i--]);
+				ocfs_safefree(dirbhs);
+				LOG_ERROR_STATUS(status);
+				goto leave;
+			}
+
 		}
 
 		new_dir = (ocfs_dir_node *) OCFS_BH_GET_DATA_WRITE(dirbhs[0]); /* write */
@@ -445,20 +460,6 @@
 		OCFS_BH_PUT_DATA(dirbhs[0]);
 		new_dir = NULL;
 
-		/* Sunil tells me that, not only does the new dirnode
-		 * header have to hit disk, but the rest of it has to
-		 * be zeroed out too. At least this will populate the
-		 * cache now... */
-		status = ocfs_write_dirnode(osb, dirbhs, inode);
-		if (status < 0) {
-			for(i=0; i < numblks; i++)
-				brelse(dirbhs[i]);
-			ocfs_safefree (dirbhs);
-			OCFS_BH_PUT_DATA(lock_bh);
-			LOG_ERROR_STATUS (status);
-			goto leave;
-		}
-
 		/* cleanup after ourselves */
 		for(i=0; i < numblks; i++)
 			brelse(dirbhs[i]);
@@ -466,8 +467,6 @@
 		ocfs_safefree (dirbhs);
 	}
 
-//	if (S_ISDIR (mode) && !cache_lock)
-//		DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
 
 	status = ocfs_insert_file (osb, fe, lock_bh, &fe_bh, handle, dir, inode);
 	if (status < 0) {
@@ -559,11 +558,8 @@
 	LOG_TRACE_ARGS("oin = 0x%08x\n", oin);
 	ocfs_linux_get_inode_offset (dir, &parentOff, NULL);
 
-	if (S_ISDIR (inode->i_mode))
-		ocfs_linux_get_dir_entry_offset (osb, &fileOff, parentOff,
-						 &(dentry->d_name), NULL, dir);
-	else
-		ocfs_linux_get_inode_offset (inode, &fileOff, NULL);
+	fileOff = GET_INODE_FEOFF(inode);
+	LOG_TRACE_ARGS("fileOff = %u.%u, ino = %lu\n", HILO(fileOff), inode->i_ino);
 
 	status = -EBUSY;
 	/* i_count > 2 is because we'll be holding a ref on it for our
@@ -887,7 +883,7 @@
 	if (S_ISDIR (old_dentry->d_inode->i_mode)) {
 		/* overwrite oldOffset to get ptr to OCFS_FILE_ENTRY
 		 * not DIR_NODE */
-		ocfs_linux_get_dir_entry_offset (osb, &oldOffset, oldDirOff, &(old_dentry->d_name), NULL, old_dir);
+		oldOffset = GET_INODE_FEOFF(old_dentry->d_inode);
 	}
 
 	/* new parent dir offset */
@@ -899,6 +895,9 @@
 	if (new_dentry->d_inode != NULL && inode_data_is_oin (new_dentry->d_inode))
 		newOIN = GET_INODE_OIN(new_dentry->d_inode);
 
+	if (new_inode)
+		atomic_inc(&new_inode->i_count);
+
 	/* want an i_count == 2 because the hash has a reference. */
 	if (atomic_read (&old_inode->i_count) > 2) {
 		status = -EBUSY;
@@ -1032,7 +1031,8 @@
 
 		status = ocfs_acquire_lock(osb, newfe_lockid, 
 					   OCFS_DLM_EXCLUSIVE_LOCK, 
-					   newfe_flags, &newfe_lock, NULL, new_dir);
+					   newfe_flags, &newfe_lock, NULL, 
+					   new_inode);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto finally;
@@ -1126,6 +1126,7 @@
 			ocfs_down_sem(&oldOIN->main_res, true);
 
 		/* move the inode offset over to the new entry */
+		SET_INODE_FEOFF(old_dentry->d_inode, tmpfe->this_sector);
 		if (S_ISDIR(old_dentry->d_inode->i_mode)) {
 			/* the vote offset doesn't actually change for
 			 * a directory, but the fe offset does... */
@@ -1164,11 +1165,7 @@
 		goto bail;
 	} else {
 		/* commit_trans */
-		status = ocfs_commit_trans(handle);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			goto bail;
-		}
+		ocfs_commit_trans(handle);
 
 		/* free bits, if we deleted anything */
 		if (free_head) {
@@ -1208,6 +1205,9 @@
 	}
 
 bail:
+	if (new_inode)
+		iput(new_inode);
+
 	if (oldfe_lock) {
 		ocfs_release_lock(osb, oldfe_lockid, 
 				  OCFS_DLM_EXCLUSIVE_LOCK, 
@@ -1342,34 +1342,11 @@
 		goto abort_trans;
 	}
 
-abort_trans:
-	if (handle) {
-		if (status < 0)
-			ocfs_abort_trans(handle);
-		else {
-			status = ocfs_commit_trans(handle);
-			if (status < 0)
-				LOG_ERROR_STATUS(status);
-		}
-	}
-
-	if (lock_res != NULL) {
-		int tmpstat;
-		tmpstat = ocfs_release_lock (osb, parent_off, OCFS_DLM_ENABLE_CACHE_LOCK,
-		     FLAG_FILE_CREATE | FLAG_DIR, lock_res, lock_bh, dir);
-		if (tmpstat < 0)
-			LOG_ERROR_STATUS (tmpstat);
-	}
-	ocfs_put_lockres (lock_res);
-
-	if (status < 0)
-		goto bail;
-
 	status = ocfs_create_oin_from_entry(osb, new_fe_bh, &oin, 
 					    parent_off, NULL);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
-		goto bail;
+		goto abort_trans;
 	}
 
 #ifdef LINUX_2_5
@@ -1390,10 +1367,25 @@
 	ocfs_inode_hash_bind(osb, GET_INODE_VOTEOFF(inode), inode);
 	d_instantiate (dentry, inode);
 
-	status = ocfs_block_symlink (inode, symname, l);
-	if (status < 0)
-		LOG_ERROR_STATUS(status);
+abort_trans:
+	if (status < 0) {
+		ocfs_abort_trans(handle);
+	} else {
+		ocfs_commit_trans(handle);
+		status = ocfs_block_symlink (inode, symname, l);
+		if (status < 0)
+			LOG_ERROR_STATUS(status);
+	}
 
+	if (lock_res != NULL) {
+		int tmpstat;
+		tmpstat = ocfs_release_lock (osb, parent_off, OCFS_DLM_ENABLE_CACHE_LOCK,
+		     FLAG_FILE_CREATE | FLAG_DIR, lock_res, lock_bh, dir);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+	}
+	ocfs_put_lockres (lock_res);
+
 bail:
 	if (new_fe_bh) {
 		if (fe)
@@ -1800,7 +1792,7 @@
 
 	if (inode && status == 0 && !(flags & FLAG_DEL_INODE)) {
 		SET_INODE_DELETED(inode);
-		printk("ocfs_fe_smash: removing inode %lu, voteoff = %u.%u\n",
+		LOG_TRACE_ARGS("removing inode %lu, voteoff = %u.%u\n",
 		       inode->i_ino, HILO(GET_INODE_VOTEOFF(inode)));
 		ocfs_inode_hash_remove(&osb->inode_hash, 
 				       GET_INODE_VOTEOFF(inode));
@@ -1809,10 +1801,8 @@
 	if (local_handle && handle && (status < 0))
 		ocfs_abort_trans(handle);
 	else if (local_handle && handle) {
-		status = ocfs_commit_trans(handle);
-		if (status < 0)
-			LOG_ERROR_STATUS(status);
-		else if (free_head) {
+		ocfs_commit_trans(handle);
+		if (free_head) {
 			/* Free the bits from the bitmap now. It's OK
 			 * if none were marked. */
 			status = ocfs_process_bitmap_free_head(osb, free_head);

Modified: trunk/src/nm.c
===================================================================
--- trunk/src/nm.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/nm.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -29,11 +29,9 @@
 /* Tracing */
 #define OCFS_DEBUG_CONTEXT      OCFS_DEBUG_CONTEXT_NM
 
-static int ocfs_release_dir_cache_lock (ocfs_super *osb, struct buffer_head **dir_bhs, struct inode *inode);
 static inline int get_process_vote_action(ocfs_super * osb, ocfs_lock_res *lockres, __u32 node_num, __u32 flags, int status, bool *master_alive, ocfs_inode **oin);
 static int ocfs_disk_update_resource (ocfs_super * osb, ocfs_lock_res * lock_res, struct buffer_head **bh, __u32 timeout, struct inode *inode);
 static int ocfs_search_commited(ocfs_super *osb, ocfs_lock_res *lockres);
-static void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode);
 static int ocfs_schedule_process_vote(ocfs_super *osb, struct buffer_head *bh, int vote_node);
 
 void ocfs_process_vote_worker(void *val);
@@ -890,7 +888,7 @@
 					/* the NO vote for delete/rename */
 					vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
 				} else if (oin && !(oin->oin_flags & OCFS_OIN_IN_TEARDOWN)) {
-					inode = oin->inode;
+//					inode = oin->inode;
 					OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_NEEDS_DELETION);
 					ocfs_up_sem (oin_sem);
 					ocfs_release_lockres (lockres);
@@ -898,7 +896,7 @@
 					oin_sem = NULL;
 				}
 			}
-			if (inode) {
+			if (inode && (flags & FLAG_ACQUIRE_LOCK)) {
 				SET_INODE_DELETED(inode);
 				ocfs_inode_hash_remove(&osb->inode_hash, 
 						     GET_INODE_VOTEOFF(inode));
@@ -956,15 +954,6 @@
 
 			status = -EFAIL;
 
-#if 0
-			if (vote_type == CHANGE_MASTER 
-			    && lockres->lock_type != OCFS_DLM_NO_LOCK) {
-				LOG_TRACE_STR("FLAG_VOTE_UPDATE_RETRY (1)");
-				vote_response = FLAG_VOTE_UPDATE_RETRY;
-				status = 0;
-				break;
-			}
-#endif
 			/* If nobody currently owns the lock, then
 			 * fastpath it. */
 			if (lockres->lock_holders == 0)
@@ -1073,35 +1062,8 @@
 			}
 			OCFS_BH_PUT_DATA(fe_bh);
 
-			if (is_dir && vote_type == RELEASE_CACHE) {
-				struct buffer_head **dir_bhs = NULL;
-				int dirblks = osb->vol_layout.dir_node_size / osb->sect_size;
-
-				dir_bhs = ocfs_malloc(dirblks * sizeof(*dir_bhs));
-				if (dir_bhs == NULL) {
-					LOG_ERROR_STATUS(status = -ENOMEM);
-					brelse(fe_bh);
-					break;
-				}
-				memset(dir_bhs, 0, dirblks * sizeof(*dir_bhs));
-
-				status = ocfs_read_dirnode(osb, lock_id, false, dir_bhs, inode);
-				if (status >= 0)
-					ocfs_release_dir_cache_lock(osb, dir_bhs, inode);
-			
-				/* we need to do a safe cleanup in either case, so */
-				/* we just jump in case of error later. */
-				for (i = 0; i < dirblks; i++)
-					if (dir_bhs[i])
-						brelse(dir_bhs[i]);
-				ocfs_safefree(dir_bhs);
-
-				if (status < 0) {
-					LOG_ERROR_STATUS(status);
-					brelse(fe_bh);
-					break;
-				}
-			}
+			if (is_dir && vote_type == RELEASE_CACHE)
+				ocfs_break_cache_lock_zap_buffers(osb, inode);
 	
 			/* need to do the write only if fe lock values need to change */
 			if (is_locked || vote_type == CHANGE_MASTER) {
@@ -1110,29 +1072,20 @@
 					fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(fe_bh); /* write */
 					DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
 					OCFS_BH_PUT_DATA(fe_bh);
-					status = ocfs_write_bh(osb, fe_bh, 0, inode);
-					if (status < 0) {
-						LOG_ERROR_STATUS (status);
-						brelse(fe_bh);
-						break;
-					}
+				}
+				status = ocfs_write_bh(osb, fe_bh, 0, inode);
+				if (status < 0) {
+					LOG_ERROR_STATUS (status);
+					brelse(fe_bh);
+					break;
+				}
+				if (vote_type == RELEASE_CACHE)
 					lockres->lock_type = lockres->lock_state = OCFS_DLM_NO_LOCK;
-				} else {
-					//if (!is_dir) /* fe_bh was written in ocfs_release_dir_cache_lock */
-					{
-						status = ocfs_write_bh(osb, fe_bh, 0, inode);
-						if (status < 0) {
-							LOG_ERROR_STATUS (status);
-							brelse(fe_bh);
-							break;
-						}
-					}
+				else // CHANGE_MASTER
 					lockres->master_node_num = node_num;
-				}
 			}
 			brelse(fe_bh);
 			vote_response = FLAG_VOTE_NODE;
-			//dump_inode_clean_queue_buffers(inode);
 			inc_inode_seq = true;
 			status = 0;
 			break;
@@ -1269,16 +1222,17 @@
 	if (status < 0)
 		LOG_ERROR_STATUS (status);
 
+	if (inode) {
+		if (inc_inode_seq)
+			ocfs_inc_inode_seq(osb, inode, true);
+		iput(inode);
+	}
+
 	if (lockres) {
 		ocfs_release_lockres (lockres);
 		ocfs_put_lockres(lockres);
 	}
 
-	if (inode) {
-		if (inc_inode_seq)
-			ocfs_inc_inode_seq(osb, inode);
-		iput(inode);
-	}
 leave:
 
 	LOG_EXIT_STATUS (status);
@@ -1286,7 +1240,7 @@
 }				/* ocfs_process_vote */
 
 
-static void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode)
+void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode, bool sync_buffers)
 {
 	atomic_t *seq = GET_INODE_CLEAN_SEQ(inode);
 
@@ -1308,10 +1262,12 @@
 	LOG_TRACE_ARGS("done incrementing inode seq... new is %d\n", 
 		       atomic_read(seq));
 
-	fsync_inode_buffers(inode);
+	if (sync_buffers) {
+		fsync_inode_buffers(inode);
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
-	fsync_inode_data_buffers(inode);
+		fsync_inode_data_buffers(inode);
 #endif
+	}
 }
 
 
@@ -1339,120 +1295,3 @@
 	}
 	ocfs_up_sem (&(osb->osb_res));
 }
-
-/*
- * ocfs_release_dir_cache_lock()
- *
- * The dir_bhs structure after this may point to a different set of
- * buffer_heads than the ones passed in (because we iterate through
- * each dirnode). You still have to clean those up though (brelse
- * them). The original ones passed in will be properly brelsed by this
- * function, so no need to worry about them.
- */
-static int ocfs_release_dir_cache_lock (ocfs_super *osb, struct buffer_head **dir_bhs, struct inode *inode)
-{
-	ocfs_file_entry *fe;
-	int status = 0;
-	int i;
-	ocfs_dir_node *dirnode = NULL;
-	int dirblks = osb->vol_layout.dir_node_size / osb->sect_size;
-	__u64 next_node_ptr;
-
-	LOG_ENTRY_ARGS ("(osb=0x%08x, dirnd=0x%08x)\n", osb, dirnode);
-
-	/* need to mark ALL buffers in a dir for write before calling write_bhs */
-	for (i = 0; i<256; i++) {
-		OCFS_BH_GET_DATA_WRITE(dir_bhs[i]);
-		OCFS_BH_PUT_DATA(dir_bhs[i]);
-	}
-	dirnode = (ocfs_dir_node *) OCFS_BH_GET_DATA_READ(dir_bhs[0]); /* read */
-
-	for(i = 0; i < dirnode->num_ent_used; i++) {
-		fe = (ocfs_file_entry *) FILEENT_GETBH_WRITE(dirnode, dir_bhs, i); /* write */
-
-		if (DISK_LOCK_FILE_LOCK(fe) == OCFS_DLM_ENABLE_CACHE_LOCK) {
-			LOG_TRACE_STR("setting lock to NO_LOCK");
-			DISK_LOCK_FILE_LOCK(fe) = OCFS_DLM_NO_LOCK;
-		}
-
-		FILEENT_PUTBH(dirnode, dir_bhs, i);
-	}
-
-	next_node_ptr = dirnode->next_node_ptr;
-	OCFS_BH_PUT_DATA(dir_bhs[0]);
-	dirnode = NULL;
-
-	status = ocfs_write_dirnode(osb, dir_bhs, inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-	
-	for (i = 0; i < 256; i++) {
-		if (dir_bhs[i]) {
-			mark_buffer_uptodate(dir_bhs[i], false);
-			CLEAR_BH_SEQNUM(dir_bhs[i]);
-		}
-	}
-
-
-	while (next_node_ptr != -1) {
-		/* clean it up */
-		for (i = 0; i < dirblks; i++)
-			if (dir_bhs[i])
-				brelse(dir_bhs[i]);
-		memset(dir_bhs, 0, dirblks * sizeof(*dir_bhs));
-
-		status = ocfs_read_dirnode(osb, next_node_ptr, false, dir_bhs, inode);
-		if (status < 0) {
-			LOG_ERROR_STATUS (status);
-			goto bail;
-		}
-
-		for (i = 0; i<256; i++) {
-			OCFS_BH_GET_DATA_WRITE(dir_bhs[i]);
-			OCFS_BH_PUT_DATA(dir_bhs[i]);
-		}
-
-		dirnode = (ocfs_dir_node *)OCFS_BH_GET_DATA_WRITE(dir_bhs[0]); /* write */
-		if(!IS_VALID_DIR_NODE(dirnode))
-			break;
-
-		LOG_TRACE_STR("setting another dirnode header to NO_LOCK");
-		DISK_LOCK_FILE_LOCK(dirnode) = OCFS_DLM_NO_LOCK;
-
-		for(i = 0; i < dirnode->num_ent_used; i++) {
-			fe = FILEENT_GETBH_WRITE(dirnode, dir_bhs, i); /* write */
-			if (DISK_LOCK_FILE_LOCK(fe) == OCFS_DLM_ENABLE_CACHE_LOCK) {
-				LOG_TRACE_STR("setting fileentry to NO_LOCK");
-				DISK_LOCK_FILE_LOCK(fe) = OCFS_DLM_NO_LOCK;
-			}
-			FILEENT_PUTBH(dirnode, dir_bhs, i);
-		}
-
-		/* for loop back */
-		next_node_ptr = dirnode->next_node_ptr;
-
-		OCFS_BH_PUT_DATA(dir_bhs[0]);
-		dirnode = NULL;
-
-		status = ocfs_write_dirnode(osb, dir_bhs, inode);
-		if (status < 0) {
-			LOG_ERROR_STATUS (status);
-			goto bail;
-		}
-		for (i = 0; i < 256; i++) {
-			if (dir_bhs[i]) {
-				mark_buffer_uptodate(dir_bhs[i], false);
-				CLEAR_BH_SEQNUM(dir_bhs[i]);
-			}
-		}
-	}
-
-bail:
-	if (dirnode)
-		OCFS_BH_PUT_DATA(dir_bhs[0]);
-
-	LOG_EXIT_STATUS(status);
-	return (status);
-}				/* ocfs_release_dir_cache_lock */

Modified: trunk/src/osb.c
===================================================================
--- trunk/src/osb.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/osb.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -489,7 +489,6 @@
 	struct buffer_head *hdr_bh = NULL;
 	ocfs_dir_node *NewDirNode = NULL;
 	int size, i;
-	unsigned long blk;
 
 	LOG_ENTRY ();
 

Modified: trunk/src/proc.c
===================================================================
--- trunk/src/proc.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/proc.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -449,12 +449,15 @@
   "Dir node size            : %u.%u\n"         \
   "File node size           : %u.%u\n"         \
   "Failed Large Allocs      : %u\n"            \
-  "Retry Large Allocs       : %u\n"
+  "Retry Large Allocs       : %u\n"            \
+  "Inode Hash Objects       : %u\n"
 
 	len = sprintf (page, PROC_STATS, HILO (osb->file_open_cnt), pubmap,
 		       vol->num_nodes, vol->cluster_size, HILO (vol->size),
 		       HILO (vol->dir_node_size), HILO (vol->file_node_size),
-		       osb->cluster_bitmap.failed, osb->cluster_bitmap.ok_retries);
+		       osb->cluster_bitmap.failed, 
+		       osb->cluster_bitmap.ok_retries, 
+		       osb->inode_hash.num_ents);
 
 	ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
 

Modified: trunk/src/super.c
===================================================================
--- trunk/src/super.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/super.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -56,7 +56,7 @@
 };
 static struct ctl_table_header *ocfs_table_header = NULL;
 
-EXPORT_NO_SYMBOLS;
+// -disabled for ocfs_show_trace- EXPORT_NO_SYMBOLS;
 
 MODULE_LICENSE ("GPL");
 MODULE_AUTHOR("Oracle Corporation");
@@ -761,6 +761,10 @@
 		sizeof(ocfs_bh_sem), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
 		NULL, NULL);
 
+	OcfsGlobalCtxt.inum_cache = kmem_cache_create("ocfs2_inum", 
+		sizeof(ocfs_inode_num), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN, 
+		NULL, NULL);
+
 	OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
 
 	return 0;
@@ -778,6 +782,7 @@
 	kmem_cache_destroy (OcfsGlobalCtxt.lockres_cache);
 	kmem_cache_destroy (OcfsGlobalCtxt.extent_cache);
 	kmem_cache_destroy (OcfsGlobalCtxt.bh_sem_cache);
+	kmem_cache_destroy (OcfsGlobalCtxt.inum_cache);
 	OCFS_CLEAR_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
 }				/* ocfs_free_mem_lists */
 

Modified: trunk/src/util.c
===================================================================
--- trunk/src/util.c	2004-01-29 07:58:15 UTC (rev 18)
+++ trunk/src/util.c	2004-02-03 01:29:16 UTC (rev 19)
@@ -36,6 +36,8 @@
 
 #ifndef USERSPACE_TOOL
 
+static void ocfs_timeout_func(unsigned long data);
+
 /*
  * ocfs_daemonize() 
  *
@@ -321,6 +323,46 @@
 #endif
 #endif
 
+
+static void ocfs_timeout_func(unsigned long data)
+{
+	ocfs_timeout *to = (ocfs_timeout *)data; 
+
+	to->timed_out = 1;
+	wake_up(&to->wait);
+}
+
+void ocfs_init_timeout(ocfs_timeout *to)
+{
+	init_timer(&to->timer);
+	to->timer.data = (unsigned long)to;
+	to->timer.function = ocfs_timeout_func;
+	to->timed_out = 0;
+	init_waitqueue_head(&to->wait);
+}
+
+void ocfs_set_timeout(ocfs_timeout *to, __u32 timeout)
+{
+	__u32 how_long;
+
+	if (!timeout) {
+		to->timed_out = 1;
+		return ;
+	}
+
+	how_long = (timeout * HZ / 1000);
+	if (how_long < 1)
+		how_long = 1;
+
+	to->timer.expires = jiffies + how_long;
+	add_timer(&to->timer);
+}
+
+void ocfs_clear_timeout(ocfs_timeout *to)
+{
+	del_timer_sync(&to->timer);
+}
+
 #endif				/* !USERSPACE_TOOL */
 
 /*
@@ -363,9 +405,73 @@
 
 	mark_buffer_uptodate(bh, uptodate);
 	unlock_buffer(bh);
-	VERBOSE_UNLOCK_BUFFER_STR(bh);
 
 //	LOG_EXIT();
 	return;
 }
 
+
+
+/*
+To print the ocfs call stack use: ocfs_show_stack( NULL);
+
+ocfs_show_trace prints alot of garbage because nothing usefull is exported
+by the kernel to determine which addresses are from the kernel/modules
+
+However the following greps will help you filter out most of the garbage
+from the syslog :
+
+alias ocfstrace='tail -200 /var/log/messages | grep -v modules | grep -v \\\[\<'
+*/
+
+
+
+void ocfs_show_stack(unsigned long * esp)
+{
+        unsigned long *stack;
+        int depth_to_print=16, i;
+
+        // debugging aid: "show_stack(NULL);" prints the
+        // back trace for this cpu.
+
+        if(esp==NULL)
+                esp=(unsigned long*)&esp;
+
+        stack = esp;
+        for(i=0; i < depth_to_print; i++) {
+                if (((long) stack & (THREAD_SIZE-1)) == 0)
+                        break;
+                if (i && ((i % 8) == 0))
+                        printk("\n       ");
+                printk("%08lx ", *stack++);
+        }
+        printk("\n");
+        ocfs_show_trace(esp);
+}
+
+static int ocfs_kernel_text_address(unsigned long addr)
+{
+  return  (addr >= 0xc0000000 ) ; 
+}
+
+void ocfs_show_trace(unsigned long * stack)
+{
+        unsigned long addr;
+        /* static to not take up stackspace; if we race here too bad */
+
+        if (!stack)
+                stack = (unsigned long*)&stack;
+
+        printk("Call Trace: \n");
+        
+        while (((long) stack & (THREAD_SIZE-1)) != 0) {
+                addr = *stack++;
+                if (ocfs_kernel_text_address(addr)) {
+                //        lookup_symbol(addr, buffer, 512);
+                        printk("[<%08lx>] %s (0x%x)\n", addr," ",stack-1);
+                }
+        }
+        printk("\n");
+
+
+}



More information about the Ocfs2-commits mailing list