[Ocfs2-commits] mfasheh commits r1624 - branches/cluster-groups/src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Nov 4 16:14:38 CST 2004


Author: mfasheh
Date: 2004-11-04 16:14:37 -0600 (Thu, 04 Nov 2004)
New Revision: 1624

Removed:
   branches/cluster-groups/src/bitmap.c
   branches/cluster-groups/src/bitmap.h
Modified:
   branches/cluster-groups/src/Makefile
   branches/cluster-groups/src/alloc.c
   branches/cluster-groups/src/alloc.h
   branches/cluster-groups/src/dir.c
   branches/cluster-groups/src/dir.h
   branches/cluster-groups/src/file.c
   branches/cluster-groups/src/file.h
   branches/cluster-groups/src/inode.c
   branches/cluster-groups/src/localalloc.c
   branches/cluster-groups/src/localalloc.h
   branches/cluster-groups/src/namei.c
   branches/cluster-groups/src/ocfs.h
   branches/cluster-groups/src/ocfs2_fs.h
   branches/cluster-groups/src/proc.c
   branches/cluster-groups/src/suballoc.c
   branches/cluster-groups/src/suballoc.h
   branches/cluster-groups/src/super.c
Log:
* first cut at this stuff. The search needs to be fixed to not fail
  easily. I haven't tested this on a live file system yet.



Modified: branches/cluster-groups/src/Makefile
===================================================================
--- branches/cluster-groups/src/Makefile	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/Makefile	2004-11-04 22:14:37 UTC (rev 1624)
@@ -66,7 +66,6 @@
 	24io.c			\
 	alloc.c			\
 	aops.c			\
-	bitmap.c		\
 	buffer_head_io.c	\
 	dcache.c		\
 	dir.c			\
@@ -101,7 +100,6 @@
 	ocfs_journal.h		\
 	buffer_head_io.h	\
 	alloc.h			\
-	bitmap.h		\
 	dcache.h		\
 	dir.h			\
 	dlm.h			\

Modified: branches/cluster-groups/src/alloc.c
===================================================================
--- branches/cluster-groups/src/alloc.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/alloc.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -35,7 +35,6 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
-#include "bitmap.h"
 #include "dlm.h"
 #include "extent_map.h"
 #include "inode.h"
@@ -54,13 +53,6 @@
 static int ocfs_extent_contig(struct inode *inode, ocfs2_extent_rec *ext,
 			      u64 blkno);
 
-static int ocfs_free_clusters(ocfs_super *osb,
-			      ocfs_journal_handle *handle,
-			      struct inode *bitmap_inode,
-			      struct buffer_head *bitmap_bh,
-			      u64 start_blk,
-			      unsigned int num_clusters);
-
 static int ocfs_create_new_meta_bhs(ocfs_super *osb, 
 				    ocfs_journal_handle *handle,
 				    struct inode *inode,
@@ -95,13 +87,6 @@
 				    struct buffer_head *fe_bh,
 				    struct buffer_head **target_bh);
 
-static int ocfs_claim_main_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_find_new_last_ext_blk(ocfs_super *osb,
 				      struct inode *inode,
 				      ocfs2_dinode *fe,
@@ -124,66 +109,6 @@
 						  ext->e_clusters));
 }
 
-static int ocfs_free_clusters(ocfs_super *osb,
-			      ocfs_journal_handle *handle,
-			      struct inode *bitmap_inode,
-			      struct buffer_head *bitmap_bh,
-			      u64 start_blk,
-			      unsigned int num_clusters)
-{
-	ocfs_alloc_bm *bitmap;
-	int status;
-	unsigned int start_cluster, bitmap_blocks, bitmap_start;
-	ocfs2_dinode *fe;
-
-	LOG_ENTRY();
-
-	start_cluster = ocfs2_blocks_to_clusters(osb->sb, start_blk);
-
-	bitmap = &osb->cluster_bitmap;
-
-	bitmap_blocks = ocfs_bitmap_blocks_affected(osb->sb,
-						    start_cluster,
-						    num_clusters,
-						    &bitmap_start);
-
-	LOG_TRACE_ARGS("want to free %u clusters starting at block %llu\n", 
-		       num_clusters, start_blk);
-	LOG_TRACE_ARGS("bitmap_start = %u, bitmap_blkno = %llu, bitmap_blocks "
-		       "= %u\n", bitmap_start, osb->bitmap_blkno, 
-		       bitmap_blocks);
-	status = ocfs_read_blocks(osb, (osb->bitmap_blkno + bitmap_start), 
-				  bitmap_blocks, &bitmap->chunk[bitmap_start], 
-				  OCFS_BH_CACHED, bitmap_inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	status = ocfs_journal_access(handle, bitmap_inode, bitmap_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-	fe = (ocfs2_dinode *) bitmap_bh->b_data;
-
-	ocfs_clear_bits(osb->sb, handle, bitmap_inode, bitmap, start_cluster, 
-			num_clusters);
-	fe->id1.bitmap1.i_used -= num_clusters;
-
-	status = ocfs_journal_dirty(handle, bitmap_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	status = 0;
-bail:
-	LOG_EXIT_STATUS(status);
-	return(0);
-}
-
 /*
  * How many free extents have we got before we need more meta data?
  */
@@ -941,287 +866,6 @@
 	return status;
 }
 
-void ocfs_free_alloc_context(ocfs2_alloc_context *ac)
-{
-	if (ac->ac_inode)
-		iput(ac->ac_inode);
-	if (ac->ac_bh)
-		brelse(ac->ac_bh);
-	kfree(ac);
-}
-
-/*
- * min_bits - minimum contiguous chunk from this total allocation we
- * can handle. set to what we asked for originally for a full
- * contig. allocation, set to '1' to indicate we can deal with extents
- * of any size.
- */
-int ocfs_claim_bits(ocfs_super *osb, 
-		    ocfs_journal_handle *handle, 
-		    ocfs2_alloc_context *ac,
-		    u32 min_bits,
-		    u32 *bit_off,
-		    u32 *num_bits)
-{
-	int status;
-
-	LOG_ENTRY();
-
-	OCFS_ASSERT(ac);
-	OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
-
-	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL 
-		    || ac->ac_which == OCFS_AC_USE_MAIN);
-	OCFS_ASSERT(ac->ac_handle == handle);
-
-	if (ac->ac_which == OCFS_AC_USE_LOCAL) {
-		status = ocfs_claim_local_alloc_bits(osb, 
-						     handle, 
-						     ac, 
-						     min_bits,
-						     bit_off, 
-						     num_bits);
-	} else {
-		status = ocfs_claim_main_bitmap_bits(osb, 
-						     handle, 
-						     ac,
-						     min_bits,
-						     bit_off,
-						     num_bits);
-	}
-	if (status < 0) {
-		/* If you're not asking for contiguous blocks, then
-		 * the reserve function should've given you enough,
-		 * and ENOSPC this is a real error. */
-		if ((status != -ENOSPC) || (min_bits == 1))
-			LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	ac->ac_bits_given += *num_bits;
-
-bail:
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
-static int ocfs_claim_main_bitmap_bits(ocfs_super *osb,
-				       ocfs_journal_handle *handle,
-				       ocfs2_alloc_context *ac,
-				       u32 min_bits,
-				       u32 *bit_off,
-				       u32 *num_bits)
-{
-	int status, num_blocks;
-	u32 bits_wanted;
-	u32 best_fit_bits;
-	ocfs2_dinode *fe;
-	struct inode *bitmap_inode;
-	struct buffer_head *bh;
-
-	LOG_ENTRY();
-	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_MAIN);
-
-	bitmap_inode = ac->ac_inode;
-	bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
-	bh = ac->ac_bh;
-	fe = (ocfs2_dinode *) bh->b_data;
-
-	num_blocks = ocfs_blocks_for_bits(osb->sb,
-					  osb->cluster_bitmap.validbits);
-	/* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
-	status = ocfs_read_blocks(osb, osb->bitmap_blkno, num_blocks, 
-			       osb->cluster_bitmap.chunk, OCFS_BH_CACHED, 
-			       bitmap_inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	best_fit_bits = bits_wanted;
-	status = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
-				       bits_wanted, bit_off, 
-				       &best_fit_bits);
-	if (status < 0) {
-		osb->cluster_bitmap.failed++;
-		LOG_TRACE_STR("Running out of space!");
-		goto bail;
-	}
-
-	if (best_fit_bits < min_bits) {
-		LOG_TRACE_ARGS ("Cannot allocate %u contiguous clusters for "
-				"system file\n", min_bits);
-		status = -ENOSPC;
-		goto bail;
-	}
-
-	if (best_fit_bits != bits_wanted)
-		LOG_TRACE_ARGS("discontiguous allocation done: wanted = %u, "
-			       "best_fit = %u, bit_off = %u!\n", 
-			       bits_wanted, best_fit_bits, *bit_off);
-
-	/* when we do discontig. just change this line. */
-	*num_bits = best_fit_bits;
-
-	/* cool, we've got some. set them now. */
-	status = ocfs_journal_access(handle, bitmap_inode, bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	fe->id1.bitmap1.i_used += *num_bits;
-
-	status = ocfs_journal_dirty(handle, bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-
-	ocfs_set_bits(osb->sb, handle, bitmap_inode, &osb->cluster_bitmap, 
-		      *bit_off, *num_bits);
-	atomic_inc(&osb->alloc_stats.bitmap_data);
-
-#warning "implement this"
-	/* At this point, we should see if local alloc was switched
-	 * off, and turn it back on if we have enough free bits in the
-	 * main bitmap.*/
-	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,
-		      u32 bits_wanted,
-		      ocfs2_alloc_context **ac)
-{
-	int status;
-
-	LOG_ENTRY();
-	OCFS_ASSERT(handle);
-
-	*ac = kmalloc(sizeof(ocfs2_alloc_context), GFP_KERNEL);
-	if (!(*ac)) {
-		status = -ENOMEM;
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-	memset(*ac, 0, sizeof(ocfs2_alloc_context));
-	(*ac)->ac_bits_wanted = bits_wanted;
-	(*ac)->ac_handle = handle;
-
-	status = -ENOSPC;
-	if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
-		status = ocfs_reserve_local_alloc_bits(osb, 
-						       handle, 
-						       bits_wanted, 
-						       *ac);
-		if ((status < 0) && (status != -ENOSPC)) {
-			LOG_ERROR_STATUS(status);
-			goto bail;
-		} else if (status == -ENOSPC) {
-#warning "need to deal with disabling local alloc better"
-			/* reserve_local_bits will return enospc with
-			 * the local alloc inode still locked, so we
-			 * can change this safely here. */
-			LOG_ERROR_STR("Disabling local alloc");
-			osb->have_local_alloc = 0;
-//			ocfs_shutdown_local_alloc(osb);
-		} else 
-			(*ac)->ac_which = OCFS_AC_USE_LOCAL;
-	}
-
-	if (status == -ENOSPC) {
-		status = ocfs_reserve_main_bitmap_bits(osb, 
-						       handle, 
-						       bits_wanted,
-						       *ac);
-		if (status < 0) {
-			LOG_ERROR_STATUS(status);
-			goto bail;
-		}
-		(*ac)->ac_which = OCFS_AC_USE_MAIN;
-	}
-
-	status = 0;
-bail:
-	if ((status < 0) && *ac) {
-		ocfs_free_alloc_context(*ac);
-		*ac = NULL;
-	}
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
-int ocfs_reserve_main_bitmap_bits(ocfs_super *osb, 
-				  ocfs_journal_handle *handle,
-				  u32 bits_wanted,
-				  ocfs2_alloc_context *ac)
-{
-	int status = 0;
-	struct inode *bitmap_inode;
-	struct buffer_head *bh = NULL;
-	ocfs2_dinode *fe;
-	u32 free_bits;
-
-	LOG_ENTRY();
-
-	OCFS_ASSERT(!(handle->flags & OCFS_HANDLE_STARTED));
-
-	bitmap_inode = ocfs_get_system_file_inode(osb, 
-						  GLOBAL_BITMAP_SYSTEM_INODE, 
-						  -1);
-	if (!bitmap_inode) {
-		status = -EINVAL;
-		LOG_ERROR_STR("Could not get bitmap inode!");
-		goto bail;
-	}
-
-	ocfs_handle_add_inode(handle, bitmap_inode);
-	status = ocfs_acquire_lock(osb, OCFS_LKM_EXMODE, 
-				   0, &bh, bitmap_inode);
-	if (status < 0) {
-		if (status != -EINTR)
-			LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-	ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 
-			     0, bitmap_inode);
-
-	fe = (ocfs2_dinode *) bh->b_data;
-	free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) - 
-		le32_to_cpu(fe->id1.bitmap1.i_used);
-
-	if (bits_wanted > free_bits) {
-		LOG_ERROR_ARGS("Disk Full: wanted=%u, free_bits=%u\n",
-			       bits_wanted, free_bits);
-		status = -ENOSPC;
-		goto bail;
-	}
-
-	/* Ok, done - we've determined that there's enough space in
-	 * the bitmap. Actually finding it is the job of the
-	 * allocation function now. We keep things locked so that the
-	 * bitmap can't change underneath us. */
-	ac->ac_inode = igrab(bitmap_inode);
-	get_bh(bh);
-	ac->ac_bh = bh;
-
-bail:
-	if (bitmap_inode)
-		iput(bitmap_inode);
-	if (bh)
-		brelse(bh);
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-}
-
 /* This function will figure out whether the currently last extent
  * block will be deleted, and if it will, what the new last extent
  * block will be so we can update his h_next_leaf_blk field, as well
@@ -1466,13 +1110,10 @@
 			OCFS_ASSERT(!el->l_recs[0].e_clusters);
 			OCFS_ASSERT(!el->l_recs[0].e_cpos);
 			OCFS_ASSERT(!el->l_recs[0].e_blkno);
-			status = ocfs_free_suballoc_bits(osb,
-							 handle,
+			status = ocfs2_free_extent_block(handle,
 							 tc->tc_ext_alloc_inode,
 							 tc->tc_ext_alloc_bh,
-							 eb->h_suballoc_bit,
-							 eb->h_blkno,
-							 1);
+							 eb);
 			if (status < 0) {
 				LOG_ERROR_STATUS(status);
 				goto bail;

Modified: branches/cluster-groups/src/alloc.h
===================================================================
--- branches/cluster-groups/src/alloc.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/alloc.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -34,35 +34,6 @@
 			u64 blkno, 
 			u32 new_clusters,
 			struct _ocfs2_alloc_context *meta_ac);
-
-typedef struct _ocfs2_alloc_context {
-	struct inode *ac_inode;    /* which bitmap are we allocating from? */
-	struct buffer_head *ac_bh; /* file entry bh */
-	u32    ac_bits_wanted;
-	u32    ac_bits_given;
-#define OCFS_AC_USE_LOCAL 1
-#define OCFS_AC_USE_MAIN  2
-#define OCFS_AC_USE_INODE 3
-#define OCFS_AC_USE_META  4
-	u32    ac_which;
-	ocfs_journal_handle *ac_handle; /* debugging mostly. */
-} ocfs2_alloc_context;
-
-void ocfs_free_alloc_context(ocfs2_alloc_context *ac);
-static inline int ocfs_alloc_context_bits_left(ocfs2_alloc_context *ac)
-{
-	return(ac->ac_bits_wanted - ac->ac_bits_given);
-}
-int ocfs_reserve_bits(ocfs_super *osb, 
-		      ocfs_journal_handle *handle,
-		      u32 bits_wanted,
-		      ocfs2_alloc_context **ac);
-int ocfs_claim_bits(ocfs_super *osb, 
-		    ocfs_journal_handle *handle, 
-		    ocfs2_alloc_context *ac,
-		    u32 min_bits,
-		    u32 *bit_off,
-		    u32 *num_bits);
 int ocfs_num_free_extents(ocfs_super *osb, 
 			  struct inode *inode,
 			  ocfs2_dinode *fe);
@@ -80,13 +51,6 @@
 	return(fe->id2.i_list.l_tree_depth + 2);
 }
 
-/* This is for local alloc ONLY. Others should use the generic apis
- * above. */
-int ocfs_reserve_main_bitmap_bits(ocfs_super *osb, 
-				  ocfs_journal_handle *handle,
-				  u32 bits_wanted,
-				  ocfs2_alloc_context *ac);
-
 typedef struct _ocfs2_truncate_context {
 	struct inode *tc_bitmap_inode;
 	struct buffer_head *tc_bitmap_bh;

Deleted: branches/cluster-groups/src/bitmap.c
===================================================================
--- branches/cluster-groups/src/bitmap.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/bitmap.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -1,496 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * bitmap.c
- *
- * Bitmap infrastructure code
- *
- * 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.
- */
-
-#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 "ocfs2.h"
-
-#include "alloc.h"
-#include "bitmap.h"
-#include "util.h"
-
-#include "ocfs_journal.h"
-#include "buffer_head_io.h"
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT  OCFS_DEBUG_CONTEXT_BITMAP
-
-/*
- * ocfs_initialize_bitmap()
- * 
- */
-void ocfs_initialize_bitmap(struct super_block *sb,
-			    ocfs_alloc_bm *bitmap, __u32 validbits,
-			    __u32 allocbits)
-{
-	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u, %u)\n", sb, bitmap, validbits,
-			allocbits);
-
-	bitmap->validbits = validbits;
-	bitmap->allocbits = allocbits;
-	bitmap->failed = 0;
-	bitmap->ok_retries = 0;
-
-	bitmap->numbh = ocfs_blocks_for_bits(sb, bitmap->allocbits);
-	bitmap->chunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
-	if (!bitmap->chunk)
-		BUG();
-
-	memset(bitmap->chunk, 0, (bitmap->numbh * sizeof(struct buffer_head *)));
-
-	LOG_EXIT ();
-	return;
-}				/* ocfs_initialize_bitmap */
-
-void ocfs_uninitialize_bitmap(ocfs_alloc_bm *bitmap)
-{
-	int i;
-
-	LOG_ENTRY();
-
-	for(i = 0; i < bitmap->numbh; i++)
-		if (bitmap->chunk[i])
-			brelse(bitmap->chunk[i]);
-
-	kfree(bitmap->chunk);
-	bitmap->chunk = NULL;
-	bitmap->numbh = 0;
-	bitmap->validbits = 0;
-	bitmap->allocbits = 0;
-	bitmap->failed = 0;
-	bitmap->ok_retries = 0;
-
-	LOG_EXIT();
-	return;
-}
-
-/* we only handle if the bitmap has grown, not shrunk. */
-void ocfs_reinitialize_bitmap(struct super_block *sb,
-			      ocfs_alloc_bm *bitmap, __u32 validbits,
-			      __u32 allocbits) 
-{
-	__u32 newnumbh;
-	struct buffer_head **newchunk;
-
-	LOG_ENTRY();
-
-	if (allocbits < bitmap->allocbits)
-		BUG();
-
-	/* most of the time the actual alloc'd size of the bitmap file
-	 * won't change and we don't have to update the buffer heads
-	 * or the number of bhs */
-	if (allocbits == bitmap->allocbits)
-		goto skipbhs;
-
-	newnumbh = ocfs_blocks_for_bits(sb, allocbits);
-	newchunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
-
-	if (!newchunk)
-		BUG();
-
-	memset(newchunk, 0, (newnumbh * sizeof(struct buffer_head *)));
-
-	memcpy(newchunk, bitmap->chunk, (bitmap->numbh * sizeof(struct buffer_head *)));
-
-	kfree(bitmap->chunk);
-
-	bitmap->numbh = newnumbh;
-	bitmap->chunk = newchunk;
-	bitmap->allocbits = allocbits;
-skipbhs:
-	bitmap->validbits = validbits;
-
-	LOG_EXIT();
-}
-
-/* 
- * More or less lifted from ext3. I'll leave their description below:
- * 
- * For ext3 allocations, we must not reuse any blocks which are
- * allocated in the bitmap buffer's "last committed data" copy.  This
- * prevents deletes from freeing up the page for reuse until we have
- * committed the delete transaction.
- *
- * If we didn't do this, then deleting something and reallocating it as
- * data would allow the old block to be overwritten before the
- * transaction committed (because we force data to disk before commit).
- * This would lead to corruption if we crashed between overwriting the
- * data and committing the delete. 
- *
- * @@@ We may want to make this allocation behaviour conditional on
- * data-writes at some point, and disable it for metadata allocations or
- * sync-data inodes.
- */
-static int ocfs_test_allocatable(int nr, struct buffer_head *bh)
-{
-	if (ocfs2_test_bit(nr, (unsigned long *)bh->b_data))
-		return 0;
-	if (!buffer_jbd(bh) || !bh2jh(bh)->b_committed_data)
-		return 1;
-	return !ocfs2_test_bit(nr, (unsigned long *)bh2jh(bh)->b_committed_data);
-}
-
-/*
- * ocfs_find_clear_bits()
- *
- * if you don't pass in best_fit_bits, we only try contig and give you
- * -ENOSPC otherwise.
- *
- * if you pass in best_fit_bits we return -ENOSPC only if we're
- * completely full, otherwise we'll always set best_fit_bits to at max
- * bits_wanted, and of course *bitoff to your starting offset.
- */
-int ocfs_find_clear_bits(ocfs_super *osb, ocfs_alloc_bm * bitmap,
-			 u32 bits_wanted, u32 *bitoff,
-			 u32 *best_fit_bits)
-{
-	int status = 0;
-	__u32 globalsize, globaloff, localstart, lastbh;
-	__u32 size = OCFS_BITS_IN_CHUNK(osb->sb);
-	__u32 count = 0;
-	u32 largest_start, largest_size;
-	void *buffer;
-	int c;
-	struct buffer_head *currbh = NULL;
-
-	LOG_ENTRY_ARGS ("(0x%p, 0x%p, %u)\n", osb, bitmap, bits_wanted);
-
-	/* We keep track of the biggest contiguous chunk we've seen so
-	 * far in these two variables. If we never completely fulfull
-	 * the request, we can pass them back for a best try. */
-	largest_start = 0;
-	largest_size = 0;
-
-	if (best_fit_bits)
-		*best_fit_bits = 0;
-
-	*bitoff = 0;
-	globalsize = bitmap->validbits;
-	lastbh = ocfs_blocks_for_bits(osb->sb, globalsize) - 1;
-
-	globaloff = 0;
-	ocfs_bitmap_block_for_off(osb->sb, globaloff, &c, &localstart);
-
-	if (lastbh == 0)
-		size = globalsize;
-
-	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 = currbh->b_data;
-
-	while ((*bitoff = ocfs2_find_next_zero_bit(buffer,
-						   OCFS_BITS_IN_CHUNK(osb->sb),
-						   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
-		   localstart: if the current one is a zero
-		*/
-		if (*bitoff >= size) {
-nextbh:
-			/* we've hit the end of our bh. */
-			/*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;
-			}
-			/* otherwise, reset localstart and switch bhs
-			 * and continue */
-			localstart = *bitoff = 0;
-			c++;
-			currbh = bitmap->chunk[c];
-			buffer = currbh->b_data;
-			if (c == lastbh)
-				size = globalsize -
-					(OCFS_BITS_IN_CHUNK(osb->sb)
-					 * lastbh);
-			globaloff = c * OCFS_BITS_IN_CHUNK(osb->sb);
-			continue;
-		}
-
-		if (!ocfs_test_allocatable(*bitoff, currbh)) {
-			/* We found a zero, but we can't use it as it
-			 * hasn't been put to disk yet! */
-			count = 0;
-			localstart = *bitoff + 1;
-			/* In doing this, we might go over our current bh. */
-			if (localstart >= size)
-				goto nextbh;
-
-			globaloff =
-				ocfs_bitmap_off_for_block(osb->sb, c,
-					 		  *bitoff) + 1;
-		} else 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_bitmap_off_for_block(osb->sb, c,
-				 			  *bitoff) + 1;
-			localstart = *bitoff + 1;
-		}
-
-		if (count > largest_size) {
-			largest_size = count;
-			largest_start = globaloff - count;
-		}
-
-		if (count == bits_wanted) {
-			/* we've found everything we wanted. */
-			LOG_TRACE_ARGS("Found it all! (count=%u)\n", count);
-			buffer = NULL;
-			break;
-		}
-	}
-
-	if (count == bits_wanted) {
-		*bitoff = globaloff - count;
-		if (best_fit_bits)
-			*best_fit_bits = bits_wanted;
-	} else if (best_fit_bits && largest_size) {
-#warning "can we go off the end of the bitmap here?"
-			*best_fit_bits = largest_size;
-			*bitoff = largest_start;
-	} else
-		status = -ENOSPC;
-
-	LOG_EXIT_STATUS(status);
-	return(status);
-}				/* ocfs_find_clear_bits */
-
-/*
- * ocfs_count_bits()
- *
- */
-int ocfs_count_bits(struct super_block *sb, ocfs_alloc_bm *bitmap)
-{
-	__u32 count = 0, i, j;
-	struct buffer_head *currbh;
-	unsigned char tmp;
-	__u8 *buffer;
-	int validbytes, size;
-
-	LOG_ENTRY ();
-
-	size = (bitmap->validbits >> 3);
-	validbytes = size;
-	if (validbytes > sb->s_blocksize)
-		validbytes = sb->s_blocksize;
-	
-	for (i = 0; size > 0; size -= validbytes, i++) {
-		currbh = bitmap->chunk[i];
-		buffer = currbh->b_data;
-		for (j = 0; j < validbytes; j++) {
-			/* U-U-U-GLY */
-			memcpy(&tmp, buffer, 1);
-			count += BITCOUNT(tmp);
-			buffer++;
-		}
-	}
-
-	LOG_EXIT_ULONG ((unsigned long)count);
-	return count;
-}				/* ocfs_count_bits */
-
-#ifdef __KERNEL__
-/* HEY LOOK! These two functions are IDENTICAL except for three lines!
- * We'd never do that... no, never... */
-
-/*
- * ocfs_set_bits()
- *
- */
-void ocfs_set_bits(struct super_block *sb,
-		   ocfs_journal_handle *handle,
-		   struct inode *inode,
-		   ocfs_alloc_bm * bitmap,
-		   u32 start,
-		   u32 num)
-{
-	struct buffer_head *currbh = NULL;
-	void *buff;
-	int i, local;
-	int status;
-
-	LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, %u, %u)\n", sb, handle,
-			bitmap, start, num);
-
-	if ((start + num) > bitmap->validbits) {
-		LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and "  \
-			       "num = %u!\n", bitmap->validbits, start, num);
-		goto bail;
-	}
-
-	ocfs_bitmap_block_for_off(sb, start, &i, &local);
-	currbh = bitmap->chunk[i];
-
-	status = ocfs_journal_access(handle, inode, currbh, 
-				     OCFS_JOURNAL_ACCESS_UNDO);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	buff = currbh->b_data;
-
-	while (num--) {
-		ocfs2_set_bit (local++, buff);
-		if ((local >= OCFS_BITS_IN_CHUNK(sb)) && (num != 0)) {
-			local = 0;
-			status = ocfs_journal_dirty(handle, currbh);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto bail;
-			}
-
-			i++;
-			currbh = bitmap->chunk[i];
-
-			status = ocfs_journal_access(handle, inode, currbh, 
-						     OCFS_JOURNAL_ACCESS_UNDO);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto bail;
-			}
-			buff = currbh->b_data;
-		}
-	}
-
-	status = ocfs_journal_dirty(handle, currbh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-bail:
-	LOG_EXIT ();
-	return;
-}				/* ocfs_set_bits */
-
-/*
- * ocfs_clear_bits()
- *
- */
-void ocfs_clear_bits(struct super_block *sb,
-		     ocfs_journal_handle *handle,
-		     struct inode *inode,
-		     ocfs_alloc_bm *bitmap,
-		     u32 start,
-		     u32 num)
-{
-	struct buffer_head *currbh = NULL;
-	void *buff;
-	int i, local;
-	int status;
-
-	LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, %u, %u)\n", sb, handle,
-			bitmap, start, num);
-
-	if ((start + num) > bitmap->validbits) {
-		LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and "  \
-			       "num = %u!\n", bitmap->validbits, start, num);
-		goto bail;
-	}
-
-	ocfs_bitmap_block_for_off(sb, start, &i, &local);
-	currbh = bitmap->chunk[i];
-
-	status = ocfs_journal_access(handle, inode, currbh, 
-				     OCFS_JOURNAL_ACCESS_UNDO);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-	buff = currbh->b_data;
-
-	while (num--) {
-		ocfs2_clear_bit (local, buff);
-		ocfs2_set_bit(local, 
-			(unsigned long *)bh2jh(currbh)->b_committed_data);
-		local++;
-
-		if ((local >= OCFS_BITS_IN_CHUNK(sb)) && (num != 0)) {
-			local = 0;
-
-			status = ocfs_journal_dirty(handle, currbh);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto bail;
-			}
-
-			i++;
-			currbh = bitmap->chunk[i];
-
-			status = ocfs_journal_access(handle, inode, currbh,
-						     OCFS_JOURNAL_ACCESS_UNDO);
-			if (status < 0) {
-				LOG_ERROR_STATUS(status);
-				goto bail;
-			}
-
-			buff = currbh->b_data;
-		}
-	}
-
-	status = ocfs_journal_dirty(handle, currbh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
-bail:
-	LOG_EXIT ();
-	return;
-}				/* ocfs_clear_bits */
-
-#endif				/* __KERNEL */

Deleted: branches/cluster-groups/src/bitmap.h
===================================================================
--- branches/cluster-groups/src/bitmap.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/bitmap.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -1,52 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * bitmap.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.
- */
-
-#ifndef OCFS2_BITMAP_H
-#define OCFS2_BITMAP_H
-
-int ocfs_count_bits(struct super_block *sb, ocfs_alloc_bm *bitmap);
-void ocfs_clear_bits(struct super_block *sb,
-		     ocfs_journal_handle *handle,
-		     struct inode *inode,
-		     ocfs_alloc_bm *bitmap,
-		     u32 start,
-		     u32 num);
-int ocfs_find_clear_bits(ocfs_super *osb, ocfs_alloc_bm * bitmap,
-			 u32 numBits, u32 *bitoff, u32 *best_fit_bits);
-void ocfs_initialize_bitmap(struct super_block *sb,
-			    ocfs_alloc_bm *bitmap, __u32 validbits,
-			    __u32 allocbits);
-void ocfs_reinitialize_bitmap(struct super_block *sb,
-			      ocfs_alloc_bm *bitmap, __u32 validbits,
-			      __u32 allocbits);
-void ocfs_set_bits(struct super_block *sb,
-		   ocfs_journal_handle *handle,
-		   struct inode *inode,
-		   ocfs_alloc_bm * bitmap,
-		   u32 start,
-		   u32 num);
-void ocfs_uninitialize_bitmap(ocfs_alloc_bm *bitmap);
-
-#endif /* OCFS2_BITMAP_H */

Modified: branches/cluster-groups/src/dir.c
===================================================================
--- branches/cluster-groups/src/dir.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/dir.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -432,7 +432,7 @@
 			}
 		}
 
-		status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+		status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto bail;

Modified: branches/cluster-groups/src/dir.h
===================================================================
--- branches/cluster-groups/src/dir.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/dir.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -39,11 +39,12 @@
 				const char *name, 
 				int namelen,
 				struct buffer_head **ret_de_bh);
+struct _ocfs2_alloc_context;
 int ocfs_do_extend_dir(struct super_block *sb,
 		       ocfs_journal_handle *handle,
 		       struct inode *dir,
 		       struct buffer_head *parent_fe_bh,
-		       ocfs2_alloc_context *data_ac,
-		       ocfs2_alloc_context *meta_ac,
+		       struct _ocfs2_alloc_context *data_ac,
+		       struct _ocfs2_alloc_context *meta_ac,
 		       struct buffer_head **new_bh);
 #endif /* OCFS2_DIR_H */

Modified: branches/cluster-groups/src/file.c
===================================================================
--- branches/cluster-groups/src/file.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/file.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -983,7 +983,8 @@
 		goto leave;
 	}
 
-	status = ocfs_claim_bits(osb, handle, data_ac, 1, &bit_off, &num_bits);
+	status = ocfs_claim_clusters(osb, handle, data_ac, 1,
+				     &bit_off, &num_bits);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto leave;
@@ -1146,10 +1147,10 @@
 		}
 	}
 
-	status = ocfs_reserve_bits(osb, 
-				   handle, 
-				   clusters_to_add,
-				   &data_ac);
+	status = ocfs_reserve_clusters(osb, 
+				       handle, 
+				       clusters_to_add,
+				       &data_ac);
 	if (status < 0) {
 		if (status != -ENOSPC)
 			LOG_ERROR_STATUS(status);

Modified: branches/cluster-groups/src/file.h
===================================================================
--- branches/cluster-groups/src/file.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/file.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -29,6 +29,7 @@
 extern struct file_operations ocfs_fops;
 extern struct file_operations ocfs_dops;
 extern struct inode_operations ocfs_file_iops;
+struct _ocfs2_alloc_context;
 
 enum ocfs2_alloc_restarted {
 	RESTART_TRANS = 0,
@@ -39,8 +40,8 @@
 			   u32 clusters_to_add, 
 			   struct buffer_head *fe_bh,
 			   ocfs_journal_handle *handle, 
-			   ocfs2_alloc_context *data_ac,
-			   ocfs2_alloc_context *meta_ac,
+			   struct _ocfs2_alloc_context *data_ac,
+			   struct _ocfs2_alloc_context *meta_ac,
 			   enum ocfs2_alloc_restarted *reason);
 int ocfs_extend_file(ocfs_super *osb, 
 		     struct inode *inode,

Modified: branches/cluster-groups/src/inode.c
===================================================================
--- branches/cluster-groups/src/inode.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/inode.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -751,9 +751,9 @@
 		goto bail;
 	}
 
-	status = ocfs_free_suballoc_bits(osb, handle, inode_alloc_inode,
-					 inode_alloc_bh, fe->i_suballoc_bit,
-					 fe->i_blkno, 1);
+	status = ocfs2_free_dinode(handle, inode_alloc_inode,
+				   inode_alloc_bh, fe);
+				       
 	if (status < 0)
 		LOG_ERROR_STATUS(status);
 

Modified: branches/cluster-groups/src/localalloc.c
===================================================================
--- branches/cluster-groups/src/localalloc.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/localalloc.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -37,7 +37,6 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
-#include "bitmap.h"
 #include "dlm.h"
 #include "localalloc.h"
 #include "suballoc.h"
@@ -486,15 +485,15 @@
  * discontiguous space, we this turns into a really simple check of
  * ->la_bits_set
  */
-int ocfs_reserve_local_alloc_bits(ocfs_super *osb, 
+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;
+	struct inode *local_alloc_inode;
 
 	LOG_ENTRY();
 
@@ -518,7 +517,6 @@
 		goto bail;
 	}
 
-#warning "isn't it about time we turned this check off?"
 	if (bits_wanted > ocfs2_clusters_for_bytes(osb->sb, 
 						   OCFS_LOCAL_ALLOC_MAX_ALLOC)) {
 		LOG_TRACE_STR("Asking for more than max local alloction!\n");
@@ -548,11 +546,9 @@
 	ac->ac_inode = igrab(local_alloc_inode);
 	get_bh(osb->local_alloc_bh);
 	ac->ac_bh = osb->local_alloc_bh;
-
+	ac->ac_which = OCFS_AC_USE_LOCAL;
 	status = 0;
 bail:
-	if (local_alloc_inode)
-		iput(local_alloc_inode);
 
 	LOG_EXIT_STATUS(status);
 	return(status);
@@ -733,10 +729,10 @@
 				   struct buffer_head *main_bm_bh)
 {
 	int status = 0;
-	int bit_off, left;
+	int bit_off, left, count, start;
+	u64 la_start_blk;
+	u64 blkno;
 	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,
@@ -748,77 +744,47 @@
 		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_inode, main_bm_bh,
-				     OCFS_JOURNAL_ACCESS_WRITE);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
+	if (LOCAL_ALLOC(alloc)->la_bits_set == 
+	    LOCAL_ALLOC(alloc)->la_bm_bits) {
+		LOG_TRACE_STR("all bits were taken!");
 		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_blocks(osb, (osb->bitmap_blkno + start), numblocks, 
-				  &osb->cluster_bitmap.chunk[start], 
-				  OCFS_BH_CACHED, main_bm_inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
+	la_start_blk = ocfs2_clusters_to_blocks(osb->sb,
+						LOCAL_ALLOC(alloc)->la_bm_off);
 	bitmap = LOCAL_ALLOC(alloc)->la_bitmap;
-	/* any unset bits in local alloc need to be unset in bitmap. */
-	bit_off = 0;
+	start = count = bit_off = 0;
 	left = LOCAL_ALLOC(alloc)->la_bm_bits;
-	while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, bit_off)) 
+
+	while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start)) 
 	       != -1) {
-		if (bit_off >= left) {
-			/*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
-			break;
-		}
+		if ((bit_off < left) && (bit_off == start)) {
+			count++;
+			start++;
+			continue;
+		} 
+		if (count) {
+			blkno = la_start_blk + (u64) (start - count);
 
-		LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n", 
-			       bit_off + LOCAL_ALLOC(alloc)->la_bm_off);
-		ocfs_clear_bits(osb->sb, handle, main_bm_inode, 
-				&osb->cluster_bitmap, 
-				bit_off + LOCAL_ALLOC(alloc)->la_bm_off,
-				1);
-		bm_fe->id1.bitmap1.i_used--;
-		bit_off++;
-	}
+			printk("freeing %u bits starting at local alloc bit "
+			       "%u (la_start_blk = %llu, blkno = %llu)\n", 
+			       count, start, la_start_blk, blkno);
 
-	status = ocfs_journal_dirty(handle, main_bm_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
+			status = ocfs_free_clusters(osb, handle, main_bm_inode,
+						    main_bm_bh, blkno, count);
+			if (status < 0) {
+				LOG_ERROR_STATUS(status);
+				goto bail;
+			}
+
+		}
+		if (bit_off >= left)
+			break;
+		count = 1;
+		start = bit_off + 1;
 	}
 
 bail:
-
 	LOG_EXIT_STATUS(status);
 	return(status);
 } /* ocfs_sync_local_to_main */
@@ -839,17 +805,22 @@
 	}
 	memset(*ac, 0, sizeof(ocfs2_alloc_context));
 	(*ac)->ac_handle = handle;
-
 	(*ac)->ac_bits_wanted = ocfs_local_alloc_window_bits(osb);
-	status = ocfs_reserve_main_bitmap_bits(osb,
-					       handle,
-					       (*ac)->ac_bits_wanted,
-					       *ac);
+	(*ac)->ac_inode = ocfs_get_system_file_inode(osb, 
+						     GLOBAL_BITMAP_SYSTEM_INODE, 
+						     -1);
+	if (!(*ac)->ac_inode) {
+		status = -EINVAL;
+		LOG_ERROR_STR("Could not get bitmap inode!");
+		goto bail;
+	}
+	(*ac)->ac_which = OCFS_AC_USE_MAIN;
+
+	status = ocfs_reserve_suballoc_bits(osb, *ac);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
-	(*ac)->ac_which = OCFS_AC_USE_MAIN;
 
 	*bitmap_inode = (*ac)->ac_inode;
 	igrab(*bitmap_inode);
@@ -888,15 +859,12 @@
 
 	LOG_TRACE_ARGS("Allocating %u clusters for a new window.\n", 
 		       ocfs_local_alloc_window_bits(osb));
-	/* we used the main bitmap specific reserve function, but we
-	 * set everything up nicely, so there's no reason why we can't
-	 * use the generic claim. */
-	status = ocfs_claim_bits(osb, 
-				 handle, 
-				 ac, 
-				 ocfs_local_alloc_window_bits(osb),
-				 &cluster_off, 
-				 &cluster_count);
+	/* we used the generic suballoc reserve function, but we set
+	 * everything up nicely, so there's no reason why we can't use
+	 * the more specific cluster api to claim bits. */
+	status = ocfs_claim_clusters(osb, handle, ac,
+				     ocfs_local_alloc_window_bits(osb), 
+				     &cluster_off, &cluster_count);
 	if (status < 0) {
 		if (status != -ENOSPC)
 			LOG_ERROR_STATUS(status);

Modified: branches/cluster-groups/src/localalloc.h
===================================================================
--- branches/cluster-groups/src/localalloc.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/localalloc.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -40,14 +40,15 @@
 int ocfs_alloc_should_use_local(ocfs_super *osb, 
 				u64 bits);
 
+struct _ocfs2_alloc_context;
 int ocfs_reserve_local_alloc_bits(ocfs_super *osb, 
 				  ocfs_journal_handle *passed_handle,
 				  u32 bits_wanted,
-				  ocfs2_alloc_context *ac);
+				  struct _ocfs2_alloc_context *ac);
 
 int ocfs_claim_local_alloc_bits(ocfs_super *osb,
 				ocfs_journal_handle *handle,
-				ocfs2_alloc_context *ac,
+				struct _ocfs2_alloc_context *ac,
 				u32 min_bits,
 				u32 *bit_off,
 				u32 *num_bits);

Modified: branches/cluster-groups/src/namei.c
===================================================================
--- branches/cluster-groups/src/namei.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/namei.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -359,7 +359,7 @@
 	/* are we making a directory? If so, reserve a cluster for his
 	 * 1st extent. */
 	if (S_ISDIR(mode)) {
-		status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+		status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
 			goto leave;
@@ -1589,7 +1589,7 @@
 		goto bail;
 	}
 
-	status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+	status = ocfs_reserve_clusters(osb, handle, 1, &data_ac);
 	if (status < 0) {
 		LOG_ERROR_STATUS (status = -ENOMEM);
 		goto bail;

Modified: branches/cluster-groups/src/ocfs.h
===================================================================
--- branches/cluster-groups/src/ocfs.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/ocfs.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -530,7 +530,7 @@
 	u64 root_blkno;
 	u64 system_dir_blkno;
 	u64 bitmap_blkno;
-	u32 bitmap_blocks;
+	u32 bitmap_cpg;
 	u64 publish_blkno;
 	u32 publish_blocks;
 	u64 vote_blkno;
@@ -542,6 +542,7 @@
 	u32 total_autoconfig_blocks;
 	u8 *uuid;
 	u8 *vol_label;
+	u64 first_cluster_group_blkno;
 
 	u32 s_feature_compat;
 	u32 s_feature_incompat;
@@ -567,7 +568,6 @@
 	int needs_flush;
 	struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/<maj_min> */
 
-	ocfs_alloc_bm cluster_bitmap;
 	atomic_t vol_state;
 	struct semaphore orphan_recovery_lock;
 	struct semaphore recovery_lock;

Modified: branches/cluster-groups/src/ocfs2_fs.h
===================================================================
--- branches/cluster-groups/src/ocfs2_fs.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/ocfs2_fs.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -317,7 +317,8 @@
 					   tunefs required */
 	__u16 s_reserved1;
 	__u32 s_reserved2;
-	__u64 s_reserved3;
+	__u64 s_first_cluster_group;	/* Block offset of 1st cluster
+					 * group header */
 /*50*/	__u8  s_label[64];		/* Label for mounting, etc. */
 /*90*/	__u8  s_uuid[16];		/* Was vol_id */
 /*A0*/

Modified: branches/cluster-groups/src/proc.c
===================================================================
--- branches/cluster-groups/src/proc.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/proc.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -459,17 +459,13 @@
   "Number of nodes          : %u\n"		\
   "Cluster size             : %d\n"		\
   "Volume size              : %llu\n"		\
-  "Failed Large Allocs      : %u\n"		\
-  "Retry Large Allocs       : %u\n"		\
   "Open Transactions:       : %u\n"		\
   "Delayed Locks            : %u\n"		\
   "Checkpointing Locks      : %u\n"
 
 	len = sprintf (page, PROC_STATS, pubmap,
 		       osb->num_nodes, osb->s_clustersize, 
-		       ocfs2_clusters_to_bytes(osb->sb, osb->cluster_bitmap.validbits),
-		       osb->cluster_bitmap.failed, 
-		       osb->cluster_bitmap.ok_retries, 
+		       ocfs2_clusters_to_bytes(osb->sb, osb->num_clusters),
 		       atomic_read(&osb->journal->num_trans),
 		       atomic_read(&osb->journal->num_cmt_locks),
 		       atomic_read(&osb->journal->num_chkpt_locks));

Modified: branches/cluster-groups/src/suballoc.c
===================================================================
--- branches/cluster-groups/src/suballoc.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/suballoc.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -37,6 +37,7 @@
 
 #include "alloc.h"
 #include "dlm.h"
+#include "localalloc.h"
 #include "util.h"
 #include "suballoc.h"
 #include "sysfile.h"
@@ -58,18 +59,18 @@
 static int ocfs_block_group_alloc(ocfs_super *osb, 
 				  struct inode *alloc_inode,
 				  struct buffer_head *bh);
-static int ocfs_reserve_suballoc_bits(ocfs_super *osb, 
-				      ocfs_journal_handle *handle,
-				      ocfs2_alloc_context *ac);
 static int ocfs_claim_suballoc_bits(ocfs_super *osb,
 				    ocfs_journal_handle *handle,
 				    ocfs2_alloc_context *ac,
 				    u32 bits_wanted,
+				    u32 min_bits,
 				    u16 *bit_off,
 				    unsigned int *num_bits,
 				    u64 *bg_blkno);
+static int ocfs_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+					int nr);
 static int ocfs_block_group_find_clear_bits(ocfs_super *osb, 
-					    ocfs2_group_desc *bg,
+					    struct buffer_head *bg_bh,
 					    unsigned int bits_wanted, 
 					    u16 *bit_off,
 					    u16 *bits_found);
@@ -79,6 +80,13 @@
 					    struct buffer_head *group_bh,
 					    unsigned int bit_off, 
 					    unsigned int num_bits);
+static inline int ocfs_block_group_clear_bits(ocfs_journal_handle *handle,
+					      struct inode *alloc_inode,
+					      ocfs2_group_desc *bg, 
+					      struct buffer_head *group_bh,
+					      unsigned int bit_off, 
+					      unsigned int num_bits);
+
 static int ocfs_relink_block_group(ocfs_journal_handle *handle,
 				   struct inode *alloc_inode,
 				   struct buffer_head *fe_bh,
@@ -87,8 +95,33 @@
 				   u16 chain);
 static inline int ocfs_block_group_reasonably_empty(ocfs2_group_desc *bg,
 						    u32 wanted);
-static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit);
+static int ocfs_free_suballoc_bits(ocfs_journal_handle *handle, 
+				   struct inode *alloc_inode,
+				   struct buffer_head *alloc_bh,
+				   unsigned int start_bit,
+				   u64 bg_blkno,
+				   unsigned int count);
+static inline u64 ocfs_which_suballoc_group(u64 block,
+					    unsigned int bit);
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+						   u64 bg_blkno,
+						   u16 bg_bit_off);
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+					    u32 cluster);
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+						u64 data_blkno,
+						u64 *bg_blkno,
+						u16 *bg_bit_off);
 
+void ocfs_free_alloc_context(ocfs2_alloc_context *ac)
+{
+	if (ac->ac_inode)
+		iput(ac->ac_inode);
+	if (ac->ac_bh)
+		brelse(ac->ac_bh);
+	kfree(ac);
+}
+
 static int ocfs2_block_group_fill(ocfs_journal_handle *handle, 
 				  struct inode *alloc_inode,
 				  struct buffer_head *bg_bh,
@@ -235,6 +268,8 @@
 	struct buffer_head **zero_bhs = NULL;
 #endif
 
+	OCFS_ASSERT(!ocfs2_is_cluster_bitmap(alloc_inode));
+
 	LOG_ENTRY();
 
 	handle = ocfs_alloc_handle(osb);
@@ -245,10 +280,10 @@
 	}
 
 	cl = &fe->id2.i_chain;
-	status = ocfs_reserve_bits(osb, 
-				   handle, 
-				   cl->cl_cpg, 
-				   &ac);
+	status = ocfs_reserve_clusters(osb, 
+				       handle, 
+				       cl->cl_cpg, 
+				       &ac);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -262,12 +297,12 @@
 		goto bail;
 	}
 
-	status = ocfs_claim_bits(osb, 
-				 handle, 
-				 ac, 
-				 cl->cl_cpg, 
-				 &bit_off, 
-				 &num_bits);
+	status = ocfs_claim_clusters(osb,
+				     handle,
+				     ac,
+				     cl->cl_cpg,
+				     &bit_off,
+				     &num_bits);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -359,15 +394,16 @@
 	return status;
 }
 
-static int ocfs_reserve_suballoc_bits(ocfs_super *osb, 
-				      ocfs_journal_handle *handle,
-				      ocfs2_alloc_context *ac)
+int ocfs_reserve_suballoc_bits(ocfs_super *osb, 
+			       ocfs2_alloc_context *ac)
 {
 	int status;
 	u32 bits_wanted = ac->ac_bits_wanted;
 	struct inode *alloc_inode = ac->ac_inode;
 	struct buffer_head *bh = NULL;
+	ocfs_journal_handle *handle = ac->ac_handle;
 	ocfs2_dinode *fe;
+	u32 free_bits;
 
 	LOG_ENTRY();
 
@@ -388,8 +424,18 @@
 	OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
 	OCFS_ASSERT_RO(fe->i_flags & OCFS2_CHAIN_FL);
 
-	if (bits_wanted > (le32_to_cpu(fe->id1.bitmap1.i_total) - 
-			   le32_to_cpu(fe->id1.bitmap1.i_used))) {
+	free_bits = le32_to_cpu(fe->id1.bitmap1.i_total) - 
+		le32_to_cpu(fe->id1.bitmap1.i_used);
+
+	if (bits_wanted > free_bits) {
+		/* cluster bitmap never grows */
+		if (ocfs2_is_cluster_bitmap(alloc_inode)) {
+			LOG_ERROR_ARGS("Disk Full: wanted=%u, free_bits=%u\n",
+				       bits_wanted, free_bits);
+			status = -ENOSPC;
+			goto bail;
+		}
+
 		status = ocfs_block_group_alloc(osb, alloc_inode, bh);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
@@ -403,7 +449,6 @@
 
 	get_bh(bh);
 	ac->ac_bh = bh;
-	status = 0;
 bail:
 	if (bh)
 		brelse(bh);
@@ -444,7 +489,7 @@
 
 	(*ac)->ac_inode = igrab(alloc_inode);
 
-	status = ocfs_reserve_suballoc_bits(osb, handle, (*ac));
+	status = ocfs_reserve_suballoc_bits(osb, (*ac));
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -491,7 +536,7 @@
 
 	(*ac)->ac_inode = igrab(alloc_inode);
 
-	status = ocfs_reserve_suballoc_bits(osb, handle, *ac);
+	status = ocfs_reserve_suballoc_bits(osb, *ac);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -511,8 +556,120 @@
 	return status;
 }
 
+/* Callers don't need to care which bitmap (local alloc or main) to
+ * use so we figure it out for them, but unfortunately this clutters
+ * things a bit. */
+int ocfs_reserve_clusters(ocfs_super *osb, 
+			  ocfs_journal_handle *handle,
+			  u32 bits_wanted,
+			  ocfs2_alloc_context **ac)
+{
+	int status;
+	struct inode *main_bitmap_inode = NULL;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT(handle);
+
+	*ac = kmalloc(sizeof(ocfs2_alloc_context), GFP_KERNEL);
+	if (!(*ac)) {
+		status = -ENOMEM;
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+	memset(*ac, 0, sizeof(ocfs2_alloc_context));
+	(*ac)->ac_bits_wanted = bits_wanted;
+	(*ac)->ac_handle = handle;
+
+	status = -ENOSPC;
+	if (ocfs_alloc_should_use_local(osb, bits_wanted)) {
+		status = ocfs_reserve_local_alloc_bits(osb,
+						       handle,
+						       bits_wanted,
+						       *ac);
+		if ((status < 0) && (status != -ENOSPC)) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		} else if (status == -ENOSPC) {
+#warning "need to deal with disabling local alloc better"
+			/* reserve_local_bits will return enospc with
+			 * the local alloc inode still locked, so we
+			 * can change this safely here. */
+			LOG_ERROR_STR("Disabling local alloc");
+			osb->have_local_alloc = 0;
+//			ocfs_shutdown_local_alloc(osb);
+		} 
+	}
+
+	if (status == -ENOSPC) {
+		main_bitmap_inode = ocfs_get_system_file_inode(osb, 
+							       GLOBAL_BITMAP_SYSTEM_INODE, 
+							       -1);
+		if (!main_bitmap_inode) {
+			status = -EINVAL;
+			LOG_ERROR_STR("Could not get bitmap inode!");
+			goto bail;
+		}
+		(*ac)->ac_which = OCFS_AC_USE_MAIN;
+		(*ac)->ac_inode = igrab(main_bitmap_inode);
+		status = ocfs_reserve_suballoc_bits(osb, *ac);
+		if (status < 0) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+	}
+
+	status = 0;
+bail:
+	if ((status < 0) && *ac) {
+		ocfs_free_alloc_context(*ac);
+		*ac = NULL;
+	}
+	if (main_bitmap_inode)
+		iput(main_bitmap_inode);
+
+	LOG_EXIT_STATUS(status);
+	return(status);
+}
+
+/* 
+ * More or less lifted from ext3. I'll leave their description below:
+ * 
+ * "For ext3 allocations, we must not reuse any blocks which are
+ * allocated in the bitmap buffer's "last committed data" copy.  This
+ * prevents deletes from freeing up the page for reuse until we have
+ * committed the delete transaction.
+ *
+ * If we didn't do this, then deleting something and reallocating it as
+ * data would allow the old block to be overwritten before the
+ * transaction committed (because we force data to disk before commit).
+ * This would lead to corruption if we crashed between overwriting the
+ * data and committing the delete. 
+ *
+ * @@@ We may want to make this allocation behaviour conditional on
+ * data-writes at some point, and disable it for metadata allocations or
+ * sync-data inodes."
+ *
+ * Note: OCFS2 already does this differently for metadata vs data
+ * allocations, as those bitmaps are seperate and undo access is never
+ * called on a metadata group descriptor.
+ */
+static int ocfs_test_bg_bit_allocatable(struct buffer_head *bg_bh,
+					int nr)
+{
+	ocfs2_group_desc *bg = (ocfs2_group_desc *) bg_bh->b_data;
+
+	if (ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap))
+		return 0;
+	if (!buffer_jbd(bg_bh) || !bh2jh(bg_bh)->b_committed_data)
+		return 1;
+
+	bg = (ocfs2_group_desc *) bh2jh(bg_bh)->b_committed_data;
+	return !ocfs2_test_bit(nr, (unsigned long *)bg->bg_bitmap);
+}
+
 static int ocfs_block_group_find_clear_bits(ocfs_super *osb, 
-					    ocfs2_group_desc *bg,
+					    struct buffer_head *bg_bh,
 					    unsigned int bits_wanted, 
 					    u16 *bit_off,
 					    u16 *bits_found)
@@ -520,6 +677,7 @@
 	void *bitmap;
 	u16 best_offset, best_size;
 	int offset, start, found, status = 0;
+	ocfs2_group_desc *bg = (ocfs2_group_desc *) bg_bh->b_data;
 
 	OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
 
@@ -532,7 +690,12 @@
 		if (offset == bg->bg_bits)
 			break;
 
-		if (offset == start) {
+		if (!ocfs_test_bg_bit_allocatable(bg_bh, offset)) {
+			/* We found a zero, but we can't use it as it
+			 * hasn't been put to disk yet! */
+			found = 0;
+			start = offset + 1;
+		} else if (offset == start) {
 			/* we found a zero */
 			found++;
 			start++;
@@ -575,6 +738,7 @@
 {
 	int status;
 	void *bitmap = bg->bg_bitmap;
+	int journal_type = OCFS_JOURNAL_ACCESS_WRITE;
 
 	LOG_ENTRY();
 
@@ -584,10 +748,13 @@
 	LOG_TRACE_ARGS("block_group_set_bits: off = %u, num = %u\n", bit_off, 
 		       num_bits);
 
+	if (ocfs2_is_cluster_bitmap(alloc_inode))
+		journal_type = OCFS_JOURNAL_ACCESS_UNDO;
+
 	status = ocfs_journal_access(handle,
 				     alloc_inode,
 				     group_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
+				     journal_type);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
@@ -723,11 +890,12 @@
 				    ocfs_journal_handle *handle,
 				    ocfs2_alloc_context *ac,
 				    u32 bits_wanted,
+				    u32 min_bits,
 				    u16 *bit_off,
 				    unsigned int *num_bits,
 				    u64 *bg_blkno)
 {
-	int status, groups_read;
+	int status;
 	struct inode *alloc_inode = ac->ac_inode;
 	struct buffer_head *group_bh = NULL;
 	struct buffer_head *prev_group_bh = NULL;
@@ -767,7 +935,6 @@
 
 	/* for now, the chain search is a bit simplistic. We just use
 	 * the 1st group with any empty bits. */
-	groups_read = 1;
 	while (!bg->bg_free_bits_count) {
 		/*
 		 * This means we've walked off the end of a chain that
@@ -790,13 +957,12 @@
 			LOG_ERROR_STATUS(status);
 			goto bail;
 		}
-		groups_read++;
 		bg = (ocfs2_group_desc *) group_bh->b_data;
 		OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
 	}
 
 	status = ocfs_block_group_find_clear_bits(osb, 
-						  bg, 
+						  group_bh, 
 						  bits_wanted, 
 						  bit_off,
 						  &tmp_bits);
@@ -804,11 +970,16 @@
 		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
+	if (tmp_bits < min_bits) {
+#warning need to search another chain here.
+		status = -ENOSPC;
+		goto bail;
+	}
+
 	*num_bits = tmp_bits;
 
 	OCFS_ASSERT(*num_bits);
 
-#define OCFS2_BG_RELINK_TRIGGER 1
 	/*
 	 * Keep track of previous block descriptor read. When
 	 * we find a target, if we have read more than X
@@ -823,7 +994,6 @@
 	 * of our target group.
 	 */
 	if ((prev_group_bh) 
-	    && (groups_read > OCFS2_BG_RELINK_TRIGGER) 
 	    && (ocfs_block_group_reasonably_empty(bg, *num_bits))) {
 		status = ocfs_relink_block_group(handle, alloc_inode,
 						 ac->ac_bh, group_bh, 
@@ -904,6 +1074,7 @@
 					  handle,
 					  ac,
 					  bits_wanted,
+					  1,
 					  suballoc_bit_start,
 					  num_bits,
 					  &bg_blkno);
@@ -938,11 +1109,12 @@
 	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_INODE);
 	OCFS_ASSERT(ac->ac_handle == handle);
 
-	status = ocfs_claim_suballoc_bits(osb, 
-					  handle, 
-					  ac, 
-					  1, 
-					  suballoc_bit, 
+	status = ocfs_claim_suballoc_bits(osb,
+					  handle,
+					  ac,
+					  1,
+					  1,
+					  suballoc_bit,
 					  &num_bits,
 					  &bg_blkno);
 	if (status < 0) {
@@ -960,29 +1132,139 @@
 	return status;
 }
 
-static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit)
+/*
+ * min_bits - minimum contiguous chunk from this total allocation we
+ * can handle. set to what we asked for originally for a full
+ * contig. allocation, set to '1' to indicate we can deal with extents
+ * of any size.
+ */
+int ocfs_claim_clusters(ocfs_super *osb, 
+			ocfs_journal_handle *handle, 
+			ocfs2_alloc_context *ac,
+			u32 min_clusters,
+			u32 *cluster_start,
+			u32 *num_clusters)
 {
-	return(block - (u64) bit);
+	int status;
+	unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
+	u64 bg_blkno;
+	u16 bg_bit_off;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT(ac);
+	OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
+
+	OCFS_ASSERT(ac->ac_which == OCFS_AC_USE_LOCAL 
+		    || ac->ac_which == OCFS_AC_USE_MAIN);
+	OCFS_ASSERT(ac->ac_handle == handle);
+
+	if (ac->ac_which == OCFS_AC_USE_LOCAL) {
+		status = ocfs_claim_local_alloc_bits(osb,
+						     handle,
+						     ac,
+						     bits_wanted,
+						     cluster_start,
+						     num_clusters);
+	} else {
+		/* clamp this down to a realistic size. */
+		if (bits_wanted > (osb->bitmap_cpg - 1))
+			bits_wanted = osb->bitmap_cpg - 1;
+
+		status = ocfs_claim_suballoc_bits(osb,
+						  handle,
+						  ac,
+						  bits_wanted,
+						  min_clusters,
+						  &bg_bit_off,
+						  num_clusters,
+						  &bg_blkno);
+		if (!status)
+			*cluster_start = 
+				ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
+								 bg_blkno,
+								 bg_bit_off);
+	}
+	if (status < 0) {
+		/* If you're not asking for contiguous blocks, then
+		 * the reserve function should've given you enough,
+		 * and ENOSPC this is a real error. */
+		if ((status != -ENOSPC) || (min_clusters == 1))
+			LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	ac->ac_bits_given += *num_clusters;
+
+bail:
+	LOG_EXIT_STATUS(status);
+	return(status);
 }
 
+static inline int ocfs_block_group_clear_bits(ocfs_journal_handle *handle,
+					    struct inode *alloc_inode,
+					    ocfs2_group_desc *bg, 
+					    struct buffer_head *group_bh,
+					    unsigned int bit_off, 
+					    unsigned int num_bits)
+{
+	int status;
+	unsigned int tmp;
+	int journal_type = OCFS_JOURNAL_ACCESS_WRITE;
+	ocfs2_group_desc *undo_bg = NULL;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
+
+	LOG_TRACE_ARGS("off = %u, num = %u\n", bit_off, num_bits);
+
+	if (ocfs2_is_cluster_bitmap(alloc_inode))
+		journal_type = OCFS_JOURNAL_ACCESS_UNDO;
+
+	status = ocfs_journal_access(handle, alloc_inode, group_bh, 
+				     journal_type);
+	if (status < 0) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	if (ocfs2_is_cluster_bitmap(alloc_inode))
+		undo_bg = (ocfs2_group_desc *) bh2jh(group_bh)->b_committed_data;
+
+	tmp = num_bits;
+	while(tmp--) {
+		ocfs2_clear_bit((bit_off + tmp),
+				(unsigned long *) bg->bg_bitmap);
+		if (ocfs2_is_cluster_bitmap(alloc_inode))
+			ocfs2_set_bit(bit_off + tmp, 
+				      (unsigned long *) undo_bg->bg_bitmap);
+	}
+	bg->bg_free_bits_count += num_bits;
+
+	status = ocfs_journal_dirty(handle, group_bh);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+bail:
+	return status;
+}
+
 /*
  * expects the suballoc inode to already be locked.
  */
-int ocfs_free_suballoc_bits(ocfs_super *osb, 
-			    ocfs_journal_handle *handle, 
-			    struct inode *alloc_inode,
-			    struct buffer_head *alloc_bh,
-			    unsigned int start_bit,
-			    u64 start_block,
-			    unsigned int count) 
+static int ocfs_free_suballoc_bits(ocfs_journal_handle *handle, 
+				   struct inode *alloc_inode,
+				   struct buffer_head *alloc_bh,
+				   unsigned int start_bit,
+				   u64 bg_blkno,
+				   unsigned int count) 
 {
 	int status = 0;
+	ocfs_super *osb = OCFS2_SB(alloc_inode->i_sb);
 	ocfs2_dinode *fe = (ocfs2_dinode *) alloc_bh->b_data;
 	ocfs2_chain_list *cl = &fe->id2.i_chain;
-	u64 bg_blkno;
 	struct buffer_head *group_bh = NULL;
 	ocfs2_group_desc *group;
-	unsigned int tmp;
 
 	LOG_ENTRY();
 
@@ -990,11 +1272,10 @@
 	OCFS_ASSERT((count + start_bit) 
 		    <= ((u32) cl->cl_cpg * (u32) cl->cl_bpc));
 
-	bg_blkno = ocfs_which_suballoc_group(start_block, start_bit);
-	LOG_TRACE_ARGS("freeing %u bits from group %llu, starting at %u "
-		       "(1st block = %llu, suballocator %llu)\n",
-		       count, bg_blkno, start_bit, start_block, 
-		       OCFS_I(alloc_inode)->ip_blkno);
+	printk("suballocator %llu: freeing %u bits from group %llu, "
+	       "starting at %u\n",
+	       OCFS_I(alloc_inode)->ip_blkno, count, bg_blkno, 
+	       start_bit);
 
 	status = ocfs_read_block(osb, bg_blkno, &group_bh, OCFS_BH_CACHED, 
 				 alloc_inode);
@@ -1006,26 +1287,14 @@
 	group = (ocfs2_group_desc *) group_bh->b_data;
 	OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(group));
 
-	status = ocfs_journal_access(handle, alloc_inode, group_bh, 
-				     OCFS_JOURNAL_ACCESS_WRITE);
+	status = ocfs_block_group_clear_bits(handle, alloc_inode,
+					     group, group_bh,
+					     start_bit, count);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
 
-	tmp = count;
-	while(tmp--)
-		ocfs2_clear_bit((start_bit + tmp),
-				(unsigned long *) group->bg_bitmap);
-
-	group->bg_free_bits_count += count;
-
-	status = ocfs_journal_dirty(handle, group_bh);
-	if (status < 0) {
-		LOG_ERROR_STATUS(status);
-		goto bail;
-	}
-
 	status = ocfs_journal_access(handle, alloc_inode, alloc_bh, 
 				     OCFS_JOURNAL_ACCESS_WRITE);
 	if (status < 0) {
@@ -1053,6 +1322,133 @@
 	return status;
 }
 
+static inline u64 ocfs_which_suballoc_group(u64 block, unsigned int bit)
+{
+	u64 group = block - (u64) bit;
+
+	return group;
+}
+
+int ocfs2_free_dinode(ocfs_journal_handle *handle,
+		      struct inode *inode_alloc_inode,
+		      struct buffer_head *inode_alloc_bh,
+		      ocfs2_dinode *di)
+{
+	u64 blk = le64_to_cpu(di->i_blkno);
+	u16 bit = le16_to_cpu(di->i_suballoc_bit);
+	u64 bg_blkno = ocfs_which_suballoc_group(blk, bit);
+
+	return ocfs_free_suballoc_bits(handle, inode_alloc_inode,
+				       inode_alloc_bh, bit, bg_blkno, 1);
+}
+
+int ocfs2_free_extent_block(ocfs_journal_handle *handle,
+			    struct inode *eb_alloc_inode,
+			    struct buffer_head *eb_alloc_bh,
+			    ocfs2_extent_block *eb)
+{
+	u64 blk = le64_to_cpu(eb->h_blkno);
+	u16 bit = le16_to_cpu(eb->h_suballoc_bit);
+	u64 bg_blkno = ocfs_which_suballoc_group(blk, bit);
+
+	return ocfs_free_suballoc_bits(handle, eb_alloc_inode, eb_alloc_bh,
+				       bit, bg_blkno, 1);
+}
+
+/* translate a group desc. blkno and it's bitmap offset into
+ * disk cluster offset. */
+static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
+						   u64 bg_blkno,
+						   u16 bg_bit_off)
+{
+	ocfs_super *osb = OCFS2_SB(inode->i_sb);
+	u32 cluster = 0;
+
+	OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+	if (bg_blkno != osb->first_cluster_group_blkno)
+		cluster = ocfs2_blocks_to_clusters(inode->i_sb, bg_blkno);
+	cluster += (u32) bg_bit_off;
+	return cluster;
+}
+
+/* given a cluster offset, calculate which block group it belongs to
+ * and return that block offset. */
+static inline u64 ocfs2_which_cluster_group(struct inode *inode,
+					    u32 cluster)
+{
+	ocfs_super *osb = OCFS2_SB(inode->i_sb);
+	u32 group_cluster_off;
+
+	OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+	/* align us to the cluster groups 1st cluster */
+	group_cluster_off = cluster / osb->bitmap_cpg;
+	if (!group_cluster_off)
+		return osb->first_cluster_group_blkno;
+	return ocfs2_clusters_to_blocks(inode->i_sb, group_cluster_off);
+}
+
+/* given the block number of a cluster start, calculate which cluster
+ * group and descriptor bitmap offset that corresponds to. */
+static inline void ocfs2_block_to_cluster_group(struct inode *inode,
+						u64 data_blkno,
+						u64 *bg_blkno,
+						u16 *bg_bit_off)
+{
+	ocfs_super *osb = OCFS2_SB(inode->i_sb);
+	u32 data_cluster = ocfs2_blocks_to_clusters(osb->sb, data_blkno);
+
+	OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+	*bg_blkno = ocfs2_which_cluster_group(inode,
+					      data_cluster);
+
+	if (*bg_blkno == osb->first_cluster_group_blkno)
+		*bg_bit_off = (u16) data_cluster;
+	else
+		*bg_bit_off = (u16) ocfs2_blocks_to_clusters(osb->sb,
+							     data_blkno - *bg_blkno);
+}
+
+int ocfs_free_clusters(ocfs_super *osb,
+		       ocfs_journal_handle *handle,
+		       struct inode *bitmap_inode,
+		       struct buffer_head *bitmap_bh,
+		       u64 start_blk,
+		       unsigned int num_clusters)
+{
+	int status;
+	u16 bg_start_bit;
+	u64 bg_blkno;
+	ocfs2_dinode *fe;
+
+	/* You can't ever have a contiguous set of clusters
+	 * bigger than a block group bitmap so we never have to worry
+	 * about looping on them. */
+
+	LOG_ENTRY();
+
+	fe = (ocfs2_dinode *) bitmap_bh->b_data;
+
+	ocfs2_block_to_cluster_group(bitmap_inode, start_blk, &bg_blkno,
+				     &bg_start_bit);
+
+	printk("want to free %u clusters starting at block %llu\n", 
+	       num_clusters, start_blk);
+	printk("bg_blkno = %llu, bg_start_bit = %u\n", bg_blkno,
+	       bg_start_bit);
+
+	status = ocfs_free_suballoc_bits(handle, bitmap_inode, bitmap_bh,
+					 bg_start_bit, bg_blkno,
+					 num_clusters);
+	if (status < 0)
+		LOG_ERROR_STATUS(status);
+
+	LOG_EXIT_STATUS(status);
+	return status;
+}
+
 static inline void debug_bg(ocfs2_group_desc *bg) 
 {
 	printk("Block Group:\n");

Modified: branches/cluster-groups/src/suballoc.h
===================================================================
--- branches/cluster-groups/src/suballoc.h	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/suballoc.h	2004-11-04 22:14:37 UTC (rev 1624)
@@ -26,6 +26,25 @@
 #ifndef _CHAINALLOC_H_
 #define _CHAINALLOC_H_
 
+typedef struct _ocfs2_alloc_context {
+	struct inode *ac_inode;    /* which bitmap are we allocating from? */
+	struct buffer_head *ac_bh; /* file entry bh */
+	u32    ac_bits_wanted;
+	u32    ac_bits_given;
+#define OCFS_AC_USE_LOCAL 1
+#define OCFS_AC_USE_MAIN  2
+#define OCFS_AC_USE_INODE 3
+#define OCFS_AC_USE_META  4
+	u32    ac_which;
+	ocfs_journal_handle *ac_handle; /* debugging mostly. */
+} ocfs2_alloc_context;
+
+void ocfs_free_alloc_context(ocfs2_alloc_context *ac);
+static inline int ocfs_alloc_context_bits_left(ocfs2_alloc_context *ac)
+{
+	return(ac->ac_bits_wanted - ac->ac_bits_given);
+}
+
 int ocfs_reserve_new_metadata(ocfs_super *osb, 
 			      ocfs_journal_handle *handle,
 			      ocfs2_dinode *fe,
@@ -33,11 +52,11 @@
 int ocfs_reserve_new_inode(ocfs_super *osb, 
 			   ocfs_journal_handle *handle,
 			   ocfs2_alloc_context **ac);
-int ocfs_claim_new_inode(ocfs_super *osb, 
-			 ocfs_journal_handle *handle,
-			 ocfs2_alloc_context *ac,
-			 u16 *suballoc_bit,
-			 u64 *fe_blkno);
+int ocfs_reserve_clusters(ocfs_super *osb, 
+			  ocfs_journal_handle *handle,
+			  u32 bits_wanted,
+			  ocfs2_alloc_context **ac);
+
 int ocfs_claim_metadata(ocfs_super *osb,
 			ocfs_journal_handle *handle,
 			ocfs2_alloc_context *ac,
@@ -45,11 +64,58 @@
 			u16 *suballoc_bit_start,
 			u32 *num_bits,
 			u64 *blkno_start);
-int ocfs_free_suballoc_bits(ocfs_super *osb, 
-			    ocfs_journal_handle *handle, 
-			    struct inode *alloc_inode,
-			    struct buffer_head *alloc_bh,
-			    unsigned int start_bit,
-			    u64 start_block,
-			    unsigned int count);
+int ocfs_claim_new_inode(ocfs_super *osb, 
+			 ocfs_journal_handle *handle,
+			 ocfs2_alloc_context *ac,
+			 u16 *suballoc_bit,
+			 u64 *fe_blkno);
+int ocfs_claim_clusters(ocfs_super *osb, 
+			ocfs_journal_handle *handle, 
+			ocfs2_alloc_context *ac,
+			u32 min_clusters,
+			u32 *cluster_start,
+			u32 *num_clusters);
+
+int ocfs2_free_dinode(ocfs_journal_handle *handle,
+		      struct inode *inode_alloc_inode,
+		      struct buffer_head *inode_alloc_bh,
+		      ocfs2_dinode *di);
+int ocfs2_free_extent_block(ocfs_journal_handle *handle,
+			    struct inode *eb_alloc_inode,
+			    struct buffer_head *eb_alloc_bh,
+			    ocfs2_extent_block *eb);
+int ocfs_free_clusters(ocfs_super *osb,
+		       ocfs_journal_handle *handle,
+		       struct inode *bitmap_inode,
+		       struct buffer_head *bitmap_bh,
+		       u64 start_blk,
+		       unsigned int num_clusters);
+
+static inline u32 ocfs2_cluster_from_desc(ocfs_super *osb,
+					  u64 bg_blkno)
+{
+	/* This should work for all block group descriptors as only
+	 * the 1st group descriptor of the cluster bitmap is
+	 * different. */
+
+	if (bg_blkno == osb->first_cluster_group_blkno)
+		return 0;
+
+	/* the rest of the block groups are located at the beginning
+	 * of their 1st cluster, so a direct translation just
+	 * works. */
+	return ocfs2_blocks_to_clusters(osb->sb, bg_blkno);
+}
+
+static inline int ocfs2_is_cluster_bitmap(struct inode *inode)
+{
+	ocfs_super *osb = OCFS2_SB(inode->i_sb);
+	return osb->bitmap_blkno == OCFS_I(inode)->ip_blkno;
+}
+
+/* This is for local alloc ONLY. Others should use the task-specific
+ * apis above. */
+int ocfs_reserve_suballoc_bits(ocfs_super *osb, 
+			       ocfs2_alloc_context *ac);
+
 #endif /* _CHAINALLOC_H_ */

Modified: branches/cluster-groups/src/super.c
===================================================================
--- branches/cluster-groups/src/super.c	2004-11-04 22:08:28 UTC (rev 1623)
+++ branches/cluster-groups/src/super.c	2004-11-04 22:14:37 UTC (rev 1624)
@@ -50,7 +50,6 @@
 #include "ocfs1_fs_compat.h"
 
 #include "alloc.h"
-#include "bitmap.h"
 #include "extent_map.h"
 #include "heartbeat.h"
 #include "inode.h"
@@ -739,7 +738,6 @@
 {
 	ocfs_super *osb;
 	__u32 numbits, freebits;
-	unsigned int reserved_bits;
 	int status, ret = 0;
 	ocfs2_dinode *bm_lock;
 	struct buffer_head *bh = NULL;
@@ -770,23 +768,16 @@
 
 	bm_lock = (ocfs2_dinode *) bh->b_data;
 
-	freebits = numbits = osb->cluster_bitmap.validbits;
+	numbits = le32_to_cpu(bm_lock->id1.bitmap1.i_total);
+	freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
 
-	if (numbits >= bm_lock->id1.bitmap1.i_used)
-	    freebits -= bm_lock->id1.bitmap1.i_used;
-
-	/* take out the space reserved for system files */
-	reserved_bits = ocfs2_clusters_for_bytes(sb, 8 * ONE_MEGA_BYTE);
-	freebits -= reserved_bits;
-
 	buf->f_type = OCFS_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_namelen = OCFS2_MAX_FILENAME_LENGTH;
 	buf->f_bavail = buf->f_bfree;
 	buf->f_blocks = (sector_t) ((unsigned long) (numbits) *
 			(unsigned long) (osb->s_clustersize >>
-					 osb->sb->s_blocksize_bits) -
-				reserved_bits);
+					 osb->sb->s_blocksize_bits));
 	buf->f_bfree = (sector_t) (freebits *
 			(osb->s_clustersize >> osb->sb->s_blocksize_bits));
 	buf->f_bavail = buf->f_bfree;
@@ -1161,11 +1152,6 @@
 	}
 	spin_unlock (&mount_cnt_lock);
 
-	down (&(OcfsGlobalCtxt.global_res));
-	ocfs_uninitialize_bitmap(&osb->cluster_bitmap);
-//    list_del(&osb->osb_next);  /* this has been moved into ocfs_delete_osb */
-	up (&(OcfsGlobalCtxt.global_res));
-
 	atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);
 	if (AcquiredOSB) {
 		up (&(osb->osb_res));
@@ -1325,6 +1311,7 @@
 	u64 p_blkno;
 	struct buffer_head *publish_bh = NULL;  /* our own publish sector */
 	struct buffer_head **publish_bhs = NULL; /* all the publish sectors */
+	struct buffer_head *bitmap_bh = NULL;
 	int i;
 	ocfs2_dinode *di = NULL;
 	struct inode *inode = NULL;
@@ -1515,6 +1502,7 @@
 	memcpy(osb->uuid, di->id2.i_super.s_uuid, MAX_VOL_ID_LENGTH);
 	osb->root_blkno = le64_to_cpu(di->id2.i_super.s_root_blkno);
 	osb->system_dir_blkno = le64_to_cpu(di->id2.i_super.s_system_dir_blkno);
+	osb->first_cluster_group_blkno = le64_to_cpu(di->id2.i_super.s_first_cluster_group);
 	printk("vol_label: %s\n", osb->vol_label);
 	{
 		int ttt;
@@ -1611,39 +1599,21 @@
 		goto bail;
 	}
 
-	status = ocfs2_extent_map_get_blocks(inode, 0ULL, 1, &p_blkno,
-					     NULL);
+	osb->bitmap_blkno = OCFS_I(inode)->ip_blkno;
+
+	status = ocfs_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0, inode);
+	iput(inode);
 	if (status < 0) {
 		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
+	di = (ocfs2_dinode *) bitmap_bh->b_data;
+	osb->bitmap_cpg = le32_to_cpu(di->id2.i_chain.cl_cpg);
+	osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total);
+	brelse(bitmap_bh);
+	printk("cluster bitmap inode: %llu, chains per group: %u\n",
+	       osb->bitmap_blkno, osb->bitmap_cpg);
 
-	/* for now, just one extent... but in the future... */
-	osb->bitmap_blkno = p_blkno;
-	osb->bitmap_blocks =
-		ocfs2_clusters_to_blocks(inode->i_sb,
-					 OCFS_I(inode)->ip_clusters);
-	osb->num_clusters = OCFS_I(inode)->u.ip_bitinfo.total_bits;
-	printk("bitmap_blkno=%llu, bitmap_blocks=%u, num_clusters=%u\n",
-	       osb->bitmap_blkno, osb->bitmap_blocks, osb->num_clusters);
-	
-	ocfs_initialize_bitmap(osb->sb, &osb->cluster_bitmap,
-			       osb->num_clusters,
-			       (u32)(ocfs2_clusters_to_bytes(inode->i_sb,
-							     OCFS_I(inode)->ip_clusters) << 3));
-	/* read the whole cluster bitmap off disk, even though we only
-	 * need the beginning of it. */
-	status = ocfs_read_blocks(osb,
-				  osb->bitmap_blkno,
-				  osb->bitmap_blocks,
-				  osb->cluster_bitmap.chunk, 0, inode);
-	if (status < 0) {
-		LOG_ERROR_STATUS (status);
-		goto bail;
-	}
-	iput(inode);
-
-
 	osb->prealloc_lock = 0;
 
 



More information about the Ocfs2-commits mailing list