[Ocfs2-commits] mfasheh commits r1538 - branches/dlm-changes/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Oct 1 17:07:14 CDT 2004


Author: mfasheh
Date: 2004-10-01 17:07:13 -0500 (Fri, 01 Oct 2004)
New Revision: 1538

Added:
   branches/dlm-changes/src/localalloc.c
   branches/dlm-changes/src/localalloc.h
Modified:
   branches/dlm-changes/src/Makefile
   branches/dlm-changes/src/alloc.c
   branches/dlm-changes/src/journal.c
   branches/dlm-changes/src/ocfs_log.h
   branches/dlm-changes/src/super.c
Log:
* move the local alloc stuff into it's own file



Modified: branches/dlm-changes/src/Makefile
===================================================================
--- branches/dlm-changes/src/Makefile	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/Makefile	2004-10-01 22:07:13 UTC (rev 1538)
@@ -73,6 +73,7 @@
 	inode.c			\
 	ioctl.c			\
 	journal.c		\
+	localalloc.c		\
 	lockres.c		\
 	namei.c			\
 	nm.c			\
@@ -106,6 +107,7 @@
 	inode.h			\
 	ioctl.h			\
 	journal.h		\
+	localalloc.h		\
 	lockres.h		\
 	namei.h			\
 	nm.h			\

Modified: branches/dlm-changes/src/alloc.c
===================================================================
--- branches/dlm-changes/src/alloc.c	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/alloc.c	2004-10-01 22:07:13 UTC (rev 1538)
@@ -41,6 +41,7 @@
 #include "dlm.h"
 #include "extmap.h"
 #include "inode.h"
+#include "localalloc.h"
 #include "util.h"
 #include "suballoc.h"
 #include "sysfile.h"
@@ -110,41 +111,14 @@
 					struct buffer_head *bh,
 					ocfs_free_rec *freelog); 
 
-/* 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)
-static inline int ocfs_local_alloc_window_bits(ocfs_super *osb);
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits);
-static int ocfs_local_alloc_full_window_change(ocfs_super *osb, 
-					       struct inode * local_alloc_inode);
-static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh,
-				 struct inode *bm_inode,
-				 ocfs_journal_handle *handle);
-static int ocfs_sync_local_from_shutdown(ocfs_super *osb, 
-					 ocfs_bitmap_free_head **f, 
-					 struct buffer_head *local_alloc_bh, 
-					 int in_recovery);
-static __u32 ocfs_alloc_count_bits(ocfs2_dinode *alloc);
-static void ocfs_clear_local_alloc(ocfs2_dinode *alloc);
-static int ocfs_local_find_clear_bits(ocfs_super *osb,
-				      ocfs2_dinode *alloc,
-				      __u32 numbits);
 static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
 			      u64 blkno);
 
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits);
-
 static int ocfs_reserve_main_bitmap_bits(ocfs_super *osb, 
 					 ocfs_journal_handle *handle,
 					 u32 bits_wanted,
 					 ocfs2_alloc_context *ac);
 
-static int ocfs_reserve_local_bits(ocfs_super *osb, 
-				   ocfs_journal_handle *passed_handle,
-				   u32 bits_wanted,
-				   ocfs2_alloc_context *ac);
-
 static int ocfs_claim_main_bitmap_bits(ocfs_super *osb,
 				       ocfs_journal_handle *handle,
 				       ocfs2_alloc_context *ac,
@@ -152,13 +126,6 @@
 				       u32 *bit_off,
 				       u32 *num_bits);
 
-static int ocfs_claim_local_bitmap_bits(ocfs_super *osb,
-					ocfs_journal_handle *handle,
-					ocfs2_alloc_context *ac,
-					u32 min_bits,
-					u32 *bit_off,
-					u32 *num_bits);
-
 static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
 			      u64 blkno)
 {
@@ -2789,12 +2756,12 @@
 	OCFS_ASSERT(ac->ac_handle == handle);
 
 	if (ac->ac_which == OCFS_AC_USE_LOCAL) {
-		status = ocfs_claim_local_bitmap_bits(osb, 
-						      handle, 
-						      ac, 
-						      min_bits,
-						      bit_off, 
-						      num_bits);
+		status = ocfs_claim_local_alloc_bits(osb, 
+						     handle, 
+						     ac, 
+						     min_bits,
+						     bit_off, 
+						     num_bits);
 	} else {
 		status = ocfs_claim_main_bitmap_bits(osb, 
 						     handle, 
@@ -2904,62 +2871,6 @@
 	return(status);
 }
 
-static int ocfs_claim_local_bitmap_bits(ocfs_super *osb,
-					ocfs_journal_handle *handle,
-					ocfs2_alloc_context *ac,
-					u32 min_bits,
-					u32 *bit_off,
-					u32 *num_bits)
-{
-	int status, start;
-	struct inode *local_alloc_inode;
-	u32 bits_wanted;
-	void *bitmap;
-	ocfs2_dinode *alloc;
-
-	LOG_ENTRY();
-	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL);
-
-	bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
-	local_alloc_inode = ac->ac_inode;
-	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
-	start = ocfs_local_find_clear_bits(osb, alloc, bits_wanted);
-	if (start == -1) {
-		/* TODO: Shouldn't we just BUG here? */
-		status = -ENOSPC;
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-	*bit_off = LOCAL_ALLOC(alloc)->la_bm_off + start;
-	/* local alloc is always contiguous by nature -- we never
-	 * delete bits from it! */
-	*num_bits = bits_wanted;
-
-	status = ocfs_journal_access(handle, osb->local_alloc_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	while(bits_wanted--)
-		set_bit(start++, bitmap);
-
-	status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	status = 0;
-bail:
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
 /* caller is responsible for freeing 'ac' when he's done with it. */
 int ocfs_reserve_bits(ocfs_super *osb, 
 		      ocfs_journal_handle *handle,
@@ -2983,10 +2894,10 @@
 
 	status = -ENOSPC;
 	if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
-		status = ocfs_reserve_local_bits(osb, 
-						 handle, 
-						 bits_wanted, 
-						 *ac);
+		status = ocfs_reserve_local_alloc_bits(osb, 
+						       handle, 
+						       bits_wanted, 
+						       *ac);
 		if ((status < 0) && (status != -ENOSPC)) {
 			LOG_ERROR_STATUS(status);
 			goto bail;
@@ -3089,211 +3000,7 @@
 	return(status);
 }
 
-/* 
- * ocfs_reserve_local_bits
- *
- * make sure we've got at least bitswanted contiguous bits in the
- * local alloc. You lose them when you drop ip_io_sem.
- * 
- * We will add ourselves to the transaction passed in, but may start
- * our own in order to shift windows.
- *
- * When we stop being lame and support multiple chunks of
- * discontiguous space, we this turns into a really simple check of
- * ->la_bits_set
- */
-static int ocfs_reserve_local_bits(ocfs_super *osb, 
-				   ocfs_journal_handle *passed_handle,
-				   u32 bits_wanted,
-				   ocfs2_alloc_context *ac)
-{
-	int status;
-	struct inode *local_alloc_inode = NULL;
-	int startoff;
-	ocfs2_dinode *alloc;
-
-	LOG_ENTRY();
-
-	OCFS_ASSERT(passed_handle);
-	OCFS_ASSERT(ac);
-	OCFS_ASSERT(!(passed_handle->flags & OCFS_HANDLE_STARTED));
-
-	local_alloc_inode = 
-		ocfs_get_system_file_inode(osb, 
-					   LOCAL_ALLOC_SYSTEM_INODE,
-					   osb->node_num);
-	if (!local_alloc_inode) {
-		status = -ENOENT;
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-	ocfs_handle_add_inode(passed_handle, local_alloc_inode);
-
-	if (!osb->have_local_alloc) {
-		status = -ENOSPC;
-		goto bail;
-	}
-
-#warning "isn't it about time we turned this check off?"
-	if (bits_wanted > ocfs_clusters_for_bytes(osb->sb, 
-						 OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
-		LOG_TRACE_STR("Asking for more than max local alloction!\n");
-		status = -ENOSPC;
-		goto bail;
-	}
-
-	if (bits_wanted > ocfs_local_alloc_window_bits(osb)) {
-		LOG_TRACE_STR("Asking for more than my max window size!\n");
-		status = -ENOSPC;
-		goto bail;
-	}
-
-	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-	startoff = ocfs_local_find_clear_bits(osb, alloc, bits_wanted);
-	if (startoff == -1) {
-		/* uhoh, window change time. */
-		status = 
-			ocfs_local_alloc_full_window_change(osb, 
-							    local_alloc_inode);
-		if (status < 0) {
-			if (status != -ENOSPC)
-				LOG_ERROR_STATUS(status);
-			goto bail;
-		}
-	}
-
-	ac->ac_inode = igrab(local_alloc_inode);
-	get_bh(osb->local_alloc_bh);
-	ac->ac_bh = osb->local_alloc_bh;
-
-	status = 0;
-bail:
-	if (local_alloc_inode)
-		iput(local_alloc_inode);
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
 /*
- * ocfs_find_contiguous_space_from_bitmap()
- *
- * Used only from local alloc right now. Eventually will go away, so
- * don't add more callers to this function. Use the reserve / claim
- * apis instead as they'll even get you distcongiuous areas.
- *
- * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
- * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
- *
- * Returns 0 on success, < 0 on error.
- */
-static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
-					   ocfs_journal_handle *handle,
-					   __u64 file_size,
-					   u32 *cluster_off,
-					   u32 *cluster_count,
-					   struct buffer_head *bh,
-					   struct inode *bitmap_inode)
-{
-	int status = 0, startbh, numblocks;
-	u32 bitoffset = 0, num_clusters = 0;
-	ocfs2_dinode *bm_lock;
-	__u32 bitmapblocks; /* we only care about the valid blocks */
-	__u32 free_bits;
-
-	LOG_ENTRY ();
-
-	OCFS_ASSERT(osb);
-	OCFS_ASSERT(bh);
-	OCFS_ASSERT(bitmap_inode);
-	OCFS_ASSERT(handle);
-
-	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto leave;
-	}
-
-	bm_lock = (ocfs2_dinode *) bh->b_data;
-
-	num_clusters = (u32) ((u64) (file_size + (osb->s_clustersize-1)) >> 
-				osb->s_clustersize_bits);
-	if (num_clusters == 0) {
-		LOG_ERROR_STR ("DISK_FULL?: num_clusters==0");
-		status = 0;
-		goto leave;
-	}
-
-	free_bits = le32_to_cpu(bm_lock->id1.bitmap1.i_total) - 
-		le32_to_cpu(bm_lock->id1.bitmap1.i_used);
-
-	if (num_clusters > free_bits) {
-		LOG_ERROR_ARGS("Disk Full: num_clusters=%u, free_bits=%u\n",
-			       num_clusters, free_bits);
-		status = -ENOSPC;
-		goto leave;
-	}
-
-	bitmapblocks =
-		ocfs_blocks_for_bits(osb->sb,
- 				     osb->cluster_bitmap.validbits);
-
-	/* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
-	if (ocfs_read_bhs(osb, osb->bitmap_blkno << osb->sb->s_blocksize_bits, 
-			  bitmapblocks << osb->sb->s_blocksize_bits,
-			  osb->cluster_bitmap.chunk, OCFS_BH_CACHED, bitmap_inode)) {
-		LOG_ERROR_STATUS(-EIO);
-		goto leave;
-	}
-
-	status = 0;
-	status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap, 
-				       num_clusters, &bitoffset, 
-				       NULL);
-	if (status < 0) {
-		osb->cluster_bitmap.failed++;
-		LOG_TRACE_ARGS("Cannot allocate %u contiguous clusters "
-			       "for system file\n", num_clusters);
-		status = -ENOSPC;
-		goto leave;
-	}
-
-	LOG_TRACE_ARGS ("setting %u bits at bit offset=%u\n", 
-			num_clusters, bitoffset);
-
-	ocfs_set_bits(osb->sb, handle, &osb->cluster_bitmap, bitoffset,
-		      num_clusters);
-
-	/* 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. */
-	numblocks = ocfs_bitmap_blocks_affected(osb->sb,
-						bitoffset,
-						num_clusters,
-						&startbh);
-
-	LOG_TRACE_ARGS("bitoffset = %u, num_clusters = %u, startbh = %u, numblocks = %u\n", bitoffset, num_clusters, startbh, numblocks);
-
-	/* write the bitmap size info to the lock sector */
-	bm_lock->id1.bitmap1.i_used =
-		ocfs_count_bits(osb->sb, &osb->cluster_bitmap);
-
-	status = ocfs_journal_dirty(handle, bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto leave;
-	}
-
-	*cluster_off = bitoffset;
-	*cluster_count = num_clusters;
-	status = 0;
-
-leave:
-	LOG_EXIT_STATUS (status);
-	return status;
-}				/* ocfs_find_contiguous_space_from_bitmap */
-
-/*
  * ocfs_free_file_extents()
  *
  */
@@ -3364,739 +3071,3 @@
 	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. */
-
-/* 
- * 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, 
- * 32k -> 128 bits, 64k -> 64 bits
- */
-static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
-{
-	int numbits;
-
-	switch (osb->s_clustersize) {
-	case (4*1024):
-		numbits = 1024;
-		break;
-
-	case (8*1024):
-		numbits = 512;
-		break;
-
-	case (16*1024):
-		numbits = 256;
-		break;
-
-	case (32*1024):
-		numbits = 128;
-		break;
-
-	default:
-		numbits = 64;
-		break;
-	}
-	return(numbits);
-} /* ocfs_local_alloc_window_bits */
-
-static inline int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits)
-{
-	if (osb->have_local_alloc 
-	    && ((bits<<osb->s_clustersize_bits) <= OCFS_LOCAL_ALLOC_MAX_ALLOC)
-	    && (bits <= ocfs_local_alloc_window_bits(osb)))
-		return(1);
-	return(0);
-}
-
-/*
- * ocfs_alloc_count_bits
- */
-static __u32 ocfs_alloc_count_bits(ocfs2_dinode *alloc)
-{
-	int i;
-	__u8 tmp;
-	__u8 *buffer;
-	__u32 count = 0;
-
-	LOG_ENTRY();
-
-	buffer = LOCAL_ALLOC(alloc)->la_bitmap;
-	for (i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++) {
-		memcpy(&tmp, buffer, 1);
-		count+= BITCOUNT(tmp);
-		buffer++;
-	}
-
-	LOG_EXIT_ULONG ((unsigned long)count);
-	return(count);
-} /* ocfs_alloc_count_bits */
-
-/*
- * ocfs_clear_local_alloc
- */
-static void ocfs_clear_local_alloc(ocfs2_dinode *alloc) 
-{
-	int i;
-	LOG_ENTRY();
-
-	LOCAL_ALLOC(alloc)->la_bm_bits = 0;
-	LOCAL_ALLOC(alloc)->la_bits_set = 0;
-	LOCAL_ALLOC(alloc)->la_bm_off = 0;
-	for(i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++)
-		LOCAL_ALLOC(alloc)->la_bitmap[i] = 0;
-
-	LOG_EXIT();
-	return;
-} /* ocfs_clear_local_alloc */
-
-/* 
- * ocfs_sync_local_to_main
- *
- * sync the local alloc to main bitmap. 
- *
- * assumes you've already locked the main bitmap -- the bitmap inode
- * passed is used for caching.
- */
-static int ocfs_sync_local_to_main(ocfs_super *osb, 
-				   ocfs_journal_handle *handle, 
-				   ocfs2_dinode *alloc,
-				   struct inode *main_bm_inode,
-				   struct buffer_head *main_bm_bh)
-{
-	int status = 0;
-	int bit_off, left;
-	void *bitmap;
-	unsigned int start, numblocks, bitmapblocks;
-	ocfs2_dinode *bm_fe;
-
-	LOG_ENTRY_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n", 
-		       LOCAL_ALLOC(alloc)->la_bm_bits,
-		       ocfs_alloc_count_bits(alloc), 
-		       LOCAL_ALLOC(alloc)->la_bits_set);
-
-	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
-		LOG_TRACE_STR("nothing to sync!");
-		goto bail;
-	}
-
-	bitmapblocks =
-		ocfs_blocks_for_bits(osb->sb,
- 				     osb->cluster_bitmap.validbits);
-
-	/* figure out which block in the bitmap to start on and the
-	 * maximum number of blocks we can span over -- we don't need
-	 * to read any more as that's the most we'll be touching... */
-	numblocks = ocfs_bitmap_blocks_affected(osb->sb,
-						LOCAL_ALLOC(alloc)->la_bm_off,
-						LOCAL_ALLOC(alloc)->la_bits_set,
-						&start);
-
-	if ((start + numblocks) > bitmapblocks) {
-		printk("uhoh, bitmap calculation is bad!\n");
-		printk("alloc->la_bm_bits = %u, COUNT = %u, alloc->la_bits_set = %u"
-		       "start=%u, alloc->la_bm_off = %u, numblocks=%u, "
-		       "bitmapblocks = %u\n",
-		       LOCAL_ALLOC(alloc)->la_bm_bits, ocfs_alloc_count_bits(alloc), 
-		       LOCAL_ALLOC(alloc)->la_bits_set, start, LOCAL_ALLOC(alloc)->la_bm_off, numblocks,
-		       bitmapblocks);
-
-		BUG();
-	}
-
-	bm_fe = (ocfs2_dinode *) main_bm_bh->b_data;
-	status = ocfs_journal_access(handle, main_bm_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	LOG_TRACE_ARGS("start=%u, alloc->la_bm_off = %u, numblocks=%u\n", start, 
-		       LOCAL_ALLOC(alloc)->la_bm_off, numblocks);
-	status = ocfs_read_bhs(osb,
-			       (osb->bitmap_blkno + start) << osb->sb->s_blocksize_bits,
-			       numblocks << osb->sb->s_blocksize_bits,
-			       &osb->cluster_bitmap.chunk[start], OCFS_BH_CACHED, 
-			       main_bm_inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-	/* any unset bits in local alloc need to be unset in bitmap. */
-	bit_off = 0;
-	left = LOCAL_ALLOC(alloc)->la_bm_bits;
-	while ((bit_off = find_next_zero_bit(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 + LOCAL_ALLOC(alloc)->la_bm_off);
-		ocfs_clear_bits(osb->sb, handle, &osb->cluster_bitmap, 
-				bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
-				1);
-		bm_fe->id1.bitmap1.i_used--;
-		bit_off++;
-	}
-
-	status = ocfs_journal_dirty(handle, main_bm_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-bail:
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-} /* ocfs_sync_local_to_main */
-
-/*
- * This essentially does the same thing as sync_local_to_main, but
- * without a journal handle -- used during shutdown and recovery.
- */
-static int ocfs_sync_local_from_shutdown(ocfs_super *osb, 
-					 ocfs_bitmap_free_head **f, 
-					 struct buffer_head *local_alloc_bh, 
-					 int in_recovery)
-{
-	int status = 0;
-	int bit_off, left;
-	ocfs2_dinode *alloc = NULL;
-	void *bitmap;
-
-	LOG_ENTRY();
-
-	if (!local_alloc_bh)
-		BUG();
-
-	alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
-	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
-		LOG_TRACE_STR("nothing to sync!");
-		goto bail;
-	}
-
-	if (!(*f)) {
-		*f = ocfs_alloc_bitmap_free_head();
-		if (*f == NULL) {
-			LOG_ERROR_STATUS(-ENOMEM);
-			goto bail;
-		}
-	}
-
-	alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
-
-	LOG_TRACE_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n", 
-		       LOCAL_ALLOC(alloc)->la_bm_bits,
-		       ocfs_alloc_count_bits(alloc), 
-		       LOCAL_ALLOC(alloc)->la_bits_set);
-
-	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-
-	/* any unset bits in local alloc need to be unset in bitmap. */
-	bit_off = 0;
-	left = LOCAL_ALLOC(alloc)->la_bm_bits;
-	while ((bit_off = find_next_zero_bit(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 + LOCAL_ALLOC(alloc)->la_bm_off,
-						 -1, 0, DISK_ALLOC_VOLUME);
-		if (status < 0) {
-			ocfs_free_bitmap_free_head(*f);
-			*f = NULL;
-		}
-		bit_off++;
-	}
-
-bail:
-	LOG_EXIT_STATUS(status);
-	return(status);
-} /* ocfs_sync_local_from_shutdown */
-
-/*
- * 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, 
-				 struct inode *bm_inode, 
-				 ocfs_journal_handle *handle)
-{
-	int status = 0;
-	__u64 alloc_bytes;
-	u32 cluster_off, cluster_count;
-	ocfs2_dinode *alloc = NULL;
-
-	LOG_ENTRY();
-
-	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-	if (LOCAL_ALLOC(alloc)->la_bm_bits != 0)
-		LOG_TRACE_STR("asking me to alloc a new window over a"
-			      " non-empty one");
-
-	/* we try to use find_contig_space_from_bitmap here for now. */
-	alloc_bytes = (u64)ocfs_local_alloc_window_bits(osb) << osb->s_clustersize_bits;
-	LOG_TRACE_ARGS("Allocating %llu bytes (%u clusters) for a "
-		       "new window.\n", alloc_bytes, 
-		       ocfs_local_alloc_window_bits(osb));
-
-	status = ocfs_find_contiguous_space_from_bitmap(osb, handle, 
-							alloc_bytes, 
-							&cluster_off, 
-							&cluster_count,
-							lock_bh, 
-							bm_inode);
-	if (status < 0) {
-		if (status != -ENOSPC)
-			LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-	atomic_inc(&osb->alloc_stats.bitmap_data);
-
-	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
-	LOCAL_ALLOC(alloc)->la_bm_off = cluster_off;
-	LOCAL_ALLOC(alloc)->la_bm_bits = 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
-	 * la_bits_set before setting the bits in the main bitmap. */
-	LOCAL_ALLOC(alloc)->la_bits_set = 0;
-	memset(LOCAL_ALLOC(alloc)->la_bitmap, 0,
-	       LOCAL_ALLOC(alloc)->la_size);
-
-	LOG_TRACE_STR("New window allocated:");
-	LOG_TRACE_ARGS("window la_bm_off = %u\n",
-		       LOCAL_ALLOC(alloc)->la_bm_off);
-	LOG_TRACE_ARGS("window la_bm_bits = %u\n",
-		       LOCAL_ALLOC(alloc)->la_bm_bits);
-
-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,
-				      ocfs2_dinode *alloc,
-				      __u32 numbits)
-{
-	int numfound, bitoff, left, startoff, lastzero;
-	void *bitmap = NULL;
-
-	LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
-
-	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
-		LOG_TRACE_STR("No bits in my window!");
-		bitoff = -1;
-		goto bail;
-	}
-
-	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-
-	numfound = bitoff = startoff = 0;
-	lastzero = -1;
-	left = LOCAL_ALLOC(alloc)->la_bm_bits;
-	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;
-
-bail:
-	LOG_EXIT_STATUS(bitoff);
-	return(bitoff);
-} /* ocfs_local_find_clear_bits */
-
-/* Note that we do *NOT* lock the local alloc inode here as
- * it's been locked already for us. */
-static int ocfs_local_alloc_full_window_change(ocfs_super *osb, 
-					       struct inode *local_alloc_inode)
-{
-	int status = 0;
-	struct buffer_head *main_bm_bh = NULL;
-	struct inode *main_bm_inode = NULL;
-	ocfs_journal_handle *handle = NULL;
-	ocfs2_dinode *alloc;
-	ocfs2_dinode *alloc_copy = NULL;
-
-	LOG_ENTRY();
-
-	main_bm_inode = ocfs_get_system_file_inode(osb, 
-						   GLOBAL_BITMAP_SYSTEM_INODE, 
-						   -1);
-	if (!main_bm_inode) {
-		status = -EINVAL;
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	handle = ocfs_alloc_handle(osb);
-	if (!handle) {
-		status = -ENOMEM;
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	/* Get the allocation lock here */
-	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, 
-				   0, &main_bm_bh, main_bm_inode);
-	if (status < 0) {
-		main_bm_bh = NULL;
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 
-			     0, main_bm_inode);
-	ocfs_handle_add_inode(handle, main_bm_inode);
-
-	handle = ocfs_start_trans(osb, handle, OCFS_WINDOW_MOVE_CREDITS);
-	if (!handle) {
-		status = -ENOMEM;
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-	ocfs_handle_set_always_commits(handle, 1);
-
-	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
-
-	/* We want to clear the local alloc before doing anything
-	 * else, so that if we error later during this operation,
-	 * local alloc shutdown won't try to double free main bitmap
-	 * bits. Make a copy so the sync function knows which bits to
-	 * free. */
-	alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);
-	if (!alloc_copy) {
-		status = -ENOMEM;
-		goto bail;
-	}
-	memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
-
-	status = ocfs_journal_access(handle, osb->local_alloc_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	ocfs_clear_local_alloc(alloc);
-
-	status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	status = ocfs_sync_local_to_main(osb, handle, alloc_copy, 
-					 main_bm_inode, main_bm_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	status = ocfs_alloc_new_window(osb, main_bm_bh, main_bm_inode, handle);
-	if (status < 0) {
-		if (status != -ENOSPC)
-			LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	atomic_inc(&osb->alloc_stats.moves);
-
-	status = 0;
-bail:
-	if (handle)
-		ocfs_commit_trans(handle);
-
-	if (main_bm_bh)
-		brelse(main_bm_bh);
-
-	if (main_bm_inode)
-		iput(main_bm_inode);
-
-	if (alloc_copy)
-		kfree(alloc_copy);
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
-/* 
- * ocfs_load_local_alloc 
- */
-int ocfs_load_local_alloc(ocfs_super *osb)
-{
-	int status = 0;
-	ocfs2_dinode *alloc = NULL;
-	struct buffer_head *alloc_bh = NULL;
-	__u32 num_used;
-	struct inode *inode = NULL;
-
-	LOG_ENTRY();
-
-	/* we don't enable local alloc on cluster sizes >= 128k */
-	if (osb->s_clustersize > OCFS_LOCAL_ALLOC_MAX_CSIZE)
-		goto bail;
-
-	/* read the alloc off disk */
-	inode = ocfs_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE, osb->node_num);
-	if (!inode) {
-		LOG_ERROR_STATUS(status=-EINVAL);
-		goto bail;
-	}
-	status = ocfs_read_bh(osb,
-			      OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
-			      &alloc_bh, 0, inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	alloc = (ocfs2_dinode *) alloc_bh->b_data;
-
-	/* do a little verification. */
-	num_used = ocfs_alloc_count_bits(alloc);
-
-	/* nowadays the local alloc has always been recovered before
-	 * we load it so there should be no bits used from the main
-	 * bitmap. */
-	if (num_used
-	    || LOCAL_ALLOC(alloc)->la_bits_set
-	    || LOCAL_ALLOC(alloc)->la_bm_bits 
-	    || LOCAL_ALLOC(alloc)->la_bm_off) {
-		LOG_ERROR_ARGS("Local alloc hasn't been recovered!\n"
-			       "found = %u, set = %u, taken = %u, off = %u\n",
-			       num_used,
-			       LOCAL_ALLOC(alloc)->la_bits_set, 
-			       LOCAL_ALLOC(alloc)->la_bm_bits,
-			       LOCAL_ALLOC(alloc)->la_bm_off);
-		status = -EFAIL;
-		goto bail;
-	}
-
-	if (!LOCAL_ALLOC(alloc)->la_size || 
-	    (LOCAL_ALLOC(alloc)->la_size > ocfs2_local_alloc_size(inode->i_sb))) {
-		LOG_ERROR_ARGS("Local alloc size is invalid (la_size = %u)\n",
-			      LOCAL_ALLOC(alloc)->la_size);
-		status = -EINVAL;
-		goto bail;
-	}
-
-	osb->local_alloc_bh = alloc_bh;
-	osb->have_local_alloc = 1;
-
-bail:
-	if (status < 0)
-		if (alloc_bh)
-			brelse(alloc_bh);
-	if (inode)
-		iput(inode);
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-} /* ocfs_load_local_alloc */
-
-/* 
- * 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)
-{
-	int status;
-	ocfs2_dinode *alloc = NULL;
-	ocfs_bitmap_free_head *f = NULL;
-	struct buffer_head *bh = NULL;
-	ocfs_journal_handle *handle = NULL;
-	struct inode *local_alloc_inode = NULL;
-	ocfs_inode_private *oip;
-
-	LOG_ENTRY();
-
-	local_alloc_inode = 
-		ocfs_get_system_file_inode(osb, 
-					   LOCAL_ALLOC_SYSTEM_INODE,
-					   osb->node_num);
-	if (!local_alloc_inode) {
-		status = -ENOENT;
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-	oip = OCFS_I(local_alloc_inode);
-
-	/* Take io_sem here to turn off local alloc before another guy
-	 * can come in and start using him. */
-	down_write(&oip->ip_io_sem);
-	if (!osb->have_local_alloc) {
-		up_write(&oip->ip_io_sem);
-		goto bail;
-	}
-	osb->have_local_alloc = 0;
-	up_write(&oip->ip_io_sem);
-
-	bh = osb->local_alloc_bh;
-
-	status = ocfs_sync_local_from_shutdown(osb, &f, bh, 0);
-	if (status < 0)
-		LOG_ERROR_STATUS(status);
-
-	handle = ocfs_start_trans(osb, NULL, 1);
-	if (!handle) {
-		LOG_ERROR_STATUS(-ENOMEM);
-		goto bail;
-	}
-	ocfs_handle_set_always_commits(handle, 1);
-
-	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	alloc = (ocfs2_dinode *) bh->b_data;
-	ocfs_clear_local_alloc(alloc);
-
-	status = ocfs_journal_dirty(handle, bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	brelse(bh);
-
-	ocfs_commit_trans(handle);
-	handle = NULL;
-
-	osb->local_alloc_bh = NULL;
-	osb->have_local_alloc = 0;
-
-	if (f)
-		ocfs_process_bitmap_free_head(osb, f);
-
-bail:
-	if (handle)
-		ocfs_commit_trans(handle);
-
-	if (f)
-		ocfs_free_bitmap_free_head(f);
-
-	if (local_alloc_inode)
-		iput(local_alloc_inode);
-
-	LOG_EXIT();
-	return;
-} /* ocfs_shutdown_local_alloc */
-
-/*
- * ocfs_recover_local_alloc
- *
- * We want to free the bitmap bits outside of any recovery context, so
- * it's allocated and passed back for you.
- */
-int ocfs_recover_local_alloc(ocfs_super *osb, 
-			     int node_num, 
-			     ocfs_bitmap_free_head **bits_to_free)
-{
-	int status = 0;
-	struct buffer_head *alloc_bh = NULL;
-	struct inode *inode = NULL;
-	ocfs2_dinode *alloc;
-
-	LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
-
-	inode = ocfs_get_system_file_inode(osb, 
-					   LOCAL_ALLOC_SYSTEM_INODE, 
-					   node_num);
-	if (!inode) {
-		LOG_ERROR_STATUS(status=-EINVAL);
-		goto bail;
-	}
-
-	status = ocfs_read_bh(osb,
-			      OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
-			      &alloc_bh, 
-			      0, inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	status = ocfs_sync_local_from_shutdown(osb, 
-					       bits_to_free, 
-					       alloc_bh, 
-					       1);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	alloc = (ocfs2_dinode *) alloc_bh->b_data;
-	ocfs_clear_local_alloc(alloc);
-
-	status = ocfs_write_bh(osb, alloc_bh, inode);
-	if (status < 0)
-		LOG_ERROR_STATUS(status);
-
-bail:
-	if (alloc_bh)
-		brelse(alloc_bh);
-
-	if (inode)
-		iput(inode);
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-} /* ocfs_recover_local_alloc */

Modified: branches/dlm-changes/src/journal.c
===================================================================
--- branches/dlm-changes/src/journal.c	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/journal.c	2004-10-01 22:07:13 UTC (rev 1538)
@@ -41,6 +41,7 @@
 #include "extmap.h"
 #include "inode.h"
 #include "journal.h"
+#include "localalloc.h"
 #include "lockres.h"
 #include "namei.h"
 #include "nm.h"

Added: branches/dlm-changes/src/localalloc.c
===================================================================
--- branches/dlm-changes/src/localalloc.c	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/localalloc.c	2004-10-01 22:07:13 UTC (rev 1538)
@@ -0,0 +1,1091 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.c
+ *
+ * Node local data allocation
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ *	    Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#define OCFS_DEBUG_CONTEXT    OCFS_DEBUG_CONTEXT_LOCALALLOC
+
+#include "ocfs_compat.h"
+
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+
+#include "ocfs_log.h"
+#include "ocfs.h"
+
+#include "alloc.h"
+#include "bitmap.h"
+#include "dlm.h"
+#include "extmap.h"
+#include "inode.h"
+#include "localalloc.h"
+#include "util.h"
+#include "suballoc.h"
+#include "sysfile.h"
+#include "file.h"
+
+#include "ocfs_journal.h"
+#include "buffer_head_io.h"
+
+/* 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)
+
+static inline int ocfs_local_alloc_window_bits(ocfs_super *osb);
+
+static __u32 ocfs_local_alloc_count_bits(ocfs2_dinode *alloc);
+
+static int ocfs_local_alloc_find_clear_bits(ocfs_super *osb,
+				      ocfs2_dinode *alloc,
+				      __u32 numbits);
+
+static void ocfs_clear_local_alloc(ocfs2_dinode *alloc);
+
+static int ocfs_local_alloc_new_window(ocfs_super *osb, 
+				 struct buffer_head *lock_bh,
+				 struct inode *bm_inode,
+				 ocfs_journal_handle *handle);
+
+static int ocfs_sync_local_from_shutdown(ocfs_super *osb, 
+					 ocfs_bitmap_free_head **f, 
+					 struct buffer_head *local_alloc_bh, 
+					 int in_recovery);
+
+static int ocfs_sync_local_to_main(ocfs_super *osb, 
+				   ocfs_journal_handle *handle, 
+				   ocfs2_dinode *alloc,
+				   struct inode *main_bm_inode,
+				   struct buffer_head *main_bm_bh);
+
+static int ocfs_local_alloc_slide_window(ocfs_super *osb, 
+					 struct inode * local_alloc_inode);
+
+static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
+					   ocfs_journal_handle *handle,
+					   __u64 file_size,
+					   u32 *cluster_off,
+					   u32 *cluster_count,
+					   struct buffer_head *bh,
+					   struct inode *bitmap_inode);
+
+/* 
+ * 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, 
+ * 32k -> 128 bits, 64k -> 64 bits
+ */
+static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
+{
+	int numbits;
+
+	switch (osb->s_clustersize) {
+	case (4*1024):
+		numbits = 1024;
+		break;
+
+	case (8*1024):
+		numbits = 512;
+		break;
+
+	case (16*1024):
+		numbits = 256;
+		break;
+
+	case (32*1024):
+		numbits = 128;
+		break;
+
+	default:
+		numbits = 64;
+		break;
+	}
+	return(numbits);
+} /* ocfs_local_alloc_window_bits */
+
+int ocfs_alloc_should_use_local(ocfs_super *osb, u64 bits)
+{
+	if (osb->have_local_alloc 
+	    && ((bits<<osb->s_clustersize_bits) <= OCFS_LOCAL_ALLOC_MAX_ALLOC)
+	    && (bits <= ocfs_local_alloc_window_bits(osb)))
+		return(1);
+	return(0);
+}
+
+/* 
+ * ocfs_load_local_alloc 
+ */
+int ocfs_load_local_alloc(ocfs_super *osb)
+{
+	int status = 0;
+	ocfs2_dinode *alloc = NULL;
+	struct buffer_head *alloc_bh = NULL;
+	__u32 num_used;
+	struct inode *inode = NULL;
+
+	LOG_ENTRY();
+
+	/* we don't enable local alloc on cluster sizes >= 128k */
+	if (osb->s_clustersize > OCFS_LOCAL_ALLOC_MAX_CSIZE)
+		goto bail;
+
+	/* read the alloc off disk */
+	inode = ocfs_get_system_file_inode(osb, LOCAL_ALLOC_SYSTEM_INODE, 
+					   osb->node_num);
+	if (!inode) {
+		LOG_ERROR_STATUS(status=-EINVAL);
+		goto bail;
+	}
+	status = ocfs_read_bh(osb,
+			      OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
+			      &alloc_bh, 0, inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	alloc = (ocfs2_dinode *) alloc_bh->b_data;
+
+	/* do a little verification. */
+	num_used = ocfs_local_alloc_count_bits(alloc);
+
+	/* nowadays the local alloc has always been recovered before
+	 * we load it so there should be no bits used from the main
+	 * bitmap. */
+	if (num_used
+	    || LOCAL_ALLOC(alloc)->la_bits_set
+	    || LOCAL_ALLOC(alloc)->la_bm_bits 
+	    || LOCAL_ALLOC(alloc)->la_bm_off) {
+		LOG_ERROR_ARGS("Local alloc hasn't been recovered!\n"
+			       "found = %u, set = %u, taken = %u, off = %u\n",
+			       num_used,
+			       LOCAL_ALLOC(alloc)->la_bits_set, 
+			       LOCAL_ALLOC(alloc)->la_bm_bits,
+			       LOCAL_ALLOC(alloc)->la_bm_off);
+		status = -EFAIL;
+		goto bail;
+	}
+
+	if (!LOCAL_ALLOC(alloc)->la_size || 
+	    (LOCAL_ALLOC(alloc)->la_size > ocfs2_local_alloc_size(inode->i_sb))) {
+		LOG_ERROR_ARGS("Local alloc size is invalid (la_size = %u)\n",
+			      LOCAL_ALLOC(alloc)->la_size);
+		status = -EINVAL;
+		goto bail;
+	}
+
+	osb->local_alloc_bh = alloc_bh;
+	osb->have_local_alloc = 1;
+
+bail:
+	if (status < 0)
+		if (alloc_bh)
+			brelse(alloc_bh);
+	if (inode)
+		iput(inode);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_load_local_alloc */
+
+/* 
+ * 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)
+{
+	int status;
+	ocfs2_dinode *alloc = NULL;
+	ocfs_bitmap_free_head *f = NULL;
+	struct buffer_head *bh = NULL;
+	ocfs_journal_handle *handle = NULL;
+	struct inode *local_alloc_inode = NULL;
+	ocfs_inode_private *oip;
+
+	LOG_ENTRY();
+
+	local_alloc_inode = 
+		ocfs_get_system_file_inode(osb, 
+					   LOCAL_ALLOC_SYSTEM_INODE,
+					   osb->node_num);
+	if (!local_alloc_inode) {
+		status = -ENOENT;
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	oip = OCFS_I(local_alloc_inode);
+
+	/* Take io_sem here to turn off local alloc before another guy
+	 * can come in and start using him. */
+	down_write(&oip->ip_io_sem);
+	if (!osb->have_local_alloc) {
+		up_write(&oip->ip_io_sem);
+		goto bail;
+	}
+	osb->have_local_alloc = 0;
+	up_write(&oip->ip_io_sem);
+
+	bh = osb->local_alloc_bh;
+
+	status = ocfs_sync_local_from_shutdown(osb, &f, bh, 0);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
+	handle = ocfs_start_trans(osb, NULL, 1);
+	if (!handle) {
+		LOG_ERROR_STATUS(-ENOMEM);
+		goto bail;
+	}
+	ocfs_handle_set_always_commits(handle, 1);
+
+	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	alloc = (ocfs2_dinode *) bh->b_data;
+	ocfs_clear_local_alloc(alloc);
+
+	status = ocfs_journal_dirty(handle, bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	brelse(bh);
+
+	ocfs_commit_trans(handle);
+	handle = NULL;
+
+	osb->local_alloc_bh = NULL;
+	osb->have_local_alloc = 0;
+
+	if (f)
+		ocfs_process_bitmap_free_head(osb, f);
+
+bail:
+	if (handle)
+		ocfs_commit_trans(handle);
+
+	if (f)
+		ocfs_free_bitmap_free_head(f);
+
+	if (local_alloc_inode)
+		iput(local_alloc_inode);
+
+	LOG_EXIT();
+	return;
+} /* ocfs_shutdown_local_alloc */
+
+/*
+ * ocfs_recover_local_alloc
+ *
+ * We want to free the bitmap bits outside of any recovery context, so
+ * it's allocated and passed back for you.
+ */
+int ocfs_recover_local_alloc(ocfs_super *osb, 
+			     int node_num, 
+			     ocfs_bitmap_free_head **bits_to_free)
+{
+	int status = 0;
+	struct buffer_head *alloc_bh = NULL;
+	struct inode *inode = NULL;
+	ocfs2_dinode *alloc;
+
+	LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
+
+	inode = ocfs_get_system_file_inode(osb, 
+					   LOCAL_ALLOC_SYSTEM_INODE, 
+					   node_num);
+	if (!inode) {
+		LOG_ERROR_STATUS(status=-EINVAL);
+		goto bail;
+	}
+
+	status = ocfs_read_bh(osb,
+			      OCFS_I(inode)->ip_blkno << inode->i_sb->s_blocksize_bits,
+			      &alloc_bh, 
+			      0, inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	status = ocfs_sync_local_from_shutdown(osb, 
+					       bits_to_free, 
+					       alloc_bh, 
+					       1);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	alloc = (ocfs2_dinode *) alloc_bh->b_data;
+	ocfs_clear_local_alloc(alloc);
+
+	status = ocfs_write_bh(osb, alloc_bh, inode);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
+bail:
+	if (alloc_bh)
+		brelse(alloc_bh);
+
+	if (inode)
+		iput(inode);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_recover_local_alloc */
+
+/* 
+ * ocfs_reserve_local_alloc_bits
+ *
+ * make sure we've got at least bitswanted contiguous bits in the
+ * local alloc. You lose them when you drop ip_io_sem.
+ * 
+ * We will add ourselves to the transaction passed in, but may start
+ * our own in order to shift windows.
+ *
+ * When we stop being lame and support multiple chunks of
+ * discontiguous space, we this turns into a really simple check of
+ * ->la_bits_set
+ */
+int ocfs_reserve_local_alloc_bits(ocfs_super *osb, 
+				  ocfs_journal_handle *passed_handle,
+				  u32 bits_wanted,
+				  ocfs2_alloc_context *ac)
+{
+	int status;
+	struct inode *local_alloc_inode = NULL;
+	int startoff;
+	ocfs2_dinode *alloc;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT(passed_handle);
+	OCFS_ASSERT(ac);
+	OCFS_ASSERT(!(passed_handle->flags & OCFS_HANDLE_STARTED));
+
+	local_alloc_inode = 
+		ocfs_get_system_file_inode(osb, 
+					   LOCAL_ALLOC_SYSTEM_INODE,
+					   osb->node_num);
+	if (!local_alloc_inode) {
+		status = -ENOENT;
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	ocfs_handle_add_inode(passed_handle, local_alloc_inode);
+
+	if (!osb->have_local_alloc) {
+		status = -ENOSPC;
+		goto bail;
+	}
+
+#warning "isn't it about time we turned this check off?"
+	if (bits_wanted > ocfs_clusters_for_bytes(osb->sb, 
+						 OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
+		LOG_TRACE_STR("Asking for more than max local alloction!\n");
+		status = -ENOSPC;
+		goto bail;
+	}
+
+	if (bits_wanted > ocfs_local_alloc_window_bits(osb)) {
+		LOG_TRACE_STR("Asking for more than my max window size!\n");
+		status = -ENOSPC;
+		goto bail;
+	}
+
+	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+	startoff = ocfs_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+	if (startoff == -1) {
+		/* uhoh, window change time. */
+		status = 
+			ocfs_local_alloc_slide_window(osb, local_alloc_inode);
+		if (status < 0) {
+			if (status != -ENOSPC)
+				LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+	}
+
+	ac->ac_inode = igrab(local_alloc_inode);
+	get_bh(osb->local_alloc_bh);
+	ac->ac_bh = osb->local_alloc_bh;
+
+	status = 0;
+bail:
+	if (local_alloc_inode)
+		iput(local_alloc_inode);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
+int ocfs_claim_local_alloc_bits(ocfs_super *osb,
+				ocfs_journal_handle *handle,
+				ocfs2_alloc_context *ac,
+				u32 min_bits,
+				u32 *bit_off,
+				u32 *num_bits)
+{
+	int status, start;
+	struct inode *local_alloc_inode;
+	u32 bits_wanted;
+	void *bitmap;
+	ocfs2_dinode *alloc;
+
+	LOG_ENTRY();
+	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL);
+
+	bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+	local_alloc_inode = ac->ac_inode;
+	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+	start = ocfs_local_alloc_find_clear_bits(osb, alloc, bits_wanted);
+	if (start == -1) {
+		/* TODO: Shouldn't we just BUG here? */
+		status = -ENOSPC;
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+	*bit_off = LOCAL_ALLOC(alloc)->la_bm_off + start;
+	/* local alloc is always contiguous by nature -- we never
+	 * delete bits from it! */
+	*num_bits = bits_wanted;
+
+	status = ocfs_journal_access(handle, osb->local_alloc_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	while(bits_wanted--)
+		set_bit(start++, bitmap);
+
+	status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	status = 0;
+bail:
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
+/*
+ * ocfs_local_alloc_count_bits
+ */
+static __u32 ocfs_local_alloc_count_bits(ocfs2_dinode *alloc)
+{
+	int i;
+	__u8 tmp;
+	__u8 *buffer;
+	__u32 count = 0;
+
+	LOG_ENTRY();
+
+	buffer = LOCAL_ALLOC(alloc)->la_bitmap;
+	for (i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++) {
+		memcpy(&tmp, buffer, 1);
+		count+= BITCOUNT(tmp);
+		buffer++;
+	}
+
+	LOG_EXIT_ULONG ((unsigned long)count);
+	return(count);
+} /* ocfs_local_alloc_count_bits */
+
+/*
+ * ocfs_local_alloc_find_clear_bits
+ */
+static int ocfs_local_alloc_find_clear_bits(ocfs_super *osb,
+					    ocfs2_dinode *alloc,
+					    __u32 numbits)
+{
+	int numfound, bitoff, left, startoff, lastzero;
+	void *bitmap = NULL;
+
+	LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
+
+	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+		LOG_TRACE_STR("No bits in my window!");
+		bitoff = -1;
+		goto bail;
+	}
+
+	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+
+	numfound = bitoff = startoff = 0;
+	lastzero = -1;
+	left = LOCAL_ALLOC(alloc)->la_bm_bits;
+	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;
+
+bail:
+	LOG_EXIT_STATUS(bitoff);
+	return(bitoff);
+} /* ocfs_local_find_alloc_clear_bits */
+
+/*
+ * ocfs_clear_local_alloc
+ */
+static void ocfs_clear_local_alloc(ocfs2_dinode *alloc) 
+{
+	int i;
+	LOG_ENTRY();
+
+	LOCAL_ALLOC(alloc)->la_bm_bits = 0;
+	LOCAL_ALLOC(alloc)->la_bits_set = 0;
+	LOCAL_ALLOC(alloc)->la_bm_off = 0;
+	for(i = 0; i < LOCAL_ALLOC(alloc)->la_size; i++)
+		LOCAL_ALLOC(alloc)->la_bitmap[i] = 0;
+
+	LOG_EXIT();
+	return;
+} /* ocfs_clear_local_alloc */
+
+/*
+ * ocfs_local_alloc_new_window
+ *
+ * pass it the bitmap lock in lock_bh if you have it. 
+ */
+static int ocfs_local_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh, 
+				 struct inode *bm_inode, 
+				 ocfs_journal_handle *handle)
+{
+	int status = 0;
+	__u64 alloc_bytes;
+	u32 cluster_off, cluster_count;
+	ocfs2_dinode *alloc = NULL;
+
+	LOG_ENTRY();
+
+	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+	if (LOCAL_ALLOC(alloc)->la_bm_bits != 0)
+		LOG_TRACE_STR("asking me to alloc a new window over a"
+			      " non-empty one");
+
+	/* we try to use find_contig_space_from_bitmap here for now. */
+	alloc_bytes = (u64)ocfs_local_alloc_window_bits(osb) << osb->s_clustersize_bits;
+	LOG_TRACE_ARGS("Allocating %llu bytes (%u clusters) for a "
+		       "new window.\n", alloc_bytes, 
+		       ocfs_local_alloc_window_bits(osb));
+
+	status = ocfs_find_contiguous_space_from_bitmap(osb, handle, 
+							alloc_bytes, 
+							&cluster_off, 
+							&cluster_count,
+							lock_bh, 
+							bm_inode);
+	if (status < 0) {
+		if (status != -ENOSPC)
+			LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	atomic_inc(&osb->alloc_stats.bitmap_data);
+
+	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+	LOCAL_ALLOC(alloc)->la_bm_off = cluster_off;
+	LOCAL_ALLOC(alloc)->la_bm_bits = 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
+	 * la_bits_set before setting the bits in the main bitmap. */
+	LOCAL_ALLOC(alloc)->la_bits_set = 0;
+	memset(LOCAL_ALLOC(alloc)->la_bitmap, 0,
+	       LOCAL_ALLOC(alloc)->la_size);
+
+	LOG_TRACE_STR("New window allocated:");
+	LOG_TRACE_ARGS("window la_bm_off = %u\n",
+		       LOCAL_ALLOC(alloc)->la_bm_off);
+	LOG_TRACE_ARGS("window la_bm_bits = %u\n",
+		       LOCAL_ALLOC(alloc)->la_bm_bits);
+
+bail:
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_local_alloc_new_window */
+
+/*
+ * This essentially does the same thing as sync_local_to_main, but
+ * without a journal handle -- used during shutdown and recovery.
+ */
+static int ocfs_sync_local_from_shutdown(ocfs_super *osb, 
+					 ocfs_bitmap_free_head **f, 
+					 struct buffer_head *local_alloc_bh, 
+					 int in_recovery)
+{
+	int status = 0;
+	int bit_off, left;
+	ocfs2_dinode *alloc = NULL;
+	void *bitmap;
+
+	LOG_ENTRY();
+
+	if (!local_alloc_bh)
+		BUG();
+
+	alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
+	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+		LOG_TRACE_STR("nothing to sync!");
+		goto bail;
+	}
+
+	if (!(*f)) {
+		*f = ocfs_alloc_bitmap_free_head();
+		if (*f == NULL) {
+			LOG_ERROR_STATUS(-ENOMEM);
+			goto bail;
+		}
+	}
+
+	alloc = (ocfs2_dinode *) local_alloc_bh->b_data;
+
+	LOG_TRACE_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n", 
+		       LOCAL_ALLOC(alloc)->la_bm_bits,
+		       ocfs_local_alloc_count_bits(alloc), 
+		       LOCAL_ALLOC(alloc)->la_bits_set);
+
+	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+
+	/* any unset bits in local alloc need to be unset in bitmap. */
+	bit_off = 0;
+	left = LOCAL_ALLOC(alloc)->la_bm_bits;
+	while ((bit_off = find_next_zero_bit(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 + LOCAL_ALLOC(alloc)->la_bm_off,
+						 -1, 0, DISK_ALLOC_VOLUME);
+		if (status < 0) {
+			ocfs_free_bitmap_free_head(*f);
+			*f = NULL;
+		}
+		bit_off++;
+	}
+
+bail:
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_sync_local_from_shutdown */
+
+/* 
+ * ocfs_sync_local_to_main
+ *
+ * sync the local alloc to main bitmap. 
+ *
+ * assumes you've already locked the main bitmap -- the bitmap inode
+ * passed is used for caching.
+ */
+static int ocfs_sync_local_to_main(ocfs_super *osb, 
+				   ocfs_journal_handle *handle, 
+				   ocfs2_dinode *alloc,
+				   struct inode *main_bm_inode,
+				   struct buffer_head *main_bm_bh)
+{
+	int status = 0;
+	int bit_off, left;
+	void *bitmap;
+	unsigned int start, numblocks, bitmapblocks;
+	ocfs2_dinode *bm_fe;
+
+	LOG_ENTRY_ARGS("alloc->la_bm_bits = %u, COUNT = %u, la_bits_set = %u\n", 
+		       LOCAL_ALLOC(alloc)->la_bm_bits,
+		       ocfs_local_alloc_count_bits(alloc), 
+		       LOCAL_ALLOC(alloc)->la_bits_set);
+
+	if (LOCAL_ALLOC(alloc)->la_bm_bits == 0) {
+		LOG_TRACE_STR("nothing to sync!");
+		goto bail;
+	}
+
+	bitmapblocks =
+		ocfs_blocks_for_bits(osb->sb,
+ 				     osb->cluster_bitmap.validbits);
+
+	/* figure out which block in the bitmap to start on and the
+	 * maximum number of blocks we can span over -- we don't need
+	 * to read any more as that's the most we'll be touching... */
+	numblocks = ocfs_bitmap_blocks_affected(osb->sb,
+						LOCAL_ALLOC(alloc)->la_bm_off,
+						LOCAL_ALLOC(alloc)->la_bits_set,
+						&start);
+
+	if ((start + numblocks) > bitmapblocks) {
+		printk("uhoh, bitmap calculation is bad!\n");
+		printk("alloc->la_bm_bits = %u, COUNT = %u, alloc->la_bits_set = %u"
+		       "start=%u, alloc->la_bm_off = %u, numblocks=%u, "
+		       "bitmapblocks = %u\n",
+		       LOCAL_ALLOC(alloc)->la_bm_bits, ocfs_local_alloc_count_bits(alloc), 
+		       LOCAL_ALLOC(alloc)->la_bits_set, start, LOCAL_ALLOC(alloc)->la_bm_off, numblocks,
+		       bitmapblocks);
+
+		BUG();
+	}
+
+	bm_fe = (ocfs2_dinode *) main_bm_bh->b_data;
+	status = ocfs_journal_access(handle, main_bm_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	LOG_TRACE_ARGS("start=%u, alloc->la_bm_off = %u, numblocks=%u\n", start, 
+		       LOCAL_ALLOC(alloc)->la_bm_off, numblocks);
+	status = ocfs_read_bhs(osb,
+			       (osb->bitmap_blkno + start) << osb->sb->s_blocksize_bits,
+			       numblocks << osb->sb->s_blocksize_bits,
+			       &osb->cluster_bitmap.chunk[start], OCFS_BH_CACHED, 
+			       main_bm_inode);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
+	/* any unset bits in local alloc need to be unset in bitmap. */
+	bit_off = 0;
+	left = LOCAL_ALLOC(alloc)->la_bm_bits;
+	while ((bit_off = find_next_zero_bit(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 + LOCAL_ALLOC(alloc)->la_bm_off);
+		ocfs_clear_bits(osb->sb, handle, &osb->cluster_bitmap, 
+				bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
+				1);
+		bm_fe->id1.bitmap1.i_used--;
+		bit_off++;
+	}
+
+	status = ocfs_journal_dirty(handle, main_bm_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+bail:
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+} /* ocfs_sync_local_to_main */
+
+/* Note that we do *NOT* lock the local alloc inode here as
+ * it's been locked already for us. */
+static int ocfs_local_alloc_slide_window(ocfs_super *osb, 
+					 struct inode *local_alloc_inode)
+{
+	int status = 0;
+	struct buffer_head *main_bm_bh = NULL;
+	struct inode *main_bm_inode = NULL;
+	ocfs_journal_handle *handle = NULL;
+	ocfs2_dinode *alloc;
+	ocfs2_dinode *alloc_copy = NULL;
+
+	LOG_ENTRY();
+
+	main_bm_inode = ocfs_get_system_file_inode(osb, 
+						   GLOBAL_BITMAP_SYSTEM_INODE, 
+						   -1);
+	if (!main_bm_inode) {
+		status = -EINVAL;
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	handle = ocfs_alloc_handle(osb);
+	if (!handle) {
+		status = -ENOMEM;
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+
+	/* Get the allocation lock here */
+	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, 
+				   0, &main_bm_bh, main_bm_inode);
+	if (status < 0) {
+		main_bm_bh = NULL;
+		if (status != -EINTR)
+			LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 
+			     0, main_bm_inode);
+	ocfs_handle_add_inode(handle, main_bm_inode);
+
+	handle = ocfs_start_trans(osb, handle, OCFS_WINDOW_MOVE_CREDITS);
+	if (!handle) {
+		status = -ENOMEM;
+		LOG_ERROR_STATUS (status);
+		goto bail;
+	}
+	ocfs_handle_set_always_commits(handle, 1);
+
+	alloc = (ocfs2_dinode *) osb->local_alloc_bh->b_data;
+
+	/* We want to clear the local alloc before doing anything
+	 * else, so that if we error later during this operation,
+	 * local alloc shutdown won't try to double free main bitmap
+	 * bits. Make a copy so the sync function knows which bits to
+	 * free. */
+	alloc_copy = kmalloc(osb->local_alloc_bh->b_size, GFP_KERNEL);
+	if (!alloc_copy) {
+		status = -ENOMEM;
+		goto bail;
+	}
+	memcpy(alloc_copy, alloc, osb->local_alloc_bh->b_size);
+
+	status = ocfs_journal_access(handle, osb->local_alloc_bh, 
+				     OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	ocfs_clear_local_alloc(alloc);
+
+	status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	status = ocfs_sync_local_to_main(osb, handle, alloc_copy, 
+					 main_bm_inode, main_bm_bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	status = ocfs_local_alloc_new_window(osb, main_bm_bh, main_bm_inode, 
+					     handle);
+	if (status < 0) {
+		if (status != -ENOSPC)
+			LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	atomic_inc(&osb->alloc_stats.moves);
+
+	status = 0;
+bail:
+	if (handle)
+		ocfs_commit_trans(handle);
+
+	if (main_bm_bh)
+		brelse(main_bm_bh);
+
+	if (main_bm_inode)
+		iput(main_bm_inode);
+
+	if (alloc_copy)
+		kfree(alloc_copy);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
+/*
+ * ocfs_find_contiguous_space_from_bitmap()
+ *
+ * Used only from local alloc right now. Eventually will go away, so
+ * don't add more callers to this function. Use the reserve / claim
+ * apis instead as they'll even get you distcongiuous areas.
+ *
+ * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
+ * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
+ *
+ * Returns 0 on success, < 0 on error.
+ */
+static int ocfs_find_contiguous_space_from_bitmap(ocfs_super *osb,
+					   ocfs_journal_handle *handle,
+					   __u64 file_size,
+					   u32 *cluster_off,
+					   u32 *cluster_count,
+					   struct buffer_head *bh,
+					   struct inode *bitmap_inode)
+{
+	int status = 0, startbh, numblocks;
+	u32 bitoffset = 0, num_clusters = 0;
+	ocfs2_dinode *bm_lock;
+	__u32 bitmapblocks; /* we only care about the valid blocks */
+	__u32 free_bits;
+
+	LOG_ENTRY ();
+
+	OCFS_ASSERT(osb);
+	OCFS_ASSERT(bh);
+	OCFS_ASSERT(bitmap_inode);
+	OCFS_ASSERT(handle);
+
+	status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto leave;
+	}
+
+	bm_lock = (ocfs2_dinode *) bh->b_data;
+
+	num_clusters = (u32) ((u64) (file_size + (osb->s_clustersize-1)) >> 
+				osb->s_clustersize_bits);
+	if (num_clusters == 0) {
+		LOG_ERROR_STR ("DISK_FULL?: num_clusters==0");
+		status = 0;
+		goto leave;
+	}
+
+	free_bits = le32_to_cpu(bm_lock->id1.bitmap1.i_total) - 
+		le32_to_cpu(bm_lock->id1.bitmap1.i_used);
+
+	if (num_clusters > free_bits) {
+		LOG_ERROR_ARGS("Disk Full: num_clusters=%u, free_bits=%u\n",
+			       num_clusters, free_bits);
+		status = -ENOSPC;
+		goto leave;
+	}
+
+	bitmapblocks =
+		ocfs_blocks_for_bits(osb->sb,
+ 				     osb->cluster_bitmap.validbits);
+
+	/* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
+	if (ocfs_read_bhs(osb, osb->bitmap_blkno << osb->sb->s_blocksize_bits, 
+			  bitmapblocks << osb->sb->s_blocksize_bits,
+			  osb->cluster_bitmap.chunk, OCFS_BH_CACHED, bitmap_inode)) {
+		LOG_ERROR_STATUS(-EIO);
+		goto leave;
+	}
+
+	status = 0;
+	status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap, 
+				       num_clusters, &bitoffset, 
+				       NULL);
+	if (status < 0) {
+		osb->cluster_bitmap.failed++;
+		LOG_TRACE_ARGS("Cannot allocate %u contiguous clusters "
+			       "for system file\n", num_clusters);
+		status = -ENOSPC;
+		goto leave;
+	}
+
+	LOG_TRACE_ARGS ("setting %u bits at bit offset=%u\n", 
+			num_clusters, bitoffset);
+
+	ocfs_set_bits(osb->sb, handle, &osb->cluster_bitmap, bitoffset,
+		      num_clusters);
+
+	/* 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. */
+	numblocks = ocfs_bitmap_blocks_affected(osb->sb,
+						bitoffset,
+						num_clusters,
+						&startbh);
+
+	LOG_TRACE_ARGS("bitoffset = %u, num_clusters = %u, startbh = %u, numblocks = %u\n", bitoffset, num_clusters, startbh, numblocks);
+
+	/* write the bitmap size info to the lock sector */
+	bm_lock->id1.bitmap1.i_used =
+		ocfs_count_bits(osb->sb, &osb->cluster_bitmap);
+
+	status = ocfs_journal_dirty(handle, bh);
+	if (status < 0) {
+		LOG_ERROR_STATUS (status);
+		goto leave;
+	}
+
+	*cluster_off = bitoffset;
+	*cluster_count = num_clusters;
+	status = 0;
+
+leave:
+	LOG_EXIT_STATUS (status);
+	return status;
+}				/* ocfs_find_contiguous_space_from_bitmap */
+

Added: branches/dlm-changes/src/localalloc.h
===================================================================
--- branches/dlm-changes/src/localalloc.h	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/localalloc.h	2004-10-01 22:07:13 UTC (rev 1538)
@@ -0,0 +1,55 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * localalloc.h
+ *
+ * Function prototypes
+ *
+ * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ *
+ * Authors: Kurt Hackel, Mark Fasheh, Sunil Mushran, Wim Coekaerts,
+ *	    Manish Singh, Neeraj Goyal, Suchit Kaura
+ */
+
+#ifndef OCFS2_LOCALALLOC_H
+#define OCFS2_LOCALALLOC_H
+
+int ocfs_load_local_alloc(ocfs_super *osb);
+
+void ocfs_shutdown_local_alloc(ocfs_super *osb);
+
+int ocfs_recover_local_alloc(ocfs_super *osb, 
+			     int node_num, 
+			     ocfs_bitmap_free_head **bits_to_free);
+
+int ocfs_alloc_should_use_local(ocfs_super *osb, 
+				u64 bits);
+
+int ocfs_reserve_local_alloc_bits(ocfs_super *osb, 
+				  ocfs_journal_handle *passed_handle,
+				  u32 bits_wanted,
+				  ocfs2_alloc_context *ac);
+
+int ocfs_claim_local_alloc_bits(ocfs_super *osb,
+				ocfs_journal_handle *handle,
+				ocfs2_alloc_context *ac,
+				u32 min_bits,
+				u32 *bit_off,
+				u32 *num_bits);
+
+#endif /* OCFS2_LOCALALLOC_H */

Modified: branches/dlm-changes/src/ocfs_log.h
===================================================================
--- branches/dlm-changes/src/ocfs_log.h	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/ocfs_log.h	2004-10-01 22:07:13 UTC (rev 1538)
@@ -113,7 +113,7 @@
 #define OCFS_DEBUG_CONTEXT_INODE       0x00000400	/* inode.c    */
 #define OCFS_DEBUG_CONTEXT_JOURNAL     0x00000800	/* journal.c  */
 #define OCFS_DEBUG_CONTEXT_CHAINALLOC  0x00001000	/*            */
-#define OCFS_DEBUG_CONTEXT_UNUSED2     0x00002000	/*            */
+#define OCFS_DEBUG_CONTEXT_LOCALALLOC  0x00002000	/*            */
 #define OCFS_DEBUG_CONTEXT_SYSFILE     0x00004000	/* sysfile.c  */
 #define OCFS_DEBUG_CONTEXT_VOLCFG      0x00008000	/* volcfg.c   */
 #define OCFS_DEBUG_CONTEXT_DCACHE      0x00010000	/* dcache.c   */

Modified: branches/dlm-changes/src/super.c
===================================================================
--- branches/dlm-changes/src/super.c	2004-10-01 21:12:52 UTC (rev 1537)
+++ branches/dlm-changes/src/super.c	2004-10-01 22:07:13 UTC (rev 1538)
@@ -56,6 +56,7 @@
 #include "heartbeat.h"
 #include "inode.h"
 #include "journal.h"
+#include "localalloc.h"
 #include "nm.h"
 #include "proc.h"
 #include "super.h"



More information about the Ocfs2-commits mailing list