[Ocfs2-commits] rev 10 - in trunk: . inc

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Dec 16 23:55:29 CST 2003


Author: manish
Date: 2003-12-16 17:55:26 -0600 (Tue, 16 Dec 2003)
New Revision: 10

Modified:
   trunk/Makefile
   trunk/TODO
   trunk/alloc.c
   trunk/bitmap.c
   trunk/dlm.c
   trunk/file.c
   trunk/inc/journal.h
   trunk/inc/ocfs.h
   trunk/inc/ocfsio.h
   trunk/inc/proto.h
   trunk/inode.c
   trunk/journal.c
   trunk/namei.c
   trunk/nm.c
   trunk/osb.c
   trunk/super.c
   trunk/sysfile.c
Log:
sync


Modified: trunk/Makefile
===================================================================
--- trunk/Makefile	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/Makefile	2003-12-16 23:55:26 UTC (rev 10)
@@ -152,7 +152,12 @@
 endif
 
 DEFINES += -DDEBUG_LOCK_BUFFER
+DEFINES += -DVERBOSE_BH_JBD_TRACE
+DEFINES += -DVERBOSE_LOCKING_TRACE
+DEFINES += -DOCFS_DBG_TIMING
 
+DEFINES += -DALLOW_NO_HANDLE_SYNCING
+
 ifeq ($(KVER),vmware)
   KERNELINC = /usr/src/linux-2.4/include
 endif

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/TODO	2003-12-16 23:55:26 UTC (rev 10)
@@ -1,9 +1,5 @@
-* fix dlm issue with stale locks
-
 * fsck must be able to replay the journal
 
-* merge and turn on the data alloc file
-
 * 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/alloc.c
===================================================================
--- trunk/alloc.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/alloc.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -10,8 +10,6 @@
 /* Tracing */
 #define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_EXTENT
 
-static int ocfs_find_new_space_from_bitmap(ocfs_super *osb, __u64 file_size, __u64 *PClusterOffset, __u64 *PNumClusterAlloc, ocfs_file_entry *fe);
-
 static int ocfs_allocate_new_data_node (ocfs_super * osb, 
 				 ocfs_file_entry * FileEntry,
 				 __u64 actualDiskOffset, __u64 actualLength, 
@@ -46,6 +44,17 @@
 static inline int ocfs_free_main_bitmap(ocfs_super *osb, 
 					ocfs_free_rec *freelog);
 
+static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh);
+static int ocfs_sync_local_to_main(ocfs_super *osb, 
+				   ocfs_bitmap_free_head **f, 
+				   struct buffer_head *local_alloc_bh, 
+				   struct buffer_head *bm_lock_bh);
+static __u32 ocfs_alloc_count_bits(ocfs_local_alloc *alloc);
+static void ocfs_clear_local_alloc(ocfs_local_alloc *alloc);
+static int ocfs_find_space_from_local(ocfs_super *osb, __u32 bitswanted, 
+				      __u64 * bitoff, __u64 * bitcount, 
+				      ocfs_journal_handle *handle);
+static int ocfs_local_find_clear_bits(ocfs_super *osb, ocfs_local_alloc *alloc, __u32 numbits);
 
 /* this is a good candidate for an inline function. */
 int ocfs_process_bitmap_free_head(ocfs_super *osb, ocfs_bitmap_free_head *f) 
@@ -2658,8 +2667,11 @@
  * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
  *
  * Returns 0 on success, < 0 on error.
+ *
+ * Pass in 'lock_bh' only if you've already taken the vol_alloc
+ * semaphore, and you've done the acquire_lock on the bitmap.
  */
-int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile)
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, struct buffer_head *lock_bh)
 {
 	int status = 0, tmpstat, startbh, numblocks;
 	__u32 bitoffset = 0, ClusterCount = 0;
@@ -2667,171 +2679,179 @@
 	__u32 LargeAlloc = 0;
 	static __u32 LargeAllocOffset = 0;
 	static __u32 SmallAllocOffset = 0;
-	__u64 startOffset = 0;
 	bool bLockAcquired = false;
 	ocfs_lock_res *pLockResource = NULL;
         struct buffer_head *bh = NULL;
         ocfs_bitmap_lock *bm_lock = NULL;
 	__u32 bitmapblocks; /* we only care about the valid blocks */
+	bool local_lock = true;
 
 	LOG_ENTRY ();
 
 	OCFS_ASSERT (osb);
 
-	ocfs_down_sem (&(osb->vol_alloc_lock), true);
+	if (lock_bh) {
+		local_lock = false;
+		bh = lock_bh;
+	}
 
-	/* always use global bitmap for clustersize > 128k, file_size > 2mb */
-#if 0
-	if (osb->vol_layout.cluster_size > (128*1024) || file_size > (2 * 1024 * 1024)) 
-#endif
-	if (true)
-	{
+	if (local_lock) {
+		ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
 		/* Get the allocation lock here */
 		status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
-				     OCFS_DLM_EXCLUSIVE_LOCK /*OCFS_DLM_ENABLE_CACHE_LOCK*/, 0, &pLockResource,
-				     &bh, NULL);
+					    OCFS_DLM_EXCLUSIVE_LOCK, 0, 
+					    &pLockResource, &bh, NULL);
 		if (status < 0) {
 			if (status != -EINTR)
 				LOG_ERROR_STATUS (status);
 			goto leave;
 		}
 		bLockAcquired = true;
-	        bm_lock = (ocfs_bitmap_lock *)OCFS_BH_GET_DATA(bh);
+	}
+	bm_lock = (ocfs_bitmap_lock *)OCFS_BH_GET_DATA(bh);
+
+	ByteCount = file_size;
+
+	/* Round off the byte count to next clustersize (bytes per cluster) */
+	ByteCount += (ByteCount % (osb->vol_layout.cluster_size)) ?
+		(osb->vol_layout.cluster_size -
+		 (ByteCount % (osb->vol_layout.cluster_size))) : 0;
+
+	if (ByteCount == 0) {
+		LOG_ERROR_STR ("DISK_FULL?: Bytecount==0");
+		status = 0;
+		goto leave;
+	}
+
+	ClusterCount = (__u32) 
+		((__u64) ByteCount / (__u64) osb->vol_layout.cluster_size);
+
+	if (sysfile ? (ClusterCount > osb->vol_layout.num_clusters) :
+	    (ClusterCount > (osb->vol_layout.num_clusters - 
+			     ((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size)))){
+		LOG_ERROR_STR ("Disk Full");
+		status = -ENOSPC;
+		goto leave;
+	}
 	
-		ByteCount = file_size;
+	/* This function will check for clear bits in the Bitmap for
+	 * consecutive */
+	/* clear bits equal to ClusterCount */
+
+	/* If we create a chunk that is larger than 5% of the
+	 * disksize, then start */
+	/* allocation at 5%, so that small files stay in the beginning
+	 * as much as possible */
+
+	if (ClusterCount > (osb->vol_layout.num_clusters / 20)) {
+		LargeAlloc = 1;
+		LargeAllocOffset = (osb->vol_layout.num_clusters / 20);
+	}
+
+	bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits, 
+				   OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
 	
-		/* Round off the byte count to next clustersize (bytes per cluster) */
-		ByteCount += (ByteCount % (osb->vol_layout.cluster_size)) ?
-		    (osb->vol_layout.cluster_size -
-		     (ByteCount % (osb->vol_layout.cluster_size))) : 0;
+	/* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
+	if (ocfs_read_bhs(osb, osb->vol_layout.bitmap_off, 
+			  bitmapblocks * osb->sect_size, 
+			  osb->cluster_bitmap.chunk, 0, NULL)) {
+		LOG_ERROR_STATUS(-EIO);
+		goto leave;
+	}
 	
-		if (ByteCount == 0) {
-			LOG_ERROR_STR ("DISK_FULL?: Bytecount==0");
-			status = 0;
-			goto leave;
-		}
-	
-		ClusterCount =
-		    (__u32) ((__u64) ByteCount / (__u64) osb->vol_layout.cluster_size);
-	
-		if (sysfile ? (ClusterCount > osb->vol_layout.num_clusters) :
-				(ClusterCount > (osb->vol_layout.num_clusters - 
-			        ((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size)))){
-			LOG_ERROR_STR ("Disk Full");
-			status = -ENOSPC;
-			goto leave;
-		}
-	
-		/* This function will check for clear bits in the Bitmap for consecutive */
-		/* clear bits equal to ClusterCount */
-	
-		/* If we create a chunk that is larger than 5% of the disksize, then start */
-		/* allocation at 5%, so that small files stay in the beginning as much as possible */
-		
-		if (ClusterCount > (osb->vol_layout.num_clusters / 20)) {
-			LargeAlloc = 1;
-			LargeAllocOffset = (osb->vol_layout.num_clusters / 20);
-		}
-		
-		bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits, OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
-	
-		/* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
-		if (ocfs_read_bhs(osb, osb->vol_layout.bitmap_off, 
-				   bitmapblocks * osb->sect_size, 
-				   osb->cluster_bitmap.chunk, 0, NULL)) {
-			LOG_ERROR_STATUS(-EIO);
-			goto leave;
-		}
-	
-		bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap, 
-						   ClusterCount,
-						LargeAlloc ? LargeAllocOffset :
-						SmallAllocOffset, sysfile ? 0 :
-						((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size));
-	
-		/* if fails we should try again from the beginning of the disk. */
-		/* in the end we pass # of bits we want to keep for system file extention only */
-		/* right now if we run out of diskspace, we still have 8mb free for a systemfile */
-	
-		if (bitoffset == -1 && LargeAlloc) {
-			LOG_TRACE_STR("Running low on diskspace.");
-			osb->cluster_bitmap.failed++;
-			bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
-						ClusterCount, 0,
-						sysfile ? 0 :
-							((8 * ONE_MEGA_BYTE) /
-							 osb->vol_layout.cluster_size));
-		}
-	
-		/* It returns -1 on failure, otherwise bitoffset points at the */
-		/* location inb bitmap from where there are ClusterCount no of bits */
-		/* are free.  */
-	
-		if (bitoffset == -1) {
-			if (sysfile)
-				LOG_ERROR_ARGS ("Cannot allocate %u contiguous clusters for system file\n",
+	bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap, 
+					  ClusterCount,
+					  LargeAlloc ? LargeAllocOffset :
+					  SmallAllocOffset, sysfile ? 0 :
+					  ((8 * ONE_MEGA_BYTE) / 
+					   osb->vol_layout.cluster_size));
+
+	/* if fails we should try again from the beginning of the disk. */
+	/* in the end we pass # of bits we want to keep for system
+	 * file extention only.  */
+	/* Right now if we run out of diskspace, we still have 8mb
+	 * free for a systemfile */
+
+	if (bitoffset == -1 && LargeAlloc) {
+		LOG_TRACE_STR("Running low on diskspace.");
+		osb->cluster_bitmap.failed++;
+		bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
+						  ClusterCount, 0,
+						  sysfile ? 0 :
+						  ((8 * ONE_MEGA_BYTE) /
+						   osb->vol_layout.cluster_size));
+	}
+
+	/* It returns -1 on failure, otherwise bitoffset points at the */
+	/* location inb bitmap from where there are ClusterCount no of bits */
+	/* are free.  */
+
+	if (bitoffset == -1) {
+		if (sysfile)
+			LOG_ERROR_ARGS ("Cannot allocate %u contiguous clusters for system file\n",
 					ClusterCount);
-			status = -ENOSPC;
-			goto leave;
-		}
+		status = -ENOSPC;
+		goto leave;
+	}
+
+	LOG_TRACE_ARGS ("byte offset=%u\n", bitoffset);
+
+	ocfs_set_bits (&osb->cluster_bitmap, bitoffset, ClusterCount);
+
+	/* Ok, write out the bitmap now. We optimize only by writing
+	 * out the bitmap blocks which have changed, and not all of
+	 * them like before. */
+	startbh = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset);
+	numblocks = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset + ClusterCount) - startbh + 1;
+
+	LOG_TRACE_ARGS("bitoffset = %u, ClusterCount = %u, startbh = %u, numblocks = %u\n", bitoffset, ClusterCount, startbh, numblocks);
 	
-		LOG_TRACE_ARGS ("byte offset=%u\n", bitoffset);
-	
-		ocfs_set_bits (&osb->cluster_bitmap, bitoffset, ClusterCount);
-	
-		/* Ok, write out the bitmap now. We optimize only by writing
-		 * out the bitmap blocks which have changed, and not all of
-		 * them like before. */
-		startbh = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset);
-		numblocks = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset + ClusterCount) - startbh + 1;
-	
-		LOG_TRACE_ARGS("bitoffset = %u, ClusterCount = %u, startbh = %u, numblocks = %u\n", bitoffset, ClusterCount, startbh, numblocks);
-	
-		status = ocfs_write_bhs(osb, &osb->cluster_bitmap.chunk[startbh], 
-					numblocks, 0, NULL);
-		if (status < 0) {
-			LOG_ERROR_STATUS (status);
-			goto leave;
-		}
-	
-	        /* write the bitmap size info to the lock sector */
-	        /* TODO: optimize by making this part of ocfs_release_lock 
-	         * for now, it will be back-to-back writes to same sector */
-	        bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
-		OCFS_BH_PUT_DATA(bh);
-		bm_lock = NULL;
-	
-		status = ocfs_write_bh (osb, bh, 0, NULL);
-	        if (status < 0) {
-	                LOG_ERROR_STATUS (status);
-	                goto leave;
-	        }
-	
-		*cluster_off = bitoffset;
-		*cluster_count = ClusterCount;
-		status = 0;
+	status = ocfs_write_bhs(osb, &osb->cluster_bitmap.chunk[startbh], 
+				numblocks, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
 	}
-#if 0
-       	else {
-		status = ocfs_get_space_from_bitmap(osb, file_size, cluster_off, cluster_count);
+
+	/* write the bitmap size info to the lock sector */
+	/* TODO: optimize by making this part of ocfs_release_lock 
+	 * for now, it will be back-to-back writes to same sector */
+	bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
+	OCFS_BH_PUT_DATA(bh);
+	bm_lock = NULL;
+
+	status = ocfs_write_bh (osb, bh, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
 	}
-#endif
 
+	*cluster_off = bitoffset;
+	*cluster_count = ClusterCount;
+	status = 0;
+
 leave:
-	ocfs_up_sem (&(osb->vol_alloc_lock));
 	if (bm_lock != NULL)
 		OCFS_BH_PUT_DATA(bh);
 
-	if (bLockAcquired) {
-		tmpstat = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
-				OCFS_DLM_EXCLUSIVE_LOCK, 0, pLockResource, bh, NULL);
-		if (tmpstat < 0)
-			LOG_ERROR_STATUS (tmpstat);
+	if (local_lock) {
+		ocfs_up_sem (&(osb->vol_alloc_lock));
+
+		if (bLockAcquired) {
+			tmpstat = ocfs_release_lock(osb, 
+						    OCFS_BITMAP_LOCK_OFFSET,
+						    OCFS_DLM_EXCLUSIVE_LOCK, 
+						    0, pLockResource, bh, 
+						    NULL);
+			if (tmpstat < 0)
+				LOG_ERROR_STATUS (tmpstat);
+		}
+		if (bh != NULL)
+			brelse(bh);
+		ocfs_put_lockres (pLockResource);
 	}
-	if (bh != NULL)
-		brelse(bh);
 
-	ocfs_put_lockres (pLockResource);
 	LOG_EXIT_STATUS (status);
 	return status;
 }				/* ocfs_find_contiguous_space_from_bitmap */
@@ -2862,13 +2882,12 @@
 	ocfs_lock_res *pLockResource = NULL;
 	__u32 fileId = 0;
 	__u32 extendFileId = 0;
-	ocfs_log_record *pOcfsLogRec = NULL;
 	struct buffer_head *bh = NULL;
 	ocfs_file_entry *fe = NULL;
 	bool needs_uninit = false;
 	bool delay_lockrel = false;
 
-	LOG_ENTRY ();
+	LOG_ENTRY_ARGS("(FileSize = (%u.%u), Type=%d)\n", HILO(FileSize),Type);
 
 	ocfs_down_sem (&(osb->dir_alloc_lock), true);
 	ocfs_down_sem (&(osb->file_alloc_lock), true);
@@ -3067,7 +3086,6 @@
 	if (bh != NULL)
 		brelse(bh);
 
-	ocfs_safefree (pOcfsLogRec);
 	LOG_EXIT_STATUS (status);
 	return status;
 }				/* ocfs_alloc_node_block */
@@ -3213,178 +3231,754 @@
 	return status;
 }				/* ocfs_free_file_extents */
 
+/* Some constants and functions that control how we allocate and use
+ * local alloc bitmaps. These are intended to be easily
+ * tunable. Possibly even remove them once we've found a good mix. */
 
-#if 0
-int ocfs_get_space_from_bitmap(ocfs_super *osb, __u64 file_size, __u64 *PClusterOffset, __u64 *PNumClusterAlloc) 
+/* The largest cluster size where we even consider using local alloc. */
+#define OCFS_LOCAL_ALLOC_MAX_CSIZE    (128 * 1024)
+/* The largest allocation to use the local bitmap for. */
+#define OCFS_LOCAL_ALLOC_MAX_ALLOC    (2 * 1024 * 1024)
+
+/* 
+ * ocfs_local_alloc_window_bits
+ * 
+ * Determine how large our local alloc window should be, in bits. This
+ * is entirely changeable -- just replace this function. Right now as
+ * a *testing* default, we have a function that takes cluster size
+ * into account in the following manner: 
+ *
+ * 4k -> 1024 bits, 8k -> 512 bits, 16k -> 256 bits, 
+ * 32/64/128k -> 64 bits
+ */
+static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
 {
-	int status = 0, ntStatus; 
-	ocfs_file_entry * fe; 
-	__u64 diskOffset, ByteCount = 0;
-	__u32 size = 0, ByteOffset =0, ClusterCount = 0; 
-	__u64 numClusterAlloc = 0, BitmapOffset = 0
-	__u64 actualDiskOffset = 0;
-       	__u64 csize = osb->vol_layout.cluster_size; 
-	ocfs_lock_res *pLockResource; 
-	ocfs_alloc_bm VolBitMap ; 
-	void *bitMapBuffer = NULL; 
-	__u32 bitMapSize; 
-	bool bLockAcquired = false; 
-	char *localBuf; 
-	int i; 
-	 
-	fe = osb->vol_bitmap_buf; 
- 
-	if (fe->file_size == 0) {
-		// Read in the file entry corresponding to this nodes volume bitmap file 
-		diskOffset = ((OCFS_VOL_BITMAP_FILE + (2 * osb->node_num) ) * 512) + osb->vol_layout.root_int_off;
-		status = ocfs_read_force_disk( osb, fe, 1024, diskOffset);			 
-		if (status < 0)
+	int numbits;
+
+	switch (osb->vol_layout.cluster_size) {
+	case (4*1024):
+		numbits = 1024;
+		break;
+
+	case (8*1024):
+		numbits = 512;
+		break;
+
+	case (16*1024):
+		numbits = 256;
+		break;
+
+	default:
+		numbits = 64;
+		break;
+	}
+	return(numbits);
+} /* ocfs_local_alloc_window_bits */
+
+/*
+ * ocfs_alloc_count_bits
+ */
+static __u32 ocfs_alloc_count_bits(ocfs_local_alloc *alloc)
+{
+	int i;
+	__u8 tmp;
+	__u8 *buffer;
+	__u32 count = 0;
+
+	LOG_ENTRY();
+
+	buffer = &(alloc->bitmap[0]);
+	for (i = 0; i < 256; i++) {
+		memcpy(&tmp, buffer, 1);
+		count+= BITCOUNT(tmp);
+		buffer++;
+	}
+
+	LOG_EXIT_ULONG (count);
+	return(count);
+} /* ocfs_alloc_count_bits */
+
+/*
+ * ocfs_clear_local_alloc
+ */
+static void ocfs_clear_local_alloc(ocfs_local_alloc *alloc) 
+{
+	int i;
+	LOG_ENTRY();
+
+	alloc->alloc_size = 0;
+	alloc->num_used = 0;
+	alloc->bitmap_start = 0;
+	for(i = 0; i < 256; i++)
+		alloc->bitmap[i] = 0;
+
+	LOG_EXIT();
+	return;
+} /* ocfs_clear_local_alloc */
+
+/* 
+ * ocfs_sync_local_to_main
+ *
+ * sync the local alloc to main bitmap. 
+ *
+ * 'osb' and 'f' are always assumed to be valid (though they don't
+ * have to be allocated)
+ *
+ * local_alloc_bh is optional. If not passed, we use the one off osb.
+ *
+ * bm_lock_bh should be passed in if you've already locked the main
+ * bitmap, otherwise we'll do our own locking. */
+static int ocfs_sync_local_to_main(ocfs_super *osb, 
+				   ocfs_bitmap_free_head **f, 
+				   struct buffer_head *local_alloc_bh, 
+				   struct buffer_head *bm_lock_bh)
+{
+	int status = 0, tmpstat;
+	ocfs_lock_res *bm_lock_res = NULL;
+	__u32 bitmapblocks;
+	struct buffer_head *bh = NULL;
+	int bit_off, left;
+	ocfs_local_alloc *alloc = NULL;
+	bool local_lock = true;
+
+	LOG_ENTRY();
+
+	if (!local_alloc_bh)
+		local_alloc_bh = osb->local_alloc_bh;
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(local_alloc_bh);
+	if (alloc->alloc_size == 0) {
+		OCFS_BH_PUT_DATA(local_alloc_bh);
+		LOG_TRACE_STR("nothing to sync!");
+		goto bail;
+	}
+	OCFS_BH_PUT_DATA(local_alloc_bh);
+
+	if (bm_lock_bh) {
+		local_lock = false;
+		bh = bm_lock_bh;
+	}
+
+	if (local_lock) {
+		ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
+		/* Get the allocation lock here */
+		status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+					    OCFS_DLM_EXCLUSIVE_LOCK, 0, 
+					    &bm_lock_res, &bh, NULL);
+		if (status < 0) {
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
 			goto bail;
-		fe->file_size = 1; 
-	} 
- 
- 
-	if (fe->AllocationSize != 0) { 
-		ocfs_alloc_bm localNodeBitmap; 
-		__u32 localBitMapSize; 
+		}
+	}
 
-		ByteCount = file_size;
-		ByteCount += (ByteCount%csize ? csize - (ByteCount%csize) : 0); 
-		 
-		if (ByteCount == 0) { 
-			status = -ENOSPC;
+	bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits, 
+				   OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
+
+	status = ocfs_read_bhs(osb, osb->vol_layout.bitmap_off, 
+			       bitmapblocks * osb->sect_size, 
+			       osb->cluster_bitmap.chunk, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	if (!(*f)) {
+		*f = alloc_bitmap_free_head();
+		if (*f == NULL) {
+			LOG_ERROR_STATUS(-ENOMEM);
 			goto bail;
-		} 
-		 
-		ClusterCount = (__u32)(ByteCount / csize);
-		 
-		// Look in the local bitmap for the reqd number of bits 
-		if(fe->extents[0].disk_off == 0 || fe->extents[0].num_bytes == 0) { 
-			printk("something is messed\n");
-		} 
- 
-		localBitMapSize = (__u32)((fe->extents[0].num_bytes) / csize); 
-		ocfs_initialize_bitmap(&localNodeBitmap, (__u32 *)(osb->vol_bitmap_buf + 512), localBitMapSize);
-		ByteOffset = ocfs_find_clear_bits (&localNodeBitmap, ClusterCount, 0); 
-		if (ByteOffset != -1) {
-			ocfs_set_bits (&localNodeBitmap, ByteOffset, ClusterCount);		 
-		 
-			// For now Flush the bitmap here itself 
-			diskOffset = ((OCFS_VOL_BITMAP_FILE + (2 * osb->node_num) ) * 512) + 
-				osb->vol_layout.root_int_off;
-			status = ocfs_write_force_disk(osb, fe, (2 * 512), diskOffset);			 
-			if (status >= 0) {
-				*PClusterOffset = (__u32)(ByteOffset + (__u32)fe->extents[0].file_off); 
-				*PNumClusterAlloc = ClusterCount;
+		}
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(local_alloc_bh);
+
+	LOG_TRACE_ARGS("alloc->alloc_size = %u, COUNT = %u, num_used = %u\n", 
+		       alloc->alloc_size, ocfs_alloc_count_bits(alloc), 
+		       alloc->num_used);
+	/* any unset bits in local alloc need to be unset in bitmap. */
+	bit_off = 0;
+	left = alloc->alloc_size;
+	while ((bit_off = find_next_zero_bit(alloc->bitmap, left, bit_off)) 
+	       != -1) {
+		if (bit_off >= left) {
+			/*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
+			break;
+		}
+	     /* LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n", bit_off);*/
+		status = ocfs_add_to_bitmap_free_head(osb, 
+						 *f, 1, 
+						 bit_off + alloc->bitmap_start,
+						 -1, DISK_ALLOC_VOLUME);
+		if (status < 0) {
+			free_bitmap_free_head(*f);
+			*f = NULL;
+		}
+		bit_off++;
+	}
+
+	OCFS_BH_PUT_DATA(local_alloc_bh);
+
+bail:
+	if (local_lock) {
+		ocfs_up_sem (&(osb->vol_alloc_lock));
+
+		if (bm_lock_res) {
+			tmpstat = ocfs_release_lock (osb, 
+						     OCFS_BITMAP_LOCK_OFFSET,
+						     OCFS_DLM_EXCLUSIVE_LOCK, 
+						     0, bm_lock_res, bh, NULL);
+			if (tmpstat < 0)
+				LOG_ERROR_STATUS (tmpstat);
+			ocfs_put_lockres (bm_lock_res);
+		}
+		if (bh != NULL)
+			brelse(bh);
+	}
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_sync_local_to_main */
+
+/*
+ * ocfs_alloc_new_window
+ *
+ * pass it the bitmap lock in lock_bh if you have it. 
+ */
+static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh)
+{
+	int status = 0;
+	__u64 alloc_bytes, cluster_off, cluster_count;
+	__u32 csize = osb->vol_layout.cluster_size;
+	ocfs_local_alloc *alloc = NULL;
+
+	LOG_ENTRY();
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
+	if (alloc->alloc_size != 0)
+		LOG_TRACE_STR("asking me to alloc a new window over a"
+			      " non-empty one");
+	OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+
+	/* we try to use find_contig_space_from_bitmap here for now. */
+	alloc_bytes = ocfs_local_alloc_window_bits(osb) * csize;
+	LOG_TRACE_ARGS("Allocating %u.%u bytes (%u clusters) for a "
+		       "new window.\n", HILO(alloc_bytes), 
+		       ocfs_local_alloc_window_bits(osb));
+
+	status = ocfs_find_contiguous_space_from_bitmap(osb, alloc_bytes, 
+							&cluster_off, 
+							&cluster_count, false, 
+							lock_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
+
+	alloc->bitmap_start = cluster_off;
+	alloc->alloc_size = cluster_count;
+	/* just in case... In the future when we find space ourselves,
+	 * we don't have to get all contiguous -- but we'll have to
+	 * set all previously used bits in bitmap and update
+	 * num_used before setting the bits in the main bitmap. */
+	alloc->num_used = 0;
+	memset(alloc->bitmap, 0, 256);
+
+	LOG_TRACE_STR("New window allocated:");
+	LOG_TRACE_ARGS("window bitmap_start = %u\n", alloc->bitmap_start);
+	LOG_TRACE_ARGS("window alloc_size = %u\n", alloc->alloc_size);
+
+	OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+bail:
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_alloc_new_window */
+
+/*
+ * ocfs_local_find_clear_bits
+ */
+static int ocfs_local_find_clear_bits(ocfs_super *osb, ocfs_local_alloc *alloc,
+				      __u32 numbits)
+{
+	int numfound, bitoff, left, startoff, lastzero;
+	__u8 *bitmap = NULL;
+
+	LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
+
+	bitmap = alloc->bitmap;
+
+	numfound = bitoff = startoff = 0;
+	lastzero = -1;
+	left = alloc->alloc_size;
+	while ((bitoff = find_next_zero_bit(bitmap, left, startoff)) != -1) {
+		if (bitoff == left) {
+			/* LOG_TRACE_ARGS("bitoff (%d) == left", bitoff); */
+			break;
+		}
+		/* LOG_TRACE_ARGS("Found a zero: bitoff = %d, startoff = %d, "
+		   "numfound = %d\n", bitoff, startoff, numfound);*/
+
+		/* Ok, we found a zero bit... is it contig. or do we
+		 * start over?*/
+		if (bitoff == startoff) {
+			/* we found a zero */
+			numfound++;
+			startoff++;
+		} else {
+			/* got a zero after some ones */
+			numfound = 1;
+			startoff = bitoff+1;
+		}
+		/* we got everything we needed */
+		if (numfound == numbits) {
+			/* LOG_TRACE_STR("Found it all!"); */
+			break;
+		}
+	}
+
+	LOG_TRACE_ARGS("Exiting loop, bitoff = %d, numfound = %d\n", bitoff, 
+		       numfound);
+
+	if (numfound == numbits)
+		bitoff = startoff - numfound;
+	else
+		bitoff = -1;
+
+	LOG_EXIT_STATUS(bitoff);
+	return(bitoff);
+} /* ocfs_local_find_clear_bits */
+
+/*
+ * ocfs_find_space_from_local
+ *
+ * We're somewhat sensitive to aborts here. If we're moving our
+ * window, or shutting down due to error, we skip our own journal
+ * handling and send the buffer straight to jbd. This ensures that if
+ * we abort_trans during one of those operations, it still gets
+ * written out. This way, the code above us can always process our
+ * bitmap free head, and our latest window will always hit disk.
+ */
+static int ocfs_find_space_from_local(ocfs_super *osb, __u32 bitswanted, 
+				      __u64 * bitoff, __u64 * bitcount, 
+				      ocfs_journal_handle *handle)
+{
+	ocfs_local_alloc *alloc = NULL;
+	int status = 0, tmpstat;
+	int startoff, tmpoff;
+	__u32 tmpwanted;
+	bool dontdirty = false;
+	/* main bitmap variables. */
+	struct buffer_head *main_bm_bh = NULL;
+	ocfs_lock_res *bm_lock_res = NULL;
+
+	LOG_ENTRY_ARGS("(bitswanted = %u)\n", bitswanted);
+	
+	if (!osb->have_local_alloc)
+		BUG();
+
+	if (bitswanted > ocfs_local_alloc_window_bits(osb)) {
+		LOG_TRACE_STR("Asking for more than my max window size!\n");
+		status = -ENOSPC;
+		goto bail;
+	}
+
+	status = ocfs_journal_access(handle, osb->local_alloc_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
+tryagain:
+	/* If we need to initialize a new window, do so now. */
+	if (alloc->alloc_size == 0) {
+		OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+		alloc = NULL;
+		LOG_TRACE_STR("Allocating a new window...");
+
+		status = ocfs_alloc_new_window(osb, main_bm_bh);
+		if (status < 0) {
+			if (status == -ENOSPC) {
+				printk("ocfs: disabling local alloc "
+				       "bitmap for this mount.\n");
+				/* at this point, we shouldn't have
+				 * anything allocated for the local
+				 * alloc, so shutting it down won't
+				 * wind up free'ing anything... */
+				ocfs_shutdown_local_alloc(osb, NULL, true);
+				goto bail;
 			}
+			LOG_ERROR_STATUS(status);
 			goto bail;
 		}
+		alloc = (ocfs_local_alloc *) 
+			OCFS_BH_GET_DATA(osb->local_alloc_bh);
 	}
- 
-	// Failed to find anything, Allocate enough bits from the cluster bitmap. 
-	ByteCount = (((__u64)(512 * 8))*csize) + file_size;
-	status = ocfs_acquire_lock(osb, OCFS_BITMAP_LOCK_OFFSET, OCFS_DLM_ENABLE_CACHE_LOCK, 0, &pLockResource, NULL); 
-	if (status < 0)
+
+	/* Alright, try to satisfy the request. */
+	startoff = ocfs_local_find_clear_bits(osb, alloc, bitswanted);
+	if (startoff == -1) {
+		/* we couldn't get enough bits from the local
+		 * alloc. Lets sync what we've got to the main bitmap,
+		 * clear the local out and try again. */
+		LOG_TRACE_STR("Could not find enough contiguous bits in local "
+			      "alloc bitmap, trying to move my window.");
+		OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+		alloc = NULL;
+
+		/* lock bitmap here */
+		ocfs_down_sem (&(osb->vol_alloc_lock), true);
+
+		/* Get the allocation lock here */
+		status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
+					    OCFS_DLM_EXCLUSIVE_LOCK, 0, 
+					    &bm_lock_res, &main_bm_bh, NULL);
+		if (status < 0) {
+			ocfs_up_sem (&(osb->vol_alloc_lock));
+			if (status != -EINTR)
+				LOG_ERROR_STATUS (status);
+			goto bail;
+		}
+
+		status = ocfs_sync_local_to_main(osb, &(osb->alloc_free_head),
+						 NULL, main_bm_bh);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+
+		alloc = (ocfs_local_alloc *) 
+			OCFS_BH_GET_DATA(osb->local_alloc_bh);
+
+		ocfs_clear_local_alloc(alloc);
+
+		OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+		alloc = NULL;
+
+		/* Ok, if we move our window, we have to make sure
+		 * that this transaction is a sync one, as we don't
+		 * want to crash after having free'd the main bitmap
+		 * bits and on replay have an old copy of the local
+		 * alloc put back! */
+		ocfs_handle_set_sync(handle, true);
+
+		/* skip our own abort handling. */
+		status = journal_dirty_metadata(handle->k_handle, 
+						osb->local_alloc_bh);
+		dontdirty = true;
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+		alloc = (ocfs_local_alloc *) 
+			OCFS_BH_GET_DATA(osb->local_alloc_bh);
+		goto tryagain;
+	}
+
+	LOG_TRACE_ARGS("Found %u bits, starting at local alloc offset %d\n",
+		       bitswanted, startoff);
+
+	/* Ok, if we've got this far then the search suceeded and we
+	 * can mark the bitmap. */
+	tmpoff = startoff;
+	tmpwanted = bitswanted;
+	while(tmpwanted--) {
+		/* LOG_TRACE_ARGS("setting bit %d\n", tmpoff); */
+		set_bit(tmpoff++, alloc->bitmap);
+	}
+	alloc->num_used += bitswanted;
+
+	*bitoff = alloc->bitmap_start + startoff;
+	*bitcount = bitswanted;
+
+	OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+	alloc = NULL;
+
+	if (!dontdirty) {
+		status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+	}
+bail:
+	/* if we locked the main bitmap, cleanup after ourselves. */
+	if (main_bm_bh) {
+		ocfs_up_sem (&(osb->vol_alloc_lock));
+
+		tmpstat = ocfs_release_lock (osb, 
+					     OCFS_BITMAP_LOCK_OFFSET,
+					     OCFS_DLM_EXCLUSIVE_LOCK, 
+					     0, bm_lock_res, main_bm_bh, NULL);
+		if (tmpstat < 0)
+			LOG_ERROR_STATUS (tmpstat);
+		ocfs_put_lockres (bm_lock_res);
+		brelse(main_bm_bh);
+	}
+
+	if (alloc && osb->local_alloc_bh)
+		OCFS_BH_PUT_DATA(osb->local_alloc_bh);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_find_space_from_local */
+
+
+/*
+ * ocfs_find_space
+ *
+ * A drop-in replacement for
+ * ocfs_find_contiguous_space_from_bitmap. We will in fact, call
+ * ocfs_find_contiguous_space_from_bitmap if you don't give us a
+ * journal handle, or if the local bitmap isn't loaded, or if the
+ * allocation is simply to big to fit in the local one. otherwise,
+ * we'll try to use our local alloc instead.
+ *
+ */
+int ocfs_find_space(ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, ocfs_journal_handle *handle)
+{
+	int status = 0;
+	__u32 bitswanted;
+	__u32 csize = osb->vol_layout.cluster_size;
+	bool use_global = true;
+
+	LOG_ENTRY_ARGS("(file_size = (%u.%u), handle = 0x%x, sysfile = %s)\n", 
+		       HILO(file_size), handle, sysfile ? "true" : "false");
+
+	if (file_size == 0) {
+		LOG_ERROR_STR ("asking for an allocation of zero bytes...");
+		status = 0;
 		goto bail;
- 
-	bLockAcquired = true; 
-	bitMapSize =  (__u32)osb->vol_layout.num_clusters;
-	size	= (__u32) OCFS_SECTOR_ALIGN((bitMapSize)/8) ; 
- 
-	// In the start one sector is for Volume header and second sector is for Global sequence Number and Directoy Entry. 
-	bitMapBuffer = ocfs_malloc(((bitMapSize + 7) / 8) + 4096); 
-	if (bitMapBuffer == NULL) 
-	{ 
-		status = -ENOMEM;
-		goto bail;
-	} 
-			 
-	status = ocfs_read_force_disk( osb, bitMapBuffer, size, osb->vol_layout.bitmap_off);			 
+	}
+
+	/* need to calculate a couple of things for below... */
+	bitswanted = (file_size + (csize-1)) / csize;
+
+	/* Ok, now decide if we can use local alloc bitmap.
+	 * We *always* use global bitmap for clustersize > 128k,
+	 * file_size > 2mb, so force it under these conditions. */
+	if ( (handle && osb->have_local_alloc)
+	     && (osb->vol_layout.cluster_size <= OCFS_LOCAL_ALLOC_MAX_CSIZE)
+	     && (file_size <= OCFS_LOCAL_ALLOC_MAX_ALLOC) )
+		use_global = false;
+
+	if (!use_global) {
+		status = ocfs_find_space_from_local(osb, bitswanted, 
+						    cluster_off, cluster_count,
+						    handle);
+		/* If we've run out of space for our local alloc, lets
+		 * try the global one just in case... */
+		if (status == -ENOSPC)
+			use_global = true;
+		else if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+	}
+
+	if (use_global)
+		status = ocfs_find_contiguous_space_from_bitmap(osb, file_size,
+								cluster_off, 
+								cluster_count, 
+								sysfile, NULL);
 	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
+	LOG_TRACE_ARGS("Returning *cluster_off = %u.%u, *cluster_count"
+		       "= %u.%u\n", HILO(*cluster_off), HILO(*cluster_count));
+bail:
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_find_space */
+
+/*
+ * ocfs_create_new_local_alloc
+ *
+ * significantly different enough from init_system_file that it
+ * deserves it's own function 
+ */
+int ocfs_create_new_local_alloc(ocfs_super *osb, int node_num)
+{
+	int status = 0;
+	__u64 offset;
+	struct buffer_head *alloc_bh = NULL;
+	ocfs_local_alloc *alloc;
+
+	LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
+
+	offset = ((OCFS_VOL_BITMAP_FILE + node_num) * osb->sect_size) +
+		osb->vol_layout.root_int_off;
+
+	status = ocfs_read_bh(osb, offset, &alloc_bh, OCFS_BH_CACHED, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(alloc_bh);
+
+	memset(alloc, 0, sizeof(ocfs_local_alloc));
+	strcpy (alloc->signature, OCFS_LOCAL_ALLOC_SIGNATURE);
+	alloc->this_sector = offset;
+	alloc->node_num = node_num;
+
+	OCFS_BH_PUT_DATA(alloc_bh);
+
+	status = ocfs_write_bh(osb, alloc_bh, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+leave:
+	if (alloc_bh)
+		brelse(alloc_bh);
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_create_new_local_alloc */
+
+/* 
+ * ocfs_load_local_alloc 
+ */
+int ocfs_load_local_alloc(ocfs_super *osb)
+{
+	int status = 0;
+	ocfs_local_alloc *alloc = NULL;
+	struct buffer_head *alloc_bh = NULL;
+	__u64 offset;
+	__u32 num_used;
+
+	LOG_ENTRY();
+
+	/* read the alloc off disk */
+	offset = ((OCFS_VOL_BITMAP_FILE + osb->node_num) * osb->sect_size) + 
+		osb->vol_layout.root_int_off;
+	status = ocfs_read_bh(osb, offset, &alloc_bh, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
 		goto bail;
- 
-	ocfs_initialize_bitmap( &VolBitMap, bitMapBuffer, bitMapSize); 
- 
-	// First clear the bits in the main bitmap which were not used in the local one 
-	if (fe->AllocationSize != 0) { 
-		__u32				offInMain = 0, freeOffset = 0; 
-		ocfs_alloc_bm			localBitmap; 
-		__u32				localBitMapSize; 
- 
-		offInMain = (__u32)fe->extents[0].file_off; 
-		localBitMapSize = (__u32)(fe->extents[0].num_bytes / csize);
- 
-		ocfs_initialize_bitmap(&localBitmap, (__u32 *)(osb->vol_bitmap_buf + 512), localBitMapSize);
- 
-		for(i = 0 ; i < (512* 8); i++) {
-			freeOffset = ocfs_find_clear_bits (&localBitmap, 1, 0); 
-			if(freeOffset == -1) 
-				break; 
-			ocfs_set_bits (&localBitmap, freeOffset, 1);		 
-			freeOffset  += offInMain ; 
-			ocfs_clear_bits(&VolBitMap, freeOffset, 1); 
-		} 
-	} 
-		 
-	// Round off the Byte Count to next ClusterSize(Bytes per cluster) 
-	ByteCount += (ByteCount % csize ? csize - (ByteCount%csize) : 0); 
-	 
-	if (ByteCount == 0) { 
-		status = -ENOSPC; 
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(alloc_bh);
+
+	/* do a little verification. */
+	num_used = ocfs_alloc_count_bits(alloc);
+
+	if (num_used != alloc->num_used) {
+		LOG_TRACE_ARGS("num_used = %u, alloc->num_used = %u!\n", 
+			       num_used, alloc->num_used);
+		OCFS_BH_PUT_DATA(alloc_bh);
+		status = -EFAIL;
 		goto bail;
-	} 
-	 
-	ClusterCount = (__u32)(ByteCount/ csize); 
-	if (ClusterCount > osb->vol_layout.num_clusters) { 
-		status = -ENOSPC; 
-		goto bail;
-	} 
- 
-	ByteOffset = ocfs_find_clear_bits (&VolBitMap, ClusterCount, 0); 
-	if (ByteOffset == -1) { 
-		status = -ENOSPC;
-		goto bail;
-	} 
- 
-	ocfs_set_bits (&VolBitMap, ByteOffset, ClusterCount);		 
-	 
-	status = ocfs_write_disk(osb, bitMapBuffer, size, osb->vol_layout.bitmap_off); 
+	}
+
+	osb->local_alloc_bh = alloc_bh;
+	osb->have_local_alloc = true;
+
+	OCFS_BH_PUT_DATA(alloc_bh);
+bail:
 	if (status < 0)
-		goto bail;
- 
-	BitmapOffset = ByteOffset ; 
-	numClusterAlloc = ClusterCount; 
-	status = 0;
+		if (alloc_bh)
+			brelse(alloc_bh);
 
-	actualDiskOffset = (BitmapOffset * csize) + osb->vol_layout.data_start_off; 
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_load_local_alloc */
 
-	// Fill in the File Entry and Zero off the new local bitmap 
-	fe->alloc_size = fe->extents[0].num_bytes = (((__u64)(512 * 8)) * csize); 
-	fe->extents[0].disk_off = actualDiskOffset; 
-	fe->extents[0].file_off = BitmapOffset; 
+/* 
+ * ocfs_shutdown_local_alloc
+ *
+ * return any unused bits to the bitmap and write out a clean
+ * local_alloc. 
+ *
+ * local_alloc_bh is optional. If not passed, we will simply use the
+ * one off osb. If you do pass it however, be warned that it *will* be
+ * returned brelse'd and NULL'd out.*/
+void ocfs_shutdown_local_alloc(ocfs_super *osb, 
+			       struct buffer_head **local_alloc_bh, bool sync)
+{
+	int status;
+	ocfs_local_alloc *alloc = NULL;
+	ocfs_bitmap_free_head *f = NULL;
+	struct buffer_head *bh = NULL;
 
-	memset((char *)osb->vol_bitmap_buf + 512, 0, 512);
+	LOG_ENTRY_ARGS("(local_alloc_bh = 0x%x, sync = %s\n)", local_alloc_bh,
+		       sync ? "true" : false);
 
-	diskOffset = ((OCFS_VOL_BITMAP_FILE + (2 * osb->node_num) ) * 512) +
-			osb->vol_layout.root_int_off;
- 
-	status = ocfs_write_force_disk(osb, fe, (2 * 512), diskOffset);			 
+	if (!osb->have_local_alloc)
+		return;
+
+	if (local_alloc_bh)
+		bh = *local_alloc_bh;
+	else
+		bh = osb->local_alloc_bh;
+
+	if (osb->alloc_free_head)
+		LOG_TRACE_STR("Shutting down with a pending bitmap_free_head!");
+	status = ocfs_sync_local_to_main(osb, &f, NULL, NULL);
 	if (status < 0)
+		LOG_ERROR_STATUS(status);
+	else if (f)
+		ocfs_process_bitmap_free_head(osb, f);
+
+	if (f) {
+		free_bitmap_free_head(f);
+		f = NULL;
+	}
+
+	alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(bh);
+	ocfs_clear_local_alloc(alloc);
+	OCFS_BH_PUT_DATA(bh);
+
+	if (sync) {
+		status = ocfs_write_bh(osb, bh, OCFS_BH_IGNORE_JBD, NULL);
+		if (status < 0)
+			LOG_ERROR_STATUS(status);
+	}
+
+	brelse(bh);
+	/* this is special only if we're using the one off osb. */
+	if (!local_alloc_bh) {
+		osb->local_alloc_bh = NULL;
+		osb->have_local_alloc = false;
+	} else
+		*local_alloc_bh = NULL;
+
+	LOG_EXIT();
+	return;
+} /* ocfs_shutdown_local_alloc */
+
+/*
+ * ocfs_recover_local_alloc
+ */
+int ocfs_recover_local_alloc(ocfs_super *osb, int node_num)
+{
+	int status = 0;
+	struct buffer_head *alloc_bh = NULL;
+	__u64 offset;
+
+	LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
+
+	offset = ((OCFS_VOL_BITMAP_FILE + node_num) * osb->sect_size) + 
+		osb->vol_layout.root_int_off;
+	status = ocfs_read_bh(osb, offset, &alloc_bh, 0, NULL);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
 		goto bail;
- 
-	*PClusterOffset = BitmapOffset + (512 * 8); 
-	*PNumClusterAlloc = numClusterAlloc - (512 * 8); 
- 
-	status = 0; 
+	}
+
+	ocfs_shutdown_local_alloc(osb, &alloc_bh, true);
+
 bail:
-	if( bLockAcquired ) {
-		ntStatus = ocfs_release_lock(osb, OCFS_BITMAP_LOCK_OFFSET, OCFS_DLM_EXCLUSIVE_LOCK, 0, pLockResource); 
-		if (ntStatus < 0 && status >= 0)
-			status = ntStatus; 
-	} 
- 
-	ocfs_safefree(bitMapBuffer) 
+	if (alloc_bh)
+		brelse(alloc_bh);
 
-	return status; 
-}
-#endif
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_recover_local_alloc */
+

Modified: trunk/bitmap.c
===================================================================
--- trunk/bitmap.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/bitmap.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -132,120 +132,100 @@
  */
 int ocfs_find_clear_bits (ocfs_super *osb, ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly)
 {
-	__u32 count, size, first_zero, globaloff, localstart, localoff,validbh;
+	__u32 globalsize, globaloff, localstart, lastbh, size, bitoff, count;
 	void *buffer;
 	int c;
 	struct buffer_head *currbh = NULL;
 
-	LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %u, %u)\n", osb, bitmap, numBits, offset, sysonly);
+	LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %u, %u)\n", osb, bitmap, numBits,
+			offset, sysonly);
 
-	size = bitmap->validbits - sysonly;
-	validbh = OCFS_ALIGN(bitmap->validbits, OCFS_BITS_IN_CHUNK) / 
-		  OCFS_BITS_IN_CHUNK;
-	count = 0; /* number of zero bits we've found contigously */
-	first_zero = globaloff = offset;
-	localoff = OCFS_GLOBAL_OFF_TO_LOCAL(globaloff);
-	c = OCFS_GLOBAL_OFF_TO_CHUNK(globaloff);
+	globalsize = bitmap->validbits - sysonly;
+	bitoff = count = 0;
+	lastbh = (OCFS_ALIGN(globalsize, OCFS_BITS_IN_CHUNK) / 
+		  OCFS_BITS_IN_CHUNK) - 1;
+
+	globaloff = offset;
+	localstart = OCFS_GLOBAL_OFF_TO_LOCAL(globaloff);
+
+	if (lastbh == 0)
+		size = globalsize;
+	else
+		size = OCFS_BITS_IN_CHUNK;
+
+	c = OCFS_GLOBAL_OFF_TO_CHUNK(localstart);
 	currbh = bitmap->chunk[c];
+
+	/*LOG_TRACE_ARGS("globalsize=%u, bitmap->validbits=%u, sysonly=%u\n", 
+	  globalsize, bitmap->validbits, sysonly);*/
+	/*LOG_TRACE_ARGS("before loop: c=%u, lastbh=%u, size=%u, "
+	  "localstart=%u\n", c, lastbh, size, localstart);*/
 	buffer = OCFS_BH_GET_DATA(currbh);
-	
-	/* while (it's still possible that there could be enough bits
-	 * left) AND we don't have enough zeros yet 
-	 * Do we ever hit this conditional or should this just be a while(1)?
-	 */
-	while ((size - globaloff + count >= numBits) && (count < numBits))
-	{
+
+	while ((bitoff = find_next_zero_bit(buffer, OCFS_BITS_IN_CHUNK, 
+					    localstart)) != -1) {
+		/*LOG_TRACE_ARGS("c=%u, globaloff=%u, bitoff=%u, "
+			       "localstart=%u\n", c, globaloff, bitoff, 
+			       localstart);*/
 		/* find_next_zero_bit returns:
+		   >= size passed in: if no zero bits in here.
 		   some number < size: at the next zero bit
-		   localoffset: if the current one is a zero
-		   size-1: if the very last bit is a zero
-		   size: if no zero bits in here.
+		   localstart: if the current one is a zero
 		*/
-		/* regarding: 'OCFS_BITS_IN_CHUNK - localoff'
-		 * it's OK for us to search beyond the outer edge of
-		 * valid bits because the bitmap owns whole sectors in
-		 * it's smallest chunks and even if we search farther
-		 * into that last sector than we need to, we'll catch
-		 * that later and just return no space.*/
-		localstart = find_next_zero_bit (buffer, 
-						 OCFS_BITS_IN_CHUNK - localoff,
-						 localoff);
-		if (localstart == localoff) {
-			/* cool, we have another zero! */
-			localoff++;
-			globaloff++;
-			count++;
-			/* Do we have enough? yay! */
-			if (count == numBits)
+		if (bitoff >= size) {
+			/* we've hit the end of our bh. */
+			OCFS_BH_PUT_DATA(currbh);
+			/*LOG_TRACE_ARGS("bitoff >= size (%u)\n", bitoff,c);*/
+
+			/* if it's the last bh, then quit the loop */
+			if (c == lastbh) {
+				count = 0;
+				LOG_TRACE_STR("Didn't find enough!");
 				break;
-			/* Can we just continue in this buffer? */
-			if (localoff < OCFS_BITS_IN_CHUNK)
-				continue;
-			/* otherwise fall through so we can switch bhs */
-		} else if (localstart >= (OCFS_BITS_IN_CHUNK - localoff)) {
-			/* we hit the end of our bh without any zeros! */
-			/* ok, we should just switch to the next
-			 * bh. fix globaloff and fall through. if we
-			 * go over, the conditional in fallthrough
-			 * will catch it. */
-			globaloff = OCFS_CHUNK_TO_GLOBAL_OFF(c+1, localoff);
-			first_zero = globaloff;
-			count = 0;
-		} else if (localstart != localoff) {
-			/* oops, hit some '1' bits :( lets reset our counters*/
-			localoff = localstart;
-			count = 0;
-			globaloff = OCFS_CHUNK_TO_GLOBAL_OFF(c, localoff);
-			first_zero = globaloff;
-			//localoff++;
-			//count = 1;
+			}
+			/* otherwise, reset localstart and switch bhs
+			 * and continue */
+			localstart = bitoff = 0;
+			c++;
+			currbh = bitmap->chunk[c];
+			buffer = OCFS_BH_GET_DATA(currbh);
+			if (c == lastbh)
+				size = globalsize-(OCFS_BITS_IN_CHUNK*lastbh);
 			continue;
 		}
 
-		/* If we have fallen through and this is our last BH,
-		 * then we haven't found enough bits. */
-		if (c >= (validbh - 1)) {
-			first_zero = -1;
-			break;
+		if (bitoff == localstart) {
+			/*LOG_TRACE_ARGS("bitoff == localstart (%u)\n", 
+			  bitoff);*/
+			/* cool, we have another zero! */
+			count++;
+			localstart++;
+			globaloff++;
+		} else {
+			/*LOG_TRACE_ARGS("bitoff (%u) != localstart (%u)\n", 
+			  bitoff, localstart);*/
+			/* we had to skip over some ones */
+			count = 1;
+			globaloff = OCFS_CHUNK_TO_GLOBAL_OFF(c, bitoff) + 1;
+			localstart = bitoff + 1;
 		}
 
-		/* if we fall here, we know we need to switch bhs */
-		OCFS_BH_PUT_DATA(currbh);
-
-		/*do we need globaloff++ ? */
-		c++;
-		localoff = 0;
-		currbh = bitmap->chunk[c];
-		buffer = OCFS_BH_GET_DATA(currbh);
+		if (count == numBits) {
+			/* we've found everything we wanted. */
+			LOG_TRACE_ARGS("Found it all! (count=%u)\n", count);
+			OCFS_BH_PUT_DATA(currbh);
+			buffer = NULL;
+			break;
+		}
 	}
 
-	/* unmap the buffer */
-	OCFS_BH_PUT_DATA(currbh);
+	if (count == numBits)
+		bitoff = globaloff - count;
+	else
+		bitoff = -1;
 
-	/* did we not get enough bits from the loop? but not realize
-	 * it? we shoulnd't his this at all */
-	if ((count < numBits) && (first_zero != -1)) {
-		LOG_ERROR_ARGS("count < numBits but first_zero is not -1!\n");
-		first_zero = -1;
-	}
-
-	/* check to see if we were able to get before the whole
-	 * sysonly shebang. */
-	if ((first_zero != -1) && (globaloff + numBits) > size) {
-		LOG_TRACE_STR("not enough space with sysonly saved.");
-		first_zero = -1;
-	}
-
-//bail:
-	/* Another error we should never hit. */
-	if (first_zero != -1 && first_zero > bitmap->validbits) {
-		LOG_ERROR_ARGS("um, first_zero > bitmap->validbits (%d > %d)",
-			       first_zero, bitmap->validbits);
-		first_zero = -1;
-	}
-
-	LOG_EXIT_LONG (first_zero);
-	return first_zero;
+	LOG_EXIT_LONG (bitoff);
+	return bitoff;
 }				/* ocfs_find_clear_bits */
 
 /*

Modified: trunk/dlm.c
===================================================================
--- trunk/dlm.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/dlm.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -33,7 +33,6 @@
 /* Tracing */
 #define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_DLM
 
-static void ocfs_stupid_loop(ocfs_super *osb, bool do_other_stupid_things);
 static int ocfs_insert_cache_link (ocfs_super * osb, ocfs_lock_res * lockres);
 static int ocfs_update_lock_state (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, bool *disk_vote, struct inode *inode);
 static int ocfs_send_dlm_request_msg (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, __u64 vote_map);
@@ -130,12 +129,6 @@
 	if (flags & FLAG_CHANGE_MASTER)
 		lockres->master_node_num = osb->node_num;
 finito:
-#if STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true);
-	osb->in_voting = NOT_VOTING;
-	ocfs_up_sem(&(osb->voting_lock));
-#endif
-
 	if (*disk_vote) {
 		tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
 					     lockres->lock_type, votemap);
@@ -148,50 +141,6 @@
 	return status;
 }				/* ocfs_update_lock_state */
 
-static void ocfs_stupid_loop(ocfs_super *osb, bool do_other_stupid_things)
-{
-	int i = 0; 
-
-	LOG_ENTRY_ARGS("do_other_stupid_things = %s\n", do_other_stupid_things ? "true" : "false");
-#ifdef STUPID_STUFF
-	if((osb->trans_in_progress) && (osb->needs_flush)) 
-	{ 
-		osb->trans_in_progress = false; 
-		atomic_set (&osb->flush_event_woken, 1);
-		wake_up (&osb->flush_event);
-		while ((osb->needs_flush) && (i < 30))  
-		{ 
-			if (do_other_stupid_things) {
-				ocfs_down_sem(&(osb->voting_lock), true); 
-				 
-				if (osb->in_voting == SKIPPED_HEARTBEAT)
-				{ 
-					osb->in_voting = DOING_HEARTBEAT;
-					ocfs_up_sem(&(osb->voting_lock)); 
-	
-					down (&(osb->publish_lock));
-					ocfs_nm_heart_beat(osb, HEARTBEAT_METHOD_DISK, false);
-					up (&(osb->publish_lock));
-				} 
-				else 
-				{ 
-					ocfs_up_sem(&(osb->voting_lock)); 
-				} 
-			}
-			ocfs_sleep(1000);
-			i++; 
-		}
-		 
-		osb->trans_in_progress = true; 
-		if (osb->needs_flush)
-			LOG_ERROR_STR("CHANGE TO TRACE >>> Trans and needs flush both are set");
-	}
-#endif
-	LOG_EXIT();
-	return;
-}
-
-
 /*
  * ocfs_disk_request_vote()
  *
@@ -261,8 +210,6 @@
 				wait += OCFS_NM_HEARTBEAT_TIME;
 				LOG_TRACE_ARGS ("wait: %d\n", wait);
 				ocfs_sleep (wait);
-
-				ocfs_stupid_loop(osb, true);
 			}
 			status = -EAGAIN;
 			goto finally;
@@ -695,19 +642,6 @@
 			status = -EAGAIN;
 			goto bail;
 		}
-#if STUPID_STUFF
-		ocfs_down_sem(&(osb->voting_lock), true);
-		if (osb->in_voting == SKIPPED_HEARTBEAT) {
-			osb->in_voting = DOING_HEARTBEAT;
-			ocfs_up_sem(&(osb->voting_lock));
-			
-			down (&(osb->publish_lock));
-			ocfs_nm_heart_beat(osb, HEARTBEAT_METHOD_DISK, false);
-			up (&(osb->publish_lock));
-		} else {
-			ocfs_up_sem(&(osb->voting_lock));
-		}
-#endif
 
 		gotvotemap |= (1 << osb->node_num);
 
@@ -732,8 +666,6 @@
 			goto bail;
 		}
 	
-		ocfs_stupid_loop(osb, false);	
-		
 		timewaited += WAIT_FOR_VOTE_INCREMENT;
 	}
 
@@ -771,27 +703,9 @@
 
 	LOG_ENTRY ();
 
-#ifdef STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true); 
-	osb->in_voting = DOING_HEARTBEAT; 
-	ocfs_up_sem(&(osb->voting_lock)); 	
-#endif
 	status = ocfs_disk_request_vote (osb, lock_id, lock_type, flags,
 					 vote_map, lock_seq_num);
 
-#ifdef STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true);
-	if (osb->in_voting == SKIPPED_HEARTBEAT) {
-		osb->in_voting = DOING_HEARTBEAT;
-		ocfs_up_sem(&(osb->voting_lock));
-
-		down (&(osb->publish_lock));
-		ocfs_nm_heart_beat(osb, HEARTBEAT_METHOD_DISK, false);
-		up (&(osb->publish_lock));
-	} else { 
-		ocfs_up_sem(&(osb->voting_lock));
-	}
-#endif
 	LOG_EXIT_STATUS (status);
 	return status;
 }				/* ocfs_request_vote */
@@ -971,11 +885,6 @@
 	}
 
 bail:
-#ifdef STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true);
-	osb->in_voting = NOT_VOTING;
-	ocfs_up_sem(&(osb->voting_lock));
-#endif
 
 	if (*disk_vote) {
 		tmpstat = ocfs_reset_voting (osb, lock_id, lock_type, vote_map);
@@ -1390,6 +1299,7 @@
 	bool become_master = false, keep_exclusive = false, wait_for_release = false;
 	bool local_lock = false, fast_path = false, wait_on_recovery = false;
 	bool get_x = false, master_request = false, truncate_extend = false;
+	bool have_cache_already = false;
 
 
 	LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u, %u, 0x%08x, 0x%08x)\n", osb,
@@ -1506,7 +1416,9 @@
 	if (local_lock && !(get_x || truncate_extend))
 		fast_path = true;
 	if (local_lock && truncate_extend) {
+#ifdef VERBOSE_LOCKING_TRACE
 		printk("local_lock but an extend or truncate request!  will do a master_request.\n");
+#endif
 		become_master = true;
 	}
 	if (!(fast_path || become_master || get_x || wait_for_release))
@@ -1516,12 +1428,14 @@
         /*   fast_path, become_master, get_x,    */
 	/*   wait_for_release, master_request    */
 
+#ifdef VERBOSE_LOCKING_TRACE
 	printk("acquire_lock: lock path is %s\n", 
 	       fast_path ? "fast_path" : 
 	        (become_master ? "become_master" : 
 		 (get_x ? "get_x" : 
 		  (wait_for_release ? "wait_for_release" : 
 		   (master_request ? "master_request" : "invalid")))));
+#endif
 
 	/* master node is this node */
 	if (fast_path) {
@@ -1561,8 +1475,6 @@
 					goto finally;
 				}
 
-				ocfs_stupid_loop(osb, false);
-				
 				updated = false;
 				goto again;
 			}
@@ -1635,13 +1547,17 @@
 got_lock:
 
 	disklock = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
+	have_cache_already = (DISK_LOCK_CURRENT_MASTER (disklock) == osb->node_num &&
+			      DISK_LOCK_FILE_LOCK (disklock) == OCFS_DLM_ENABLE_CACHE_LOCK);
 	DISK_LOCK_CURRENT_MASTER (disklock) = osb->node_num;
 
 	if (!keep_exclusive) {
 		DISK_LOCK_FILE_LOCK (disklock) = lock_type;
 		OCFS_BH_PUT_DATA(*b);
 
-		if (lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
+		if (have_cache_already)
+			LOG_TRACE_STR("have cachelock already... skip the write");
+		else if (lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
 			status = ocfs_write_bh (osb, *b, 0, inode);
 			if (status < 0) {
 				LOG_ERROR_STATUS (status);
@@ -1841,12 +1757,6 @@
 			LOG_ERROR_STATUS (tmpstat);
 	}
 
-#ifdef STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true);
-	osb->in_voting = NOT_VOTING;
-	ocfs_up_sem(&(osb->voting_lock));
-#endif
-
 	fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
 
 	if (flags & FLAG_FILE_RELEASE_MASTER)
@@ -2083,9 +1993,6 @@
 #endif
 	status = -EAGAIN;
 	while (status == -EAGAIN) {
-		if (retry)
-			ocfs_stupid_loop(osb, false);
-
 		if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
 				    OCFS_MAXIMUM_NODES)) {
 			LOG_TRACE_ARGS ("Master (%u) is dead, lockid %u.%u\n",
@@ -2173,11 +2080,6 @@
 	}
 
 	lockres->lock_type = (__u8) OCFS_DLM_NO_LOCK;
-#ifdef STUPID_STUFF
-	ocfs_down_sem(&(osb->voting_lock), true);
-	osb->in_voting = NOT_VOTING;
-	ocfs_up_sem(&(osb->voting_lock));
-#endif
 
 	LOG_TRACE_STR ("okie dokie... ocfs_break_cache_lock done\n");
 

Modified: trunk/file.c
===================================================================
--- trunk/file.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/file.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -1,9 +1,25 @@
 #include  <ocfs.h>
 #define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_EXTENT
 
-static int ocfs_change_file_size (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) 				     \
+do {									     \
+	if (attr->ia_valid & ATTR_SIZE)					     \
+		fe->file_size = attr->ia_size;				     \
+	if (attr->ia_valid & ATTR_UID)					     \
+		fe->uid = attr->ia_uid;					     \
+	if (attr->ia_valid & ATTR_GID)					     \
+		fe->gid = attr->ia_gid;					     \
+	if (attr->ia_valid & ATTR_MODE)					     \
+		fe->prot_bits = attr->ia_mode & 0007777;		     \
+	if (attr->ia_valid & ATTR_CTIME)				     \
+		fe->create_time = attr->ia_ctime;			     \
+	if (attr->ia_valid & ATTR_MTIME)				     \
+		fe->modify_time = attr->ia_mtime;			     \
+} while (0)
+
 /*
  * ocfs_file_open()
  *
@@ -406,10 +422,10 @@
 	return (err < 0) ? -EIO : 0;
 }				/* ocfs_sync_file */
 
-/* ocfs_change_file_size()
+/* ocfs_change_file_attrib()
  *
  */
-static int ocfs_change_file_size (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;
@@ -423,12 +439,11 @@
 	__u32 lockFlags = 0;
 	bool bCacheLock = false;
 	struct buffer_head *bh = NULL;
+	ocfs_journal_handle *handle = NULL;
 	int flags = 0;
 
 	LOG_ENTRY ();
 
-	ocfs_take_trans_lock (osb);
-
 	changeSeqNum = osb->curr_trans_id;
 
 	status = ocfs_read_bh (osb, *file_off, &bh, OCFS_BH_CACHED, inode);
@@ -436,6 +451,7 @@
 		LOG_ERROR_STATUS (status);
 		goto leave;
 	}
+
 	fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
 
 	if (!IS_VALID_FILE_ENTRY(fileEntry)) {
@@ -456,6 +472,18 @@
 	lockFlags = FLAG_FILE_UPDATE;
 	OCFS_BH_PUT_DATA(bh);
 
+	/* Start a transaction - need a minimal amount of block credits (1) */
+	handle = ocfs_start_trans(osb, 1);
+	if (handle == NULL) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+	/* we want this transaction to return quickly. */
+	ocfs_handle_set_checkpoint(handle, false);
+#ifdef ALLOW_NO_HANDLE_SYNCING
+	ocfs_handle_set_sync(handle, false);
+#endif
+
 	status = ocfs_acquire_lock (osb, lockId, 
 			bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK : OCFS_DLM_EXCLUSIVE_LOCK, 
 			lockFlags, &pLockResource, &bh, inode);
@@ -465,6 +493,13 @@
 		goto leave;
 	}
 	bAcquiredLock = true;
+
+	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
 	fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
 
 	if (bCacheLock) {
@@ -475,20 +510,8 @@
 	fileEntry->modify_time = CURRENT_TIME;
 
 	DISK_LOCK_SEQNUM (fileEntry) = changeSeqNum;
-	if (attr->ia_valid & ATTR_SIZE)
-		fileEntry->file_size = attr->ia_size;
-	if (attr->ia_valid & ATTR_UID)
-		fileEntry->uid = attr->ia_uid;
-	if (attr->ia_valid & ATTR_GID)
-		fileEntry->gid = attr->ia_gid;
-	if (attr->ia_valid & ATTR_MODE)
-		fileEntry->prot_bits = attr->ia_mode & 0007777;
-	if (attr->ia_valid & ATTR_CTIME)
-		fileEntry->create_time = attr->ia_ctime;
-	if (attr->ia_valid & ATTR_MTIME)
-		fileEntry->modify_time = attr->ia_mtime;
+	OCFS_FE_SET_ATTRIBUTES(fileEntry, attr);
 
-
 	/* Set the valid bit here */
 	SET_VALID_BIT (fileEntry->sync_flags);
 	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
@@ -498,35 +521,47 @@
 
 	flags = OCFS_FE_CACHE_FLAGS(osb, fileEntry);
 	OCFS_BH_PUT_DATA(bh);
-	status = ocfs_write_bh(osb, bh, flags, inode);
+
+	status = ocfs_journal_dirty(handle, bh);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto leave;
 	}
 
-      leave:
+leave:
+	lockFlags |= FLAG_FILE_UPDATE_OIN;
+
+	if (handle) {
+		if (status < 0) {
+			ocfs_abort_trans(handle);
+		} else {
+			ocfs_journal_add_lock(handle, lockId, 
+					      OCFS_DLM_EXCLUSIVE_LOCK, 
+					      lockFlags, pLockResource, bh);
+			bAcquiredLock = false;
+			status = ocfs_commit_trans(handle);
+			if (status < 0)
+				LOG_ERROR_STATUS(status);
+		}
+	}
 	if (bAcquiredLock) {
-		lockFlags |= FLAG_FILE_UPDATE_OIN;
-
 		tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
 					     lockFlags, pLockResource, bh, inode);
 		if (tmpstat < 0)
 			LOG_ERROR_STATUS (tmpstat);
+		ocfs_put_lockres (pLockResource);
 	}
 	
 	if (bh != NULL)
 		brelse(bh);
 
-	ocfs_put_lockres (pLockResource);
-
-	ocfs_release_trans_lock (osb);
 	if (status < 0)
 		if (status != -ENOSPC && status != -EINTR)
 			LOG_ERROR_STATUS (status);
 
 	LOG_EXIT_STATUS (status);
 	return status;
-}				/* ocfs_change_file_size */
+}				/* ocfs_change_file_attrib */
 
 /*
  * ocfs_file_write()
@@ -640,7 +675,7 @@
 		     LO (newsize));
 
 
-		status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode);
+		status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode, NULL);
 		if (status < 0) {
 			if (status != -EINTR && status != -ENOSPC) {
 				LOG_ERROR_STATUS (status);
@@ -659,40 +694,25 @@
 		ret = generic_file_write (filp, buf, count, ppos);
 
 	if (writingAtEOF && ret >= 0) {
-		struct iattr attr;
-
 		LOG_TRACE_STR
 		    ("Generic_file_write ok, asking for OIN update now");
 		inode->i_size = newsize;
 		inode->i_blocks = (newsize + sb->s_blocksize) >> sb->s_blocksize_bits;
-		memset (&attr, 0, sizeof (struct iattr));
-		attr.ia_valid |= ATTR_SIZE;
-		attr.ia_size = newsize;
-		status = ocfs_change_file_size (osb, oin->parent_dirnode_off, 
-						oin, newsize, &oin->file_disk_off, &attr, inode);
-		if (status < 0) {
-			/* 
-			 * WE NEED TO MAKE SURE THIS ALWAYS WORKS OR
-			 * WE NEED TO DO MORE HERE!!!!
-			 */
-			if (status != -EINTR) {
-				LOG_ERROR_STATUS (status);
-				ret = -EIO;
-			} else
-				ret = status;
-		}
 	}
 
 bail:
 	if (saAcquired) {
 		OCFS_CLEAR_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_WRITE);
 	}
+
+#if 0
         if (inode && oin && !oin->cache_enabled && !(filp->f_flags & O_DIRECT)) {
                 fsync_inode_buffers(inode);
 #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
 		fsync_inode_data_buffers(inode);
 #endif
         }
+#endif
 
 	ocfs_put_lockres (lockres);
 	LOG_EXIT_LONG (ret);
@@ -928,7 +948,7 @@
 /* ocfs_extend_file()
  *
  */
-int ocfs_extend_file (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, ocfs_journal_handle *passed_handle, struct inode *inode)
+int ocfs_extend_file (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, ocfs_journal_handle *passed_handle, struct inode *inode, struct iattr *attr)
 {
 	int status = 0;
 	int tmpstat;
@@ -985,8 +1005,11 @@
 			goto leave;
 		}
 
-		handle->flags &= ~OCFS_HANDLE_CHECKPOINT;
-
+		/* we don't want to checkpoint extends. */
+		ocfs_handle_set_checkpoint(handle, false);
+#ifdef ALLOW_NO_HANDLE_SYNCING
+		ocfs_handle_set_sync(handle, false);
+#endif
 		/* Grab a lock on the entry found if we have more than
 		 * 1 extents and also make this node the master*/
 		fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
@@ -1052,10 +1075,8 @@
 
 		}
 
-		status = ocfs_find_contiguous_space_from_bitmap(osb, allocSize,
-							     &bitmapOffset,
-							     &numClustersAlloc,
-							     false);
+		status = ocfs_find_space(osb, allocSize, &bitmapOffset,
+					 &numClustersAlloc, false, handle);
 		if (status < 0) {
 			OCFS_BH_PUT_DATA(bh);
 			if (status != -ENOSPC && status != -EINTR)
@@ -1100,14 +1121,18 @@
 	fileEntry->file_size = file_size;
 	LOG_TRACE_ARGS("fileEntry->alloc_size = %u.%u\n", HILO(fileEntry->alloc_size));
 
+	if (attr)
+		OCFS_FE_SET_ATTRIBUTES(fileEntry, attr);
 	/* Set the Valid bit and reset the change bit here... TODO */
 	SET_VALID_BIT (fileEntry->sync_flags);
 	fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
 	fileEntry->modify_time = OCFS_CURRENT_TIME;
+
 	tempOffset = fileEntry->this_sector;
 	size = (__u32) OCFS_ALIGN (sizeof (ocfs_file_entry), osb->sect_size);
 
 	flags = OCFS_FE_CACHE_FLAGS(osb, fileEntry);
+
 	OCFS_BH_PUT_DATA(bh);
 
 	status = ocfs_journal_dirty(handle, bh);
@@ -1124,6 +1149,9 @@
 leave:
 	if (passed_handle == NULL) {
 		if (handle) {
+			ocfs_bitmap_free_head *f = osb->alloc_free_head;
+			osb->alloc_free_head = NULL;
+
 			if (status < 0) {
 				ocfs_abort_trans(handle);
 			} else {
@@ -1139,6 +1167,11 @@
 				if (status < 0)
 					LOG_ERROR_STATUS(status);
 			}
+
+			if (f) {
+				ocfs_process_bitmap_free_head(osb, f);
+				free_bitmap_free_head(f);
+			}
 		}
 	}
 
@@ -1178,6 +1211,7 @@
 	ocfs_super *osb = NULL;
 	__u64 parentOff, fileOff;
 	struct super_block *sb = inode->i_sb;
+	bool extended = false;
 
 	LOG_ENTRY_ARGS ("(0x%08x, '%*s')\n", dentry,
                         dentry->d_name.len, dentry->d_name.name);
@@ -1246,9 +1280,11 @@
                 if (inode->i_size > newsize)
 			status = ocfs_truncate_file(osb, fileOff, newsize, 
 						    oin, inode);
-		else
+		else {
 			status = ocfs_extend_file(osb, parentOff, oin, newsize,
-						  &fileOff, NULL, inode);
+						  &fileOff, NULL, inode, attr);
+			extended = true;
+		}
 		if (status < 0) {
 			if (status != -EINTR)
 				LOG_ERROR_STATUS (status);
@@ -1269,11 +1305,14 @@
 
 	/* 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);
+		ocfs_linux_get_dir_entry_offset(osb, &fileOff, parentOff, 
+						&(dentry->d_name), NULL, 
+						parentInode);
 
 	status = -EFAIL;
-	if (fileOff != -1) {
-		status = ocfs_change_file_size (osb, parentOff, NULL, newsize, &fileOff, attr, inode);
+	if ((fileOff != -1) && !extended) {
+		status = ocfs_change_file_attrib(osb, parentOff, NULL, newsize,
+					       &fileOff, attr, inode);
 		if (status < 0) {
 			if (status != -EINTR)
 				LOG_ERROR_STATUS (status);
@@ -1286,7 +1325,6 @@
 bail:
 	atomic_dec (&parentInode->i_count);
 bail2:
-//	ocfs_release_file_entry(fe);
 	LOG_EXIT_LONG (error);
 	return error;
 }				/* ocfs_setattr */
@@ -1331,7 +1369,7 @@
 	stat->blksize = (__u32) osb->vol_layout.cluster_size;
 
 	err = 0;
-      bail:
+bail:
 	LOG_EXIT_LONG (err);
 	return err;
 }				/* ocfs_getattr */
@@ -1365,7 +1403,7 @@
 			LOG_ERROR_STATUS (status);
 	}
 
-      bail:
+bail:
 	LOG_EXIT_LONG (0);
 	return 0;
 }				/* ocfs_getattr */

Modified: trunk/inc/journal.h
===================================================================
--- trunk/inc/journal.h	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/inc/journal.h	2003-12-16 23:55:26 UTC (rev 10)
@@ -46,6 +46,7 @@
 	enum {
 		OCFS_JOURNAL_FREE = 0,
 		OCFS_JOURNAL_LOADED,
+		OCFS_JOURNAL_IN_SHUTDOWN,
 		OCFS_JOURNAL_CREATE    /* only used during journal_create */
 	}                         state;      /* Journals current state   */
 
@@ -133,10 +134,23 @@
 
 /* should we checkpoint this handle on commit? */
 #define OCFS_HANDLE_CHECKPOINT			1
-/* should we NOT sync-commit this handle? Don't use this flag yet... */
-#define OCFS_HANDLE_NO_SYNC			2
+/* should we sync-commit this handle? */
+#define OCFS_HANDLE_SYNC			2
+#define ocfs_handle_set_checkpoint(handle, val) 			      \
+do { 									      \
+	if (val) 							      \
+		(handle)->flags |= OCFS_HANDLE_CHECKPOINT;		      \
+	else								      \
+		(handle)->flags &= ~OCFS_HANDLE_CHECKPOINT;		      \
+} while(0)
+#define ocfs_handle_set_sync(handle, val) 				      \
+do { 									      \
+	if (val) 							      \
+		(handle)->flags |= OCFS_HANDLE_SYNC;			      \
+	else								      \
+		(handle)->flags &= ~OCFS_HANDLE_SYNC;			      \
+} while(0)
 
-
 /* 
  *  Journal Configuration Management:
  *  These are normally called at mount and unmount time.
@@ -279,9 +293,10 @@
 			    OCFS_JOURNAL_FUZZ_CREDITS)
 
 /* single file metadata updates * 3 because we might have to extend
- * the file alloc and file alloc bitmap files. */
+ * the file alloc and file alloc bitmap files + possible update to
+ * local bitmap. */
 #define OCFS_FILE_EXTEND_CREDITS (OCFS_SINGLE_FILE_EXTEND_CREDITS * 3         \
-				  + OCFS_JOURNAL_FUZZ_CREDITS)
+				  + 1 + OCFS_JOURNAL_FUZZ_CREDITS)
 
 /* fe, anything along new 'edge' of tree + fuzz*/
 #define OCFS_FILE_TRUNCATE_CREDITS (1 + 4 + OCFS_JOURNAL_FUZZ_CREDITS)

Modified: trunk/inc/ocfs.h
===================================================================
--- trunk/inc/ocfs.h	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/inc/ocfs.h	2003-12-16 23:55:26 UTC (rev 10)
@@ -321,9 +321,8 @@
     OCFS_FILE_EXTENT_BM_SYSFILE,
     OCFS_RECOVER_LOG_SYSFILE,
     OCFS_CLEANUP_LOG_SYSFILE,
-#ifdef LOCAL_ALLOC
     OCFS_VOL_BM_SYSFILE,
-#endif
+    OCFS_VOL_BM,
     OCFS_NUM_SYSFILES
 };
 #define OCFS_FILE_VOL_META_DATA      (OCFS_VOL_MD_SYSFILE         * OCFS_MAXIMUM_NODES)
@@ -335,9 +334,9 @@
 #define LOG_FILE_BASE_ID             (OCFS_RECOVER_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)
 #define CLEANUP_FILE_BASE_ID         (OCFS_CLEANUP_LOG_SYSFILE    * OCFS_MAXIMUM_NODES)
 #define JOURNAL_FILE_BASE_ID         (CLEANUP_FILE_BASE_ID)
-#ifdef LOCAL_ALLOC
 #define OCFS_VOL_BITMAP_FILE         (OCFS_VOL_BM_SYSFILE         * OCFS_MAXIMUM_NODES)
-#endif
+/* ocfs_vol_bitmap is unused. */
+#define OCFS_VOL_BITMAP              (OCFS_VOL_BM                 * OCFS_MAXIMUM_NODES)
 
 
 
@@ -496,6 +495,7 @@
 #define  OCFS_FILE_ENTRY_SIGNATURE           "FIL"
 #define  OCFS_EXTENT_HEADER_SIGNATURE        "EXTHDR2"
 #define  OCFS_EXTENT_DATA_SIGNATURE          "EXTDAT1"
+#define  OCFS_LOCAL_ALLOC_SIGNATURE          "LCLBMP"
 
 #define  MAX_IP_ADDR_LEN	32
 
@@ -1166,6 +1166,26 @@
 #define OCFS_DEBUG_CONTEXT_JOURNAL     0x80000000      /*  journal.c */
 
 
+#ifdef OCFS_DBG_TIMING
+typedef union _my_timing_t
+{
+	__u64 q;
+	__u32 lohi[2];
+} my_timing_t;
+
+#define IO_FUNC_TIMING_DECL		my_timing_t begin, end;  \
+					rdtsc (begin.lohi[0], begin.lohi[1]);
+#define IO_FUNC_TIMING_PRINT(_fn,_ret)	rdtsc (end.lohi[0], end.lohi[1]); \
+					IF_LEVEL_NO_CONTEXT(OCFS_DEBUG_LEVEL_TIMING) \
+						printk("(%d) EXIT : %s() = %d  => [%u.%u]\n",\
+					       		ocfs_getpid(), _fn, \
+							_ret, HILO(end.q-begin.q));
+#else
+#define IO_FUNC_TIMING_DECL
+#define IO_FUNC_TIMING_PRINT(_fn,_ret)
+#endif
+
+
 #ifndef OCFS_DBG_TIMING
 #define DECL_U8_ARRAY(__t, __s)
 #define INIT_U8_ARRAY(__s)
@@ -1196,6 +1216,8 @@
 # define IF_LEVEL(level)	\
 	if ((debug_context & OCFS_DEBUG_CONTEXT) && (debug_level & level) && \
 	    ocfs_getpid()!=debug_exclude)
+# define IF_LEVEL_NO_CONTEXT(level)	\
+	if ((debug_level & level) &&  ocfs_getpid()!=debug_exclude)
 	
 #ifndef OCFS_DBG_TIMING
 # define ENTRY_TIMING_DECLS
@@ -1457,10 +1479,10 @@
 
 typedef struct _HASHBUCKET
 {
-	void *key;
 	__u32 keylen;
-	void *val;
 	__u32 vallen;
+	void *key;
+	void *val;
 	struct _HASHBUCKET *next;
 }
 HASHBUCKET;
@@ -1620,7 +1642,6 @@
 
 typedef struct _ocfs_alloc_bm
 {
-//	void *buf;
 	__u32 validbits; /* number of valid bits */
 	__u32 allocbits; /* number of allocated bits */
 	__u32 failed;
@@ -1823,6 +1844,8 @@
 }
 ocfs_vol_node_map;
 
+struct _ocfs_bitmap_free_head;
+
 /*
  * ocfs_super
  *
@@ -1893,7 +1916,6 @@
 	struct buffer_head **cfg_bhs;
 	__u32 cfg_len;
 	__u32 cfg_numblocks;
-	__u8 *log_prealloc;
 	struct semaphore publish_lock;  /* protects r/w to publish sector */
 	atomic_t node_req_vote;         /* set when node's vote req pending */
 	struct semaphore trans_lock;	/* serializes transactions */
@@ -1902,7 +1924,6 @@
 	ocfs_sem voting_lock;
 	struct list_head needs_flush_head;
 	ocfs_sem vol_lock_res;
-	__u32 num_nm_thread_iter;
 	wait_queue_head_t flush_event;
 	atomic_t flush_event_woken;
 	struct _ocfs_journal journal;
@@ -1910,6 +1931,10 @@
 	spinlock_t clean_buffer_lock;
 	struct list_head lock_recovery_lists[OCFS_MAXIMUM_NODES];
 	__u64 last_publ_seq_num[OCFS_MAXIMUM_NODES];
+	bool have_local_alloc;
+	/* These two are protected by the trans_lock. */
+	struct buffer_head *local_alloc_bh;
+	struct _ocfs_bitmap_free_head *alloc_free_head;
 };
 
 typedef struct _ocfs_comm_info
@@ -2024,6 +2049,20 @@
 OCFS_GCC_ATTR_PACKALGN
 ocfs_vote;				// END CLASS
 
+typedef struct _ocfs_local_alloc
+{
+	ocfs_disk_lock disk_lock;
+	__u8 signature[8];        /* "LCLBMP"                           */
+	__u32 alloc_size;         /* num bits taken from main bitmap    */
+	__u32 num_used;           /* num bits used (is this needed?)    */
+	__u32 bitmap_start;       /* starting bit offset in main bitmap */
+	__u32 node_num;           /* which node owns me                 */
+	__u64 this_sector;        /* disk offset of this structure      */
+	__u8 padding[176];  	  /* pad out to 256                     */
+  	__u8 bitmap[256];
+}
+ocfs_local_alloc;
+
 typedef struct _ocfs_file_entry		// CLASS
 {
 	ocfs_disk_lock disk_lock;       // DISKLOCK
@@ -2322,72 +2361,16 @@
 		ocfs_free_rec *log; 					      \
 		struct list_head *p, *n; 				      \
 									      \
-		if (f && (f->num_logs)) { 				      \
-			list_for_each_safe(p, n, &(f->free_logs)) {	      \
+		if ((f) && ((f)->num_logs)) { 				      \
+			list_for_each_safe(p, n, &((f)->free_logs)) {	      \
 				log = list_entry(p, ocfs_free_rec, log_list); \
 				list_del(&(log->log_list));		      \
 			}						      \
 		} 							      \
-		ocfs_safefree(f);					      \
+		ocfs_safefree((f));					      \
 	} while(0)
 
 
-/* Log Records */
-
-typedef struct _ocfs_delete_log
-{
-	__u64 node_num;
-	__u64 ent_del;
-	__u64 parent_dirnode_off;
-	__u32 flags;
-	__u8 pad[4];
-}
-ocfs_delete_log;
-
-typedef struct _ocfs_recovery_log
-{
-	__u64 node_num;
-}
-ocfs_recovery_log;
-
-typedef struct _ocfs_alloc_log
-{
-	__u64 length;
-	__u64 file_off;
-	__u32 type;
-	__u32 node_num;
-}
-ocfs_alloc_log;
-
-
-typedef struct _ocfs_cleanup_record
-{
-	__u64 log_id;
-	__u32 log_type;
-	__u8 pad[4];
-	union
-	{
-		ocfs_delete_log del;
-		ocfs_free_rec free;
-	}
-	rec;
-}
-ocfs_cleanup_record;
-
-typedef struct _ocfs_log_record
-{
-	__u64 log_id;
-	__u32 log_type;
-	__u8 pad[4];
-	union
-	{
-		ocfs_alloc_log alloc;
-		ocfs_delete_log del;
-		ocfs_recovery_log recovery;
-	}
-	rec;
-}
-ocfs_log_record;
 struct ocfs_ioc
 {
 	char name[255];		/* "OCFS" */

Modified: trunk/inc/ocfsio.h
===================================================================
--- trunk/inc/ocfsio.h	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/inc/ocfsio.h	2003-12-16 23:55:26 UTC (rev 10)
@@ -94,9 +94,18 @@
 	return 0;
 }
 
+
 static inline int ocfs_write_bh (ocfs_super * osb, struct buffer_head *bh, int flags, struct inode *inode)
 {
-	return ocfs_write_bhs (osb, &bh, 1, flags, inode);
+	int ret;
+	
+	IO_FUNC_TIMING_DECL
+
+	ret = ocfs_write_bhs (osb, &bh, 1, flags, inode);
+
+	IO_FUNC_TIMING_PRINT("ocfs_write_bh", ret)
+
+	return ret;
 }
 
 static inline int ocfs_write_bhs (ocfs_super * osb, struct buffer_head *bhs[], int nr, int flags, struct inode *inode)
@@ -106,7 +115,10 @@
 	struct super_block *sb;
 	ocfs_blockdev dev;
 	struct buffer_head *bh;
+	int jbd_managed_buffers = 0;
 
+	IO_FUNC_TIMING_DECL
+
 	if (osb == NULL || osb->sb == NULL || bhs == NULL) {
 		printk("ocfs: osb == NULL || osb->sb == NULL || bhs == NULL\n");
 		status = -EINVAL;
@@ -141,11 +153,13 @@
 		if (check_block_zero_write(bh) < 0)
 			goto bail;
 
-		if (!(flags & OCFS_BH_CACHED) && !(flags & OCFS_BH_IGNORE_JBD) 
-		    && buffer_jbd(bh)) {
-			printk("ocfs: trying to sync write a jbd managed bh "
-			       "(blocknr = %u)\n", bh->b_blocknr);
+		if (!(flags & OCFS_BH_IGNORE_JBD) && buffer_jbd(bh)) {
+#ifdef VERBOSE_BH_JBD_TRACE
+			printk("ocfs: trying to write a jbd managed bh "
+			       "(blocknr = %u), nr=%d\n", bh->b_blocknr, nr);
+#endif
 			/* they should not have dirty bit set... */
+			jbd_managed_buffers++;
 			continue;
 		}
 
@@ -170,6 +184,10 @@
 		VERBOSE_UNLOCK_BUFFER_STR(bh);
 	}
 
+	/* if *every* buffer submitted is already jbd managed, fully cached */
+	if (jbd_managed_buffers == nr)
+		flags |= OCFS_BH_CACHED;
+
 	if (!(flags & OCFS_BH_CACHED))
 		ll_rw_block (WRITE, nr, bhs);
 
@@ -183,6 +201,9 @@
 	}
 
 bail:
+
+	IO_FUNC_TIMING_PRINT("ocfs_write_bhs", status)
+
 	return status;
 }
 
@@ -193,6 +214,8 @@
 	int nr;
 	__u64 blocknum;
 	ocfs_blockdev dev;
+
+	IO_FUNC_TIMING_DECL
 	
 	if (osb == NULL || osb->sb == NULL || bh == NULL) {
 		printk("ocfs: osb == NULL || osb->sb == NULL || bh == NULL\n");
@@ -237,9 +260,11 @@
 	}
 
 	if (!(flags & OCFS_BH_CACHED) && buffer_jbd(*bh)) {
+#ifdef VERBOSE_BH_JBD_TRACE
 		printk("ocfs: trying to sync read a jbd managed bh "
 		       "(blocknr = %u)\n", (*bh)->b_blocknr);
-		return(status);
+#endif
+		goto error;
 	}
 
 	if (!(flags & OCFS_BH_CACHED)) {
@@ -265,6 +290,9 @@
 	//buffer_insert_inode_clean_queue(*bh, inode);
 
 error:
+
+	IO_FUNC_TIMING_PRINT("ocfs_read_bh", status)
+
 	return status;
 
 }
@@ -282,6 +310,8 @@
 	ocfs_blockdev dev;
 	struct buffer_head *bh;
 
+	IO_FUNC_TIMING_DECL
+
 	if (len % 512) {
 		printk("ocfs: len %% 512 (len=%u)\n", len);
 		status = -EINVAL;
@@ -313,7 +343,8 @@
 		printk("ocfs: No buffers will be read!!!\n");
 		printk("ocfs: Len=%u Off=%u.%u numbuffers=%u blocknum=%u.%u\n", len,
 		     HI (off), LO (off), nr, HI (blocknum), LO (blocknum));
-		return 0;
+		status = 0;
+		goto done;
 	}
 
 	for (i = 0 ; i < nr ; i++) {
@@ -340,9 +371,11 @@
 
 		if (!(flags & OCFS_BH_CACHED) || ignore_cache) {
 			if (buffer_jbd(bh)) {
+#ifdef VERBOSE_BH_JBD_TRACE
 				printk("ocfs: trying to sync read a jbd "
 				       "managed bh (blocknr = %u)\n", 
 				       bh->b_blocknr);
+#endif
 				if (!buffer_uptodate(bh)) {
 					printk("ocfs: jbd buffer is not "
 					       "uptodate!\n");
@@ -378,6 +411,9 @@
         }
 
 done:
+
+	IO_FUNC_TIMING_PRINT("ocfs_read_bh", status)
+
 	return status;
 }
 

Modified: trunk/inc/proto.h
===================================================================
--- trunk/inc/proto.h	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/inc/proto.h	2003-12-16 23:55:26 UTC (rev 10)
@@ -3,7 +3,7 @@
 int ocfs_free_extents_for_truncate (ocfs_super * osb, ocfs_file_entry * FileEntry, ocfs_journal_handle *handle, ocfs_bitmap_free_head *free_head, struct inode *inode);
 int ocfs_lookup_file_allocation (ocfs_super * osb, ocfs_inode * oin, __s64 Vbo, __s64 * Lbo, __u32 sectors, u32 *sector_count, struct inode *inode);
 int ocfs_get_leaf_extent (ocfs_super * osb, ocfs_file_entry * FileEntry, __s64 Vbo, struct buffer_head **data_extent_bh, struct inode *inode);
-int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile);
+int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, struct buffer_head *lock_bh);
 int ocfs_alloc_node_block (ocfs_super * osb, __u64 FileSize, __u64 * DiskOffset, __u64 * file_off, __u32 NodeNum, __u32 Type, ocfs_journal_handle *handle);
 int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe, ocfs_bitmap_free_head *free_head, struct inode *inode);
 int ocfs_free_file_extents (ocfs_super * osb, struct buffer_head *fe_bh, ocfs_bitmap_free_head *free_head);
@@ -49,7 +49,7 @@
 int ocfs_sync_file (struct file *file, struct dentry *dentry, int datasync);
 ssize_t ocfs_file_write (struct file *filp, const char *buf, size_t count, loff_t * ppos);
 ssize_t ocfs_file_read (struct file *filp, char *buf, size_t count, loff_t * ppos);
-int ocfs_extend_file (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, ocfs_journal_handle *passed_handle, struct inode *inode);
+int ocfs_extend_file (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, ocfs_journal_handle *passed_handle, struct inode *inode, struct iattr *attr);
 int ocfs_setattr (struct dentry *dentry, struct iattr *attr);
 int ocfs_getattr (struct dentry *dentry, struct iattr *attr);
 
@@ -197,3 +197,10 @@
 
 
 int ocfs_follow_link(struct dentry *dentry, struct nameidata *nd);
+
+int ocfs_create_new_local_alloc(ocfs_super *osb, int node_num);
+int ocfs_load_local_alloc(ocfs_super *osb);
+void ocfs_shutdown_local_alloc(ocfs_super *osb, 
+			       struct buffer_head **local_alloc_bh, bool sync);
+int ocfs_find_space(ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, ocfs_journal_handle *handle);
+int ocfs_recover_local_alloc(ocfs_super *osb, int node_num);

Modified: trunk/inode.c
===================================================================
--- trunk/inode.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/inode.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -774,7 +774,7 @@
 		if (unlock)
 			ocfs_up_sem (&(oin->main_res));
 
-		status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode);
+		status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode, NULL);
 
 		if (unlock)
 			ocfs_down_sem (&(oin->main_res), true);

Modified: trunk/journal.c
===================================================================
--- trunk/journal.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/journal.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -88,8 +88,6 @@
 		retval->k_handle = NULL;
 		goto done_free;
 	}
-	/* we want all transactions to be force-committed for now */
-	retval->k_handle->h_sync = 1;
 
 	atomic_inc(&(osb->journal.num_trans));
 
@@ -98,7 +96,8 @@
 	up(&osb->journal.commit_sem);
 
 	/* default handle flags! */
-	retval->flags = OCFS_HANDLE_CHECKPOINT;
+	ocfs_handle_set_sync(retval, true);
+	ocfs_handle_set_checkpoint(retval, true);
 
 	LOG_EXIT_PTR(retval);
 	return(retval);
@@ -265,7 +264,7 @@
 	int retval = 0, i;
 	struct buffer_head *bh;
 	bool revoked = false;
-	bool checkpoint;
+	bool checkpoint, sync;
 	ocfs_journal *journal;
 
 	LOG_ENTRY();
@@ -278,10 +277,21 @@
 	kern_trans = kern_handle->h_transaction;
 	journal = &osb->journal;
 	checkpoint = handle->flags & OCFS_HANDLE_CHECKPOINT;
+	/* if you want to checkpoint, you MUST also sync. */
+	if (checkpoint)
+		ocfs_handle_set_sync(handle, true);
+	sync = handle->flags & OCFS_HANDLE_SYNC;
 
-	LOG_TRACE_ARGS("Commiting %d blocks, checkpoint = %s\n", 
-		       handle->num_buffs, checkpoint ? "true" : "false");
-	/* actually stop the transaction. because we've set h_sync,
+	LOG_TRACE_ARGS("Commiting %d blocks, checkpoint = %s, sync = %s\n", 
+		       handle->num_buffs, checkpoint ? "true" : "false",
+		       sync ? "true" : "false");
+
+	if (sync)
+		kern_handle->h_sync = 1;
+	else
+		kern_handle->h_sync = 0;
+
+	/* actually stop the transaction. if we've set h_sync,
 	 * it'll have been commited when we return */
 	retval = journal_stop(kern_handle);
 	if (retval < 0) {
@@ -421,6 +431,9 @@
 		journal_forget(handle->k_handle, bh);
 	}
 
+	/* want to force our handle to disk in abort case. */
+	handle->k_handle->h_sync = 1;
+
 	retval = journal_stop(handle->k_handle);
 	if (retval < 0) {
 		LOG_ERROR_STR("Could not commit aborted transaction!");
@@ -780,7 +793,7 @@
 void ocfs_journal_shutdown(ocfs_super *osb) 
 {
 	ocfs_journal * journal = NULL;
-	int status = -1;
+	int status = 0;
 	ocfs_inode *oin;
 	struct inode * inode = NULL;
 	int num_running_trans = 0;
@@ -793,8 +806,10 @@
 	journal = &osb->journal;
 	inode = journal->k_inode;
 
-	if (journal->state != OCFS_JOURNAL_LOADED)
+	if (journal->state != OCFS_JOURNAL_LOADED) {
+		LOG_ERROR_STATUS(status = -EINVAL);
 		goto done;
+	}
 
 	/* need to inc inode use count as journal_destroy will iput. */
 	atomic_inc(&inode->i_count);
@@ -805,20 +820,20 @@
 			       " running transactions!\n", num_running_trans);
 
 	down(&osb->trans_lock);
-	journal_lock_updates(journal->k_journal);
-	status = journal_flush(journal->k_journal);
-	journal_unlock_updates(journal->k_journal);
+	/* Do a commit_cache here. It will flush our journal, *and*
+	 * release any locks that are still held The
+	 * OCFS_JOURNAL_IN_SHUTDOWN will signal to commit_cache to not
+	 * drop the trans_lock (which we want to hold until we
+	 * completely destroy the journal. */
+	journal->state = OCFS_JOURNAL_IN_SHUTDOWN;
+	
+	status = ocfs_commit_cache(osb, false);
 	if (status < 0)
 		LOG_ERROR_STATUS(status);
 
 	/* Shutdown the kernel journal system */
 	journal_destroy(journal->k_journal);
 
-	/* unset the mounted flag -- we're done with the journal */
-	status = ocfs_journal_set_unmounted(osb, journal->node_num);
-	if (status < 0)
-		LOG_ERROR_STR("Could not set mounted flag!");
-
 	/* release the oin here. Isn't this racy? */
 	if (inode_data_is_oin(inode)) {
 		oin = GET_INODE_OIN(inode);
@@ -1254,7 +1269,7 @@
 	cleanup_file_id = (__u32) (JOURNAL_FILE_BASE_ID + node_num);
 	lock_id = ((JOURNAL_FILE_BASE_ID + node_num) * osb->sect_size) 
 		+ osb->vol_layout.root_int_off;
-	
+
 	/* Should not ever be called to recover ourselves -- in that
 	 * case we should've called ocfs_journal_load instead. */
 	if (osb->node_num == node_num)
@@ -1378,6 +1393,13 @@
 	/* shutdown the journal */
 	journal_destroy(k_journal);
 
+	/* recover his local alloc file, AFTER recovering his journal... */
+	status = ocfs_recover_local_alloc(osb, node_num);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto done;
+	}
+
 	/* clear the publish sector (mark it unmounted and clean) */
 	status = ocfs_reset_publish(osb, node_num);
 	if (status < 0)
@@ -1489,12 +1511,15 @@
  *
  * 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.
  */
 int ocfs_commit_cache (ocfs_super * osb, bool data_flush)
 {
 	int status = 0, tmpstat;
 	ocfs_journal * journal = NULL;
 	struct list_head *p, *n;
+	struct list_head tmplist;
 	ocfs_journal_handle *handle = NULL;
 
 	LOG_ENTRY_ARGS("(data_flush = %u)\n", data_flush);
@@ -1505,6 +1530,8 @@
 	journal = &osb->journal;
 
 	if (atomic_read(&journal->num_trans) == 0) {
+		up(&osb->trans_lock);
+
 		LOG_TRACE_STR("No transactions for me to flush!");
 		goto flush_data;
 	}
@@ -1514,23 +1541,44 @@
 	status = journal_flush(journal->k_journal);
 	journal_unlock_updates(journal->k_journal);
 	if (status < 0) {
+		up(&osb->trans_lock);
+
 		LOG_ERROR_STATUS(status);
 		goto finally;
 	}
 
+	LOG_TRACE_ARGS("flushing %d transactions\n", 
+		       atomic_read(&journal->num_trans));
+
+	atomic_set(&journal->num_trans, 0);
+
 	/* now we can run an unlock against any pending handles and
 	 * release them. */
+	INIT_LIST_HEAD(&tmplist);
+
 	down(&journal->commit_sem);
-	list_for_each_safe(p, n, &journal->commited) {
+	/* 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 , (&tmplist));
+		INIT_LIST_HEAD(&journal->commited);
+	}
+	up(&journal->commit_sem);
+
+	osb->needs_flush = false;
+	/* shutdown code wants to hold the trans lock */
+	if (journal->state != OCFS_JOURNAL_IN_SHUTDOWN)
+		up(&osb->trans_lock);
+
+	list_for_each_safe(p, n, &tmplist) {
 		handle = list_entry(p, ocfs_journal_handle, h_list);
 		tmpstat = ocfs_journal_release_locks(handle, 0);
 		if (tmpstat < 0)
 			LOG_ERROR_STATUS((status = tmpstat));
 		list_del(&(handle->h_list));
 		ocfs_free(handle);
-		atomic_dec(&journal->num_trans);
 	}
-	up(&journal->commit_sem);
 
 flush_data:
 	/* flush data buffers if asked. */

Modified: trunk/namei.c
===================================================================
--- trunk/namei.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/namei.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -157,7 +157,10 @@
 		goto leave;
 	}
 
-	handle->flags &= ~OCFS_HANDLE_CHECKPOINT;
+	ocfs_handle_set_checkpoint(handle, false);
+#ifdef ALLOW_NO_HANDLE_SYNCING
+		ocfs_handle_set_sync(handle, false);
+#endif
 
 	/* lock the parent directory */
 	status = ocfs_acquire_lock (osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
@@ -1147,7 +1150,7 @@
 	OCFS_BH_PUT_DATA(new_fe_bh);
 	fe = NULL;
 
-	status = ocfs_extend_file (osb, parent_off, NULL, newsize, &file_off, handle, inode);
+	status = ocfs_extend_file (osb, parent_off, NULL, newsize, &file_off, handle, inode, NULL);
 	if (status < 0) {
 		if (status != -ENOSPC && status != -EINTR) {
 			LOG_ERROR_ARGS ("Failed to extend file to %u.%u", HILO (newsize));
@@ -1159,6 +1162,9 @@
 
 abort_trans:
 	if (handle) {
+		ocfs_bitmap_free_head *f = osb->alloc_free_head;
+		osb->alloc_free_head = NULL;
+
 		if (status < 0)
 			ocfs_abort_trans(handle);
 		else {
@@ -1166,6 +1172,11 @@
 			if (status < 0)
 				LOG_ERROR_STATUS(status);
 		}
+
+		if (f) {
+			ocfs_process_bitmap_free_head(osb, f);
+			free_bitmap_free_head(f);
+		}
 	}
 
 	if (lock_res != NULL) {

Modified: trunk/nm.c
===================================================================
--- trunk/nm.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/nm.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -212,6 +212,7 @@
 	return(status);
 }   /* ocfs_schedule_process_vote */
 
+#define OCFS_NM_MAX_FLUSH_MISSES		150
 
 /*
  * ocfs_volume_thread()
@@ -237,6 +238,7 @@
 	__u64 curr_node_map;
 	__u64 cfg_seq_num;
 	int which;
+	int flush_misses = 0;
 	struct buffer_head *bh = NULL;
 
 	LOG_ENTRY ();
@@ -284,27 +286,21 @@
 		if (osb->vol_state == VOLUME_MOUNTED) {
 			if (osb->needs_flush && down_trylock(&osb->trans_lock) == 0) {
 				if (osb->trans_in_progress == false) {
-					osb->num_nm_thread_iter = 0;
+					flush_misses = 0;
 					status = ocfs_commit_cache(osb, false);
 					if (status < 0)
 						LOG_ERROR_STATUS (status);
-					osb->needs_flush = false;
 				}
-				up(&osb->trans_lock);
+			} else if (osb->needs_flush) {
+				flush_misses++;
+				if (flush_misses > OCFS_NM_MAX_FLUSH_MISSES) {
+					printk("ocfs: nm thread has not been "
+					       "able to commit cache in %d "
+					       "iterations!\n", flush_misses);
+				}
 			}
 		}
 
-		/* Force a flush every 300 iterations. No longer
-		 * necessary, but I suppose it doesn't hurt... */
-		if (osb->needs_flush)
-			osb->num_nm_thread_iter = 0;
-		else {
-			osb->num_nm_thread_iter++;
-			if (osb->num_nm_thread_iter > 300) {
-				osb->needs_flush = true;
-			}
-		}
-
 		/* lock publish to prevent overwrites from vote_req and vote_reset */
 		down (&(osb->publish_lock));
 
@@ -319,20 +315,7 @@
 			goto finally;
 		}
 
-#ifdef STUPID_STUFF
-		/* Update the timestamp on disk to indicate that it is alive */
-		ocfs_down_sem (&(osb->voting_lock), true);
-		if (osb->in_voting == NOT_VOTING) {
-			ocfs_up_sem (&(osb->voting_lock));
-#endif
-			ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, false);
-#ifdef STUPID_STUFF
-		} else {
-			printk("(%u) ocfs_volume_thread: SKIPPING HEARTBEAT\n", ocfs_getpid());
-			osb->in_voting = SKIPPED_HEARTBEAT;
-			ocfs_up_sem (&(osb->voting_lock));
-		}
-#endif
+		ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, false);
 
 		/* release publish lock */
 		up (&(osb->publish_lock));
@@ -1083,8 +1066,6 @@
 					ocfs_put_lockres(lockres);
 					goto leave;
 				}
-				osb->needs_flush = false;
-				up(&osb->trans_lock);
 
 				status = ocfs_acquire_lockres_ex(lockres, 
 						   (OCFS_NM_HEARTBEAT_TIME/2));
@@ -1106,8 +1087,6 @@
 			break;
 
 give_lock:
-			osb->num_nm_thread_iter = 0;
-			
 			if (vote_type == CHANGE_MASTER)	
 				lockres->master_node_num = node_num;
 

Modified: trunk/osb.c
===================================================================
--- trunk/osb.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/osb.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -34,11 +34,8 @@
 	osb->obj_id.type = OCFS_TYPE_OSB;
 	osb->obj_id.size = sizeof (ocfs_super);
 
-#ifdef x86_64
-#define HASHBITS	11
-#else
 #define HASHBITS	12
-#endif
+
 	if (!ocfs_hash_create (&(osb->root_sect_node), HASHBITS)) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
 		goto bail;
@@ -71,7 +68,6 @@
 
 	osb->publish_dirty = false;
 	osb->in_voting = NOT_VOTING;
-	osb->num_nm_thread_iter = 0;
 	ocfs_init_sem (&(osb->voting_lock));
 	init_waitqueue_head (&osb->flush_event);
 	atomic_set (&osb->flush_event_woken, 0);
@@ -160,13 +156,6 @@
 	memset(osb->cfg_bhs, 0, 
 	       osb->cfg_numblocks * sizeof(struct buffer_head *));
 
-	osb->log_prealloc = ocfs_malloc (OCFS_ALIGN(sizeof(ocfs_cleanup_record),
-						    PAGE_SIZE));
-	if (!osb->log_prealloc) {
-		LOG_ERROR_STATUS (status = -ENOMEM);
-		goto bail;
-	}
-
 	status = ocfs_get_config (osb);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
@@ -231,7 +220,6 @@
 		ocfs_hash_destroy (&(osb->root_sect_node), NULL);
 	ocfs_safefree (osb->data_prealloc);
 	ocfs_safefree (osb->md_prealloc);
-	ocfs_safefree (osb->log_prealloc);
 	ocfs_safefree (osb->cfg_bhs);
 
 finally:
@@ -359,7 +347,7 @@
 			goto finally;
 		}
 
-		printk("OCFS: Old journal type found, converting to new"    \
+		printk("ocfs: Old journal type found, converting to new"    \
 			      "style. You will no longer be able to mount " \
 			      "with old versions of ocfs.\n");
 
@@ -377,6 +365,16 @@
 			LOG_ERROR_STR("Could not update node config!");
 			goto finally;
 		}
+
+		/* Ok, piggy-back local alloc file creation here. If
+		 * this is also a 1st mount of the filesystem, then
+		 * the worst that'll happen is we stamp the new local
+		 * alloc twice -- not really a big deal :) */
+		status = ocfs_create_new_local_alloc(osb, osb->node_num);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
 		goto skip_load;
 	}
 
@@ -388,10 +386,19 @@
 	else
 		printk(KERN_NOTICE "ocfs: File system was not unmounted "
 		       "cleanly, recovering volume.\n");
-	
+
 	/* will play back anything left in the journal. */
 	ocfs_journal_load(&osb->journal);
 
+	if (mounted) {
+		/* recover my local alloc if we didn't unmount cleanly. */
+		status = ocfs_recover_local_alloc(osb, node_num);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto finally;
+		}
+	}
+
 skip_load:
 	/* 'mounted' flag in publish sector should not be set until
 	 * after we successfully load the journal. */
@@ -399,7 +406,11 @@
 	if (status < 0)
 		LOG_ERROR_STR("Could not set mounted flag!");
 	LOG_TRACE_STR("Journal loaded.");
-	
+
+	status = ocfs_load_local_alloc(osb);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
 finally:
 	if (publish_bh) {
 		if (publish)
@@ -447,111 +458,12 @@
 		if (osb->cfg_bhs[i])
 			brelse(osb->cfg_bhs[i]);
 	ocfs_safefree(osb->cfg_bhs);
-	ocfs_safefree(osb->log_prealloc);
 	memset (osb, 0, sizeof (ocfs_super));
 
 	LOG_EXIT ();
 	return;
 }				/* ocfs_delete_osb */
 
-
-#if 0
-/*
- * ocfs_create_meta_log_files()
- *
- */
-static int ocfs_create_meta_log_files (ocfs_super * osb)
-{
-	int status = 0;
-	__u64 fileSize = 0;
-	__u64 allocSize = 0;
-	__u64 log_disk_off = 0;
-	__u32 logFileId;
-
-	LOG_ENTRY ();
-
-	logFileId = (OCFS_FILE_VOL_LOG_FILE + osb->node_num);
-
-	status = ocfs_get_system_file_size (osb, logFileId, &fileSize, &allocSize);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	if (allocSize != 0) {
-		log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_LOG_FILE +
-						       osb->node_num), 0);
-		if (log_disk_off == 0) {
-			LOG_ERROR_STATUS(status = -EFAIL);
-			goto bail;
-		}
-
-		osb->log_disk_off = log_disk_off;
-
-		log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_META_DATA +
-						       osb->node_num), 0);
-		if (log_disk_off == 0) {
-			LOG_ERROR_STATUS(status = -EFAIL);
-			goto bail;
-		}
-		osb->log_meta_disk_off = log_disk_off;
-		goto bail;
-	}
-
-	status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE +
-					 osb->node_num), (ONE_MEGA_BYTE * 10), 
-					  NULL, NULL);
-	if (status < 0) {
-		/* if that fails, fall back to smaller, for fragmented fs */
-		status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE 
-							+ osb->node_num), 
-						  128 * 1024, NULL, NULL);
-		if (status < 0) {
-			LOG_ERROR_STATUS (status);
-			goto bail;
-		}
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	ocfs_extend_system_file (osb, (OCFS_FILE_VOL_LOG_FILE + osb->node_num),
-				 0, NULL, NULL);
-
-	log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_LOG_FILE +
-					       osb->node_num), 0);
-	if (log_disk_off == 0) {
-		LOG_ERROR_STATUS(status = -EFAIL);
-		goto bail;
-	}
-
-	osb->log_disk_off = log_disk_off;
-
-	status = ocfs_extend_system_file (osb, (OCFS_FILE_VOL_META_DATA +
-					 osb->node_num), ONE_MEGA_BYTE, NULL, 
-					  NULL);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		return (status);
-	}
-
-	ocfs_extend_system_file (osb, (OCFS_FILE_VOL_META_DATA + osb->node_num), 0, NULL, NULL);
-
-	log_disk_off = ocfs_file_to_disk_off (osb, (OCFS_FILE_VOL_META_DATA +
-					       osb->node_num), 0);
-	if (log_disk_off == 0) {
-		LOG_ERROR_STATUS(status = -EFAIL);
-		goto bail;
-	}
-
-	osb->log_meta_disk_off = log_disk_off;
-
-      bail:
-	LOG_EXIT_STATUS (status);
-	return status;
-}				/* ocfs_create_meta_log_files */
-#endif
-
-
 /* ocfs_create_root_dir_node()
  *
  */
@@ -603,7 +515,8 @@
 	    ONE_MEGA_BYTE : osb->vol_layout.cluster_size;
 
 	status = ocfs_find_contiguous_space_from_bitmap (osb, size,
-					&bitmapOffset, &numClustersAlloc, false);
+					&bitmapOffset, &numClustersAlloc, 
+					false, NULL);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status);
 		goto bail;
@@ -622,9 +535,7 @@
 		ocfs_init_system_file (osb, OCFS_FILE_FILE_ALLOC_BITMAP + i, buf);
 		ocfs_init_system_file (osb, LOG_FILE_BASE_ID + i, buf);
 		ocfs_init_system_file (osb, CLEANUP_FILE_BASE_ID + i, buf);
-#ifdef LOCAL_ALLOC
-		ocfs_init_system_file (osb, OCFS_VOL_BITMAP_FILE + (2*i), buf);
-#endif 
+		status = ocfs_create_new_local_alloc(osb, i);
 	}
 
 	status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size,

Modified: trunk/super.c
===================================================================
--- trunk/super.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/super.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -598,11 +598,6 @@
  */
 static void __exit ocfs_driver_exit (void)
 {
-	ocfs_super *osb = NULL;
-	struct list_head *osb_entry;
-	struct list_head *osb_tmp;
-	__u32 i = 0;
-	int status;
 
 	LOG_ENTRY ();
 
@@ -613,26 +608,6 @@
 	ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
 	OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_SHUTDOWN_VOL_THREAD);
 
-	list_for_each_safe (osb_entry, osb_tmp, &(OcfsGlobalCtxt.osb_next)) {
-		osb = list_entry (osb_entry, ocfs_super, osb_next);
-
-		ocfs_down_sem (&osb->osb_res, true);
-		OCFS_SET_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_SHUTDOWN);
-		ocfs_up_sem (&osb->osb_res);
-
-		osb->needs_flush = true;
-		while ((osb->trans_in_progress) && (i < 10)) {
-			ocfs_sleep (100);
-			i++;
-		}
-		status = ocfs_commit_cache (osb, true);
-		if (status < 0)
-			LOG_ERROR_STATUS (status);
-		osb->needs_flush = false;
-
-		list_del (&osb->osb_next);
-	}
-
 	if (OcfsGlobalCtxt.flags & OCFS_FLAG_MEM_LISTS_INITIALIZED)
 		ocfs_free_mem_lists ();
 
@@ -1050,7 +1025,16 @@
 	}
 #endif
 
+	/* Shutdown the journal and sync up and clear the local alloc. */
 	ocfs_journal_shutdown(osb);
+	ocfs_shutdown_local_alloc(osb, NULL, true);
+
+	/* unset the mounted flag -- we're done with the journal and
+	 * the local alloc bitmap */
+	status = ocfs_journal_set_unmounted(osb, osb->node_num);
+	if (status < 0)
+		LOG_ERROR_STR("Could not set mounted flag!");
+
 	ocfs_sync_blockdev(sb);
 	ocfs_release_oin (rootoin, true);
 

Modified: trunk/sysfile.c
===================================================================
--- trunk/sysfile.c	2003-12-10 19:24:56 UTC (rev 9)
+++ trunk/sysfile.c	2003-12-16 23:55:26 UTC (rev 10)
@@ -76,11 +76,10 @@
 	} else if ((file_id >= OCFS_FILE_VOL_LOG_FILE) &&
 		   (file_id < (OCFS_FILE_VOL_LOG_FILE + 32))) {
 		sprintf (filename, "%s", "VolMetaDataLogFile");
-#ifdef LOCAL_ALLOC
 	} else if ((file_id >= OCFS_VOL_BITMAP_FILE) && 
-	      	   (file_id < (OCFS_FILE_VOL_LOG_FILE + 64))) {
-		sprintf (filename, "%s", "VolBitMapFile");
-#endif
+	      	   (file_id < (OCFS_VOL_BITMAP_FILE + 32))) {
+		/* do nothing! should use create_new_local_alloc! */
+		return(0);
 	} else {
 		sprintf (filename, "%s", "UKNOWNSysFile");
 	}
@@ -149,9 +148,10 @@
 	int flags = OCFS_BH_CACHED;
 	bool bWriteThru = false;
 
-	LOG_ENTRY_ARGS ("(FileId = %u, metadatafile = %u, offset = (%u.%u))\n",
-			FileId, OCFS_FILE_VOL_META_DATA + osb->node_num, 
-			HILO(Offset));
+	LOG_ENTRY_ARGS ("(FileId = %u, metadatafile = %u, offset = (%u.%u), "
+			"Length = (%u.%u))\n", FileId, 
+			OCFS_FILE_VOL_META_DATA + osb->node_num, HILO(Offset),
+			HILO(Length));
 
 	if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
 	    (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
@@ -425,7 +425,8 @@
 		    ocfs_find_contiguous_space_from_bitmap (osb,
 						   FileSize - fe->alloc_size,
 						   &BitmapOffset,
-						   &numClusterAlloc, true);
+						   &numClusterAlloc, true, 
+						   NULL);
 		if (status < 0) {
 			LOG_ERROR_STATUS (status);
 			goto leave;



More information about the Ocfs2-commits mailing list