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

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Thu Nov 4 19:37:42 CST 2004


Author: mfasheh
Date: 2004-11-04 19:37:41 -0600 (Thu, 04 Nov 2004)
New Revision: 1625

Modified:
   branches/cluster-groups/src/alloc.c
   branches/cluster-groups/src/localalloc.c
   branches/cluster-groups/src/ocfs_journal.h
   branches/cluster-groups/src/suballoc.c
   branches/cluster-groups/src/suballoc.h
Log:
* factor out the descriptor search stuff into seperate functions for  
  metadata and data. 

* teach the suballocation stuff how to try other chains if the one it picked 
  winds up being empty (this will only ever really happen with data
  allocation).

* clean up and rework some of the journal credits affected by this stuff.



Modified: branches/cluster-groups/src/alloc.c
===================================================================
--- branches/cluster-groups/src/alloc.c	2004-11-04 22:14:37 UTC (rev 1624)
+++ branches/cluster-groups/src/alloc.c	2004-11-05 01:37:41 UTC (rev 1625)
@@ -1125,7 +1125,7 @@
 	}
 
 	OCFS_ASSERT(delete_blk);
-	status = ocfs_free_clusters(osb, handle, tc->tc_bitmap_inode,
+	status = ocfs_free_clusters(handle, tc->tc_bitmap_inode,
 				    tc->tc_bitmap_bh, delete_blk, 
 				    clusters_to_del);
 	if (status < 0) {

Modified: branches/cluster-groups/src/localalloc.c
===================================================================
--- branches/cluster-groups/src/localalloc.c	2004-11-04 22:14:37 UTC (rev 1624)
+++ branches/cluster-groups/src/localalloc.c	2004-11-05 01:37:41 UTC (rev 1625)
@@ -770,7 +770,7 @@
 			       "%u (la_start_blk = %llu, blkno = %llu)\n", 
 			       count, start, la_start_blk, blkno);
 
-			status = ocfs_free_clusters(osb, handle, main_bm_inode,
+			status = ocfs_free_clusters(handle, main_bm_inode,
 						    main_bm_bh, blkno, count);
 			if (status < 0) {
 				LOG_ERROR_STATUS(status);

Modified: branches/cluster-groups/src/ocfs_journal.h
===================================================================
--- branches/cluster-groups/src/ocfs_journal.h	2004-11-04 22:14:37 UTC (rev 1624)
+++ branches/cluster-groups/src/ocfs_journal.h	2004-11-05 01:37:41 UTC (rev 1625)
@@ -319,6 +319,9 @@
  * prev. group desc. if we relink. */
 #define OCFS_SUBALLOC_ALLOC (3)
 
+/* dinode + group descriptor update. We don't relink on free yet. */
+#define OCFS_SUBALLOC_FREE  (2)
+
 /* data block for new dir/symlink, 2 for bitmap updates (bitmap fe +
  * bitmap block for the new bit) */
 #define OCFS_DIR_LINK_ADDITIONAL_CREDITS (1 + 2)
@@ -329,7 +332,8 @@
 			    + OCFS_DIR_LINK_ADDITIONAL_CREDITS)
 
 /* local alloc metadata change + main bitmap updates */
-#define OCFS_WINDOW_MOVE_CREDITS (OCFS_INODE_UPDATE_CREDITS + 8 + 5)
+#define OCFS_WINDOW_MOVE_CREDITS (OCFS_INODE_UPDATE_CREDITS                   \
+				  + OCFS_SUBALLOC_ALLOC + OCFS_SUBALLOC_FREE)
 
 /* used when we don't need an allocation change for a dir extend. One
  * for the dinode, one for the new block. */
@@ -358,16 +362,17 @@
 					   u32 bits_wanted)
 {
 	int bitmap_blocks, sysfile_bitmap_blocks, dinode_blocks;
-	/* take advantage of the fact that we always allocate in one 
-	 * large chunk. */
-	bitmap_blocks = ocfs_blocks_for_bits(sb, bits_wanted) + 1;
 
+	/* bitmap dinode, group desc. + relinked group. */
+	bitmap_blocks = OCFS_SUBALLOC_ALLOC;
+
 	/* we might need to shift tree depth so lets assume an
-	 * absolute worst case of complete fragmentation so for each
-	 * new metadata block we have a descriptor and the actual
-	 * block and of course 1 credit for the metadata dinode
-	 * update. */
-	sysfile_bitmap_blocks = 1 + 3 * ocfs2_extend_meta_needed(fe);
+	 * absolute worst case of complete fragmentation.  Even with
+	 * that, we only need one update for the dinode, and then
+	 * however many metadata chunks needed * a remaining suballoc
+	 * alloc. */
+	sysfile_bitmap_blocks = 1 + 
+		(OCFS_SUBALLOC_ALLOC - 1) * ocfs2_extend_meta_needed(fe);
 
 	/* this does not include *new* metadata blocks, which are
 	 * accounted for in sysfile_bitmap_blocks. fe +
@@ -394,7 +399,7 @@
 						unsigned int cpg)
 {
 	int blocks;
-	int bitmap_blocks = ocfs_blocks_for_bits(sb, cpg) + 1;
+	int bitmap_blocks = OCFS_SUBALLOC_ALLOC + 1;
 	/* parent inode update + new block group header + bitmap inode update 
 	   + bitmap blocks affected */
 	blocks = 1 + 1 + 1 + bitmap_blocks;
@@ -420,9 +425,9 @@
 	    && ((last_el->l_recs[i].e_clusters - clusters_to_del) == 0))
 		credits += 1 + fe->id2.i_list.l_tree_depth;
 
-	/* bitmap fe + bitmap blocks covered by this extent */
-	bitmap_blocks = 1 + ocfs_blocks_for_bits(sb, 
-						 clusters_to_del);
+	/* bitmap fe + group descriptor */
+	bitmap_blocks = OCFS_SUBALLOC_FREE;
+
 	credits += bitmap_blocks;
 
 	return(credits);

Modified: branches/cluster-groups/src/suballoc.c
===================================================================
--- branches/cluster-groups/src/suballoc.c	2004-11-04 22:14:37 UTC (rev 1624)
+++ branches/cluster-groups/src/suballoc.c	2004-11-05 01:37:41 UTC (rev 1625)
@@ -59,8 +59,21 @@
 static int ocfs_block_group_alloc(ocfs_super *osb, 
 				  struct inode *alloc_inode,
 				  struct buffer_head *bh);
+static int ocfs2_cluster_group_search(struct inode *inode,
+				      struct buffer_head *group_bh,
+				      u32 bits_wanted, u32 min_bits,
+				      u16 *bit_off, u16 *bits_found);
+static int ocfs2_block_group_search(struct inode *inode,
+				    struct buffer_head *group_bh,
+				    u32 bits_wanted, u32 min_bits,
+				    u16 *bit_off, u16 *bits_found);
+static int ocfs_search_suballoc_chain(ocfs2_alloc_context *ac,
+				      u32 bits_wanted,
+				      u32 min_bits,
+				      u16 *bit_off,
+				      unsigned int *num_bits,
+				      u64 *bg_blkno);
 static int ocfs_claim_suballoc_bits(ocfs_super *osb,
-				    ocfs_journal_handle *handle,
 				    ocfs2_alloc_context *ac,
 				    u32 bits_wanted,
 				    u32 min_bits,
@@ -488,6 +501,7 @@
 	}
 
 	(*ac)->ac_inode = igrab(alloc_inode);
+	(*ac)->ac_group_search = ocfs2_block_group_search;
 
 	status = ocfs_reserve_suballoc_bits(osb, (*ac));
 	if (status < 0) {
@@ -535,6 +549,7 @@
 	}
 
 	(*ac)->ac_inode = igrab(alloc_inode);
+	(*ac)->ac_group_search = &ocfs2_block_group_search;
 
 	status = ocfs_reserve_suballoc_bits(osb, *ac);
 	if (status < 0) {
@@ -612,6 +627,7 @@
 		}
 		(*ac)->ac_which = OCFS_AC_USE_MAIN;
 		(*ac)->ac_inode = igrab(main_bitmap_inode);
+		(*ac)->ac_group_search = &ocfs2_cluster_group_search;
 		status = ocfs_reserve_suballoc_bits(osb, *ac);
 		if (status < 0) {
 			LOG_ERROR_STATUS(status);
@@ -885,41 +901,89 @@
 	return bg->bg_free_bits_count > wanted;
 }
 
-/* will give out up to bits_wanted contiguous bits. */
-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)
+/* return 0 to keep searching, > 0 on succes (and populate the return
+ * values) and < 0 on failure. -ENOSPC means that we hit the end of
+ * the chain without finding anything. */
+static int ocfs2_cluster_group_search(struct inode *inode,
+				      struct buffer_head *group_bh,
+				      u32 bits_wanted, u32 min_bits,
+				      u16 *bit_off, u16 *bits_found)
 {
+	int ret = 0;
+	ocfs2_group_desc *bg = (ocfs2_group_desc *) group_bh->b_data;
+	u16 tmp_off, tmp_found;
+
+	OCFS_ASSERT(ocfs2_is_cluster_bitmap(inode));
+
+	if (bg->bg_free_bits_count) {
+		ret = ocfs_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+						       group_bh, bits_wanted,
+						       &tmp_off, &tmp_found);
+		if (ret == -ENOSPC)
+			ret = 0;
+		else if (!ret) {
+			if (min_bits <= tmp_found) {
+				*bit_off = tmp_off;
+				*bits_found = tmp_found;
+				ret = 1; /* success */
+			}
+		}
+	}
+
+	if (!ret && !bg->bg_next_group)
+		ret = -ENOSPC;
+	return ret;
+}
+
+static int ocfs2_block_group_search(struct inode *inode,
+				    struct buffer_head *group_bh,
+				    u32 bits_wanted, u32 min_bits,
+				    u16 *bit_off, u16 *bits_found)
+{
+	int ret = 0;
+	ocfs2_group_desc *bg = (ocfs2_group_desc *) group_bh->b_data;
+
+	OCFS_ASSERT(min_bits == 1);
+	OCFS_ASSERT(!ocfs2_is_cluster_bitmap(inode));
+
+	if (bg->bg_free_bits_count) {
+		ret = ocfs_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
+						       group_bh, bits_wanted,
+						       bit_off, bits_found);
+		if (ret == -ENOSPC)
+			ret = 0;
+		else if (!ret)
+			ret = 1; /* success */
+	} else if (!bg->bg_next_group) {
+		/* This really shouldn't happen... */
+		LOG_ERROR_ARGS("Failure to find free space in suballoc "
+			       "chain!\n");
+		ret = -ENOSPC;
+	}
+	return ret;
+}
+
+static int ocfs_search_suballoc_chain(ocfs2_alloc_context *ac,
+				      u32 bits_wanted,
+				      u32 min_bits,
+				      u16 *bit_off,
+				      unsigned int *num_bits,
+				      u64 *bg_blkno)
+{
 	int status;
+	ocfs_journal_handle *handle = ac->ac_handle;
 	struct inode *alloc_inode = ac->ac_inode;
+	ocfs_super *osb = OCFS2_SB(alloc_inode->i_sb);
 	struct buffer_head *group_bh = NULL;
 	struct buffer_head *prev_group_bh = NULL;
-	ocfs2_chain_list *cl;
-	ocfs2_dinode *fe;
+	ocfs2_dinode *fe = (ocfs2_dinode *) ac->ac_bh->b_data;
+	ocfs2_chain_list *cl = (ocfs2_chain_list *) &fe->id2.i_chain;
 	ocfs2_group_desc *bg;
 	u16 chain, tmp_bits;
 	u64 next_group;
 
-	LOG_ENTRY();
 
-	OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
-	OCFS_ASSERT(ac->ac_handle == handle);
-	OCFS_ASSERT(bits_wanted <= (ac->ac_bits_wanted - ac->ac_bits_given));
-	OCFS_ASSERT(ac->ac_bh);
-
-	fe = (ocfs2_dinode *) ac->ac_bh->b_data;
-	OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
-	OCFS_ASSERT_RO(fe->id1.bitmap1.i_used < fe->id1.bitmap1.i_total);
-
-	cl = (ocfs2_chain_list *) &fe->id2.i_chain;
-
-	chain = ocfs2_find_victim_chain(cl);
-
+	chain = ac->ac_chain;
 	LOG_TRACE_ARGS("trying to alloc %u bits from chain %u, inode %llu\n",
 		       bits_wanted, chain, OCFS_I(alloc_inode)->ip_blkno);
 
@@ -929,13 +993,14 @@
 		LOG_ERROR_STATUS(status);
 		goto bail;
 	}
-
 	bg = (ocfs2_group_desc *) group_bh->b_data;
 	OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
 
 	/* for now, the chain search is a bit simplistic. We just use
 	 * the 1st group with any empty bits. */
-	while (!bg->bg_free_bits_count) {
+	while ((status = ac->ac_group_search(alloc_inode, group_bh, 
+					     bits_wanted, min_bits, bit_off, 
+					     &tmp_bits)) == 0) {
 		/*
 		 * This means we've walked off the end of a chain that
 		 * we thought had bits, but didn't.  While this
@@ -960,21 +1025,11 @@
 		bg = (ocfs2_group_desc *) group_bh->b_data;
 		OCFS_ASSERT_RO(IS_VALID_GROUP_DESC(bg));
 	}
-
-	status = ocfs_block_group_find_clear_bits(osb, 
-						  group_bh, 
-						  bits_wanted, 
-						  bit_off,
-						  &tmp_bits);
 	if (status < 0) {
-		LOG_ERROR_STATUS(status);
+		if (status != -ENOSPC)
+			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;
 
@@ -993,8 +1048,9 @@
 	 * Do this *after* figuring out how many bits we're taking out
 	 * of our target group.
 	 */
-	if ((prev_group_bh) 
-	    && (ocfs_block_group_reasonably_empty(bg, *num_bits))) {
+	if (ac->ac_allow_chain_relink &&
+	    (prev_group_bh) &&
+	    (ocfs_block_group_reasonably_empty(bg, *num_bits))) {
 		status = ocfs_relink_block_group(handle, alloc_inode,
 						 ac->ac_bh, group_bh, 
 						 prev_group_bh, chain);
@@ -1054,6 +1110,73 @@
 	return status;
 }
 
+/* will give out up to bits_wanted contiguous bits. */
+static int ocfs_claim_suballoc_bits(ocfs_super *osb,
+				    ocfs2_alloc_context *ac,
+				    u32 bits_wanted,
+				    u32 min_bits,
+				    u16 *bit_off,
+				    unsigned int *num_bits,
+				    u64 *bg_blkno)
+{
+	int status;
+	u16 victim, i;
+	ocfs2_chain_list *cl;
+	ocfs2_dinode *fe;
+
+	LOG_ENTRY();
+
+	OCFS_ASSERT(ac->ac_bits_given < ac->ac_bits_wanted);
+	OCFS_ASSERT(bits_wanted <= (ac->ac_bits_wanted - ac->ac_bits_given));
+	OCFS_ASSERT(ac->ac_bh);
+
+	fe = (ocfs2_dinode *) ac->ac_bh->b_data;
+	OCFS_ASSERT_RO(IS_VALID_FILE_ENTRY(fe));
+	OCFS_ASSERT_RO(fe->id1.bitmap1.i_used < fe->id1.bitmap1.i_total);
+
+	cl = (ocfs2_chain_list *) &fe->id2.i_chain;
+
+	victim = ocfs2_find_victim_chain(cl);
+	ac->ac_chain = victim;
+	ac->ac_allow_chain_relink = 1;
+
+	status = ocfs_search_suballoc_chain(ac, bits_wanted, min_bits, bit_off,
+					    num_bits, bg_blkno);
+	if (!status)
+		goto bail;
+	if (status < 0 && status != -ENOSPC) {
+		LOG_ERROR_STATUS(status);
+		goto bail;
+	}
+
+	/* If we didn't pick a good victim, then just default to
+	 * searching each chain in order. Don't allow chain relinking
+	 * because we only calculate enough journal credits for one
+	 * relink per alloc. */
+	ac->ac_allow_chain_relink = 0;
+	for (i = 0; i < cl->cl_next_free_rec; i ++) {
+		if (i == victim)
+			continue;
+		if (!cl->cl_recs[i].c_free)
+			continue;
+
+		ac->ac_chain = i;
+		status = ocfs_search_suballoc_chain(ac, bits_wanted, min_bits, 
+						    bit_off, num_bits, 
+						    bg_blkno);
+		if (!status)
+			break;
+		if (status < 0 && status != -ENOSPC) {
+			LOG_ERROR_STATUS(status);
+			goto bail;
+		}
+	}
+bail:
+
+	LOG_EXIT_STATUS(status);
+	return status;
+}
+
 int ocfs_claim_metadata(ocfs_super *osb,
 			ocfs_journal_handle *handle,
 			ocfs2_alloc_context *ac,
@@ -1071,7 +1194,6 @@
 	OCFS_ASSERT(ac->ac_handle == handle);
 
 	status = ocfs_claim_suballoc_bits(osb,
-					  handle,
 					  ac,
 					  bits_wanted,
 					  1,
@@ -1110,7 +1232,6 @@
 	OCFS_ASSERT(ac->ac_handle == handle);
 
 	status = ocfs_claim_suballoc_bits(osb,
-					  handle,
 					  ac,
 					  1,
 					  1,
@@ -1167,12 +1288,19 @@
 						     cluster_start,
 						     num_clusters);
 	} else {
-		/* clamp this down to a realistic size. */
+		if (min_clusters > (osb->bitmap_cpg - 1)) {
+			/* The only paths asking for contiguousness
+			 * should know about this already. */
+			LOG_ERROR_ARGS("minimum allocation requested exceeds "
+				       "group bitmap size!");
+			status = -ENOSPC;
+			goto bail;
+		}
+		/* clamp the current request 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,
@@ -1411,8 +1539,7 @@
 							     data_blkno - *bg_blkno);
 }
 
-int ocfs_free_clusters(ocfs_super *osb,
-		       ocfs_journal_handle *handle,
+int ocfs_free_clusters(ocfs_journal_handle *handle,
 		       struct inode *bitmap_inode,
 		       struct buffer_head *bitmap_bh,
 		       u64 start_blk,

Modified: branches/cluster-groups/src/suballoc.h
===================================================================
--- branches/cluster-groups/src/suballoc.h	2004-11-04 22:14:37 UTC (rev 1624)
+++ branches/cluster-groups/src/suballoc.h	2004-11-05 01:37:41 UTC (rev 1625)
@@ -26,6 +26,13 @@
 #ifndef _CHAINALLOC_H_
 #define _CHAINALLOC_H_
 
+typedef int (group_search_t)(struct inode *,
+			     struct buffer_head *,
+			     u32,
+			     u32,
+			     u16 *,
+			     u16 *);
+
 typedef struct _ocfs2_alloc_context {
 	struct inode *ac_inode;    /* which bitmap are we allocating from? */
 	struct buffer_head *ac_bh; /* file entry bh */
@@ -36,7 +43,12 @@
 #define OCFS_AC_USE_INODE 3
 #define OCFS_AC_USE_META  4
 	u32    ac_which;
-	ocfs_journal_handle *ac_handle; /* debugging mostly. */
+	ocfs_journal_handle *ac_handle;
+
+	/* these are used by the chain search */
+	u16    ac_chain;
+	int    ac_allow_chain_relink;
+	group_search_t *ac_group_search;
 } ocfs2_alloc_context;
 
 void ocfs_free_alloc_context(ocfs2_alloc_context *ac);
@@ -84,8 +96,7 @@
 			    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,
+int ocfs_free_clusters(ocfs_journal_handle *handle,
 		       struct inode *bitmap_inode,
 		       struct buffer_head *bitmap_bh,
 		       u64 start_blk,



More information about the Ocfs2-commits mailing list