[Ocfs2-tools-commits] zab commits r397 - in trunk: fsck.ocfs2 libocfs2 libocfs2/include mkfs.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Fri Nov 12 17:26:27 CST 2004


Author: zab
Date: 2004-11-12 17:26:25 -0600 (Fri, 12 Nov 2004)
New Revision: 397

Modified:
   trunk/fsck.ocfs2/pass0.c
   trunk/libocfs2/chainalloc.c
   trunk/libocfs2/include/ocfs2.h
   trunk/libocfs2/include/ocfs2_fs.h
   trunk/mkfs.ocfs2/mkfs.c
Log:
o ensure that the cluster chain alloc descs are at the right offsets in the fs
o verify the cluster chain alloc linkage
o add an ocfs2_init_group_desc() which just fills the fields
o add an ocfs2_calc_cluster_groups() func to have cluster group math in
  one place


Modified: trunk/fsck.ocfs2/pass0.c
===================================================================
--- trunk/fsck.ocfs2/pass0.c	2004-11-12 22:52:03 UTC (rev 396)
+++ trunk/fsck.ocfs2/pass0.c	2004-11-12 23:26:25 UTC (rev 397)
@@ -19,20 +19,29 @@
  *
  * --
  *
- * Pass 0 verifies that the inode suballocators can be iterated over by later
- * passes without risk of running into corruption.  This is so the passes can
- * build up state without having to worry about tearing it down half way
- * through to clean up the suballocators.  For now fsck treats failure to find
- * and verify the suballocator inodes themselves as fatal.  It will only clean
- * up the data they point to.
+ * Pass 0 verifies that the basic linkage of the various chain allocators is
+ * intact so that future passes can use them in place safely.  The actual
+ * bitmaps in the allocators aren't worried about here.  Later passes will
+ * clean them up by loading them in to memory, updating them, and writing them
+ * back out.
  *
+ * Pass 1, for example, wants to iterate over the inode blocks covered by the
+ * inode chain allocators so it can verify them and update the allocation
+ * bitmaps for inodes that are still in use.
+ *
+ * The cluster chain allocator is a special case because its group descriptors
+ * are at regular predictable offsets throughout the volume.  fsck forces these
+ * block descriptors into service and removes and block descriptors in the
+ * chain that aren't at these offsets.
+ *
  * pass0 updates group descriptor chains on disk.
  *
  * XXX
- * 	track used blocks that iteration won't see?
+ * 	track blocks and clusters we see here that iteration won't
  * 	verify more inode fields?
- * 	use prompt to mark soft errors
  * 	make sure blocks don't overlap as part of cluster tracking
+ * 	make sure _bits is correct, pass in from callers
+ * 	generalize the messages to chain allocators instead of inode allocators
  */
 
 #include <string.h>
@@ -149,28 +158,43 @@
 	return 0;
 }
 
-/* returns non-zero if the chain_rec was updated */
+/*
+ * this function is pretty hairy.  for dynamic chain allocators
+ * it is just walking the chains to verify the group descs
+ * and truncates a chain when it sees a link it can't follow. 
+ * The only complexity in that case is the different language for
+ * the head of the chain and the links in the chain.
+ *
+ * For static chain allocators (the cluster bitmap) it has a bitmap
+ * of blocks that should be in the chains.  it will ask to remove
+ * blocks in the chains that aren't in the bitmap and will clear
+ * the bits in the bitmaps for blocks it finds in the chains.
+ */
 static int check_chain(o2fsck_state *ost, ocfs2_dinode *di,
 		       struct chain_state *cs, ocfs2_chain_rec *chain,
-		       char *buf1, char *buf2)
+		       char *buf1, char *buf2, ocfs2_bitmap *allowed)
 {
 	ocfs2_group_desc *bg1 = (ocfs2_group_desc *)buf1;
 	ocfs2_group_desc *bg2 = (ocfs2_group_desc *)buf2;
-	uint64_t blkno = chain->c_blkno;
+	uint64_t blkno;
 	errcode_t ret;
-	int rc, changed = 0;
+	int rc, changed = 0, remove = 0;
+	int was_set;
 
 	verbosef("free %u total %u blkno %"PRIu64"\n", chain->c_free,
 		 chain->c_total, chain->c_blkno);
 
-	if (chain->c_blkno == 0)
+new_head:
+	blkno = chain->c_blkno;
+
+	if (blkno == 0)
 		goto out;
 
 	if (ocfs2_block_out_of_range(ost->ost_fs, blkno)) {
 		if (prompt(ost, PY, "Chain record %d in group allocator inode "
 			    "%"PRIu64" points to block %"PRIu64" which is out "
- 			    "of range.  fsck can't continue without deleting "
-			    "this chain.  Delete it?", cs->cs_chain_no,
+ 			    "of range.  Empty this chain by deleting this "
+			    "invalid block reference?", cs->cs_chain_no,
 			    di->i_blkno, blkno))  {
 			chain->c_blkno = 0;
 			changed = 1;
@@ -179,6 +203,18 @@
 		goto out;
 	}
 
+	if (allowed) {
+		ocfs2_bitmap_test(allowed, blkno, &was_set);
+		if (!was_set &&
+		    prompt(ost, PY, "Chain record %d in chain allocator inode "
+			   "%"PRIu64" points to group descriptor block "
+			   "%"PRIu64" which should not be found in the "
+			   "allocator.  Remove this group descriptor block?",
+			   cs->cs_chain_no, di->i_blkno, blkno))  {
+			remove = 1;
+		}
+	}
+
 	ret = ocfs2_read_group_desc(ost->ost_fs, blkno, buf1);
 	if (ret) {
 		com_err(whoami, ret, "while reading a group descriptor from "
@@ -188,6 +224,13 @@
 		goto out;
 	}
 
+	if (remove) {
+		chain->c_blkno = bg1->bg_next_group;
+		changed = 1;
+		remove = 0;
+		goto new_head;
+	}
+
 	ret = check_group_desc(ost, di, cs, bg1, blkno);
 	if (ret) {
 		if (prompt(ost, PY, "Chain %d in group allocator inode "
@@ -200,9 +243,31 @@
 		goto out;
 	}
 
-	/* read in each group desc and check it.  if we see an error we try
-	 * to truncate the list after the last good desc */
+	if (allowed)
+		ocfs2_bitmap_clear(allowed, chain->c_blkno, NULL);
+
+	/* read in each group desc and check it.  In this loop bg1 is 
+	 * verified and in the chain.  it's bg2 that is considered.  if
+	 * bg2 is found lacking we overwrite bg1's next_group and check
+	 * again */
 	while (bg1->bg_next_group) {
+		int write = 0;
+		/* see if we're about to reference a block that we shouldn't */
+		if (allowed) {
+			ocfs2_bitmap_test(allowed, bg1->bg_next_group, 
+					  &was_set);
+			if (!was_set &&
+			    prompt(ost, PY, "Chain %d in chain allocator "
+				   "inode %"PRIu64" points to group "
+				   "descriptor block %"PRIu64" which should "
+				   "not be found in the allocator.  Remove "
+				   "this group descriptor block?",
+				   cs->cs_chain_no, di->i_blkno, blkno))  {
+				remove = 1;
+			}
+		}
+		/* read the next desc in either to verify it or just to
+		 * grab the reference to the desc after it */
 		ret = ocfs2_read_group_desc(ost->ost_fs, bg1->bg_next_group,
 					    buf2);
 		if (ret) {
@@ -214,8 +279,19 @@
 			goto out;
 		} 
 
+		/* skip over this desc that we've been told to remove it */
+		if (remove) {
+			bg1->bg_next_group = bg2->bg_next_group;
+			write = 1;
+			remove = 0;
+			goto write_bg1;
+		}
+
 		rc = check_group_desc(ost, di, cs, bg2, bg1->bg_next_group);
 		if (rc == 0) {
+			if (allowed)
+				ocfs2_bitmap_clear(allowed, bg2->bg_blkno,
+						   NULL);
 			memcpy(buf1, buf2, ost->ost_fs->fs_blocksize);
 			continue;
 		}
@@ -226,6 +302,11 @@
 			   "valid descriptor block?", cs->cs_chain_no,
 			   di->i_blkno, bg1->bg_next_group)) {
 			bg1->bg_next_group = 0;
+			write = 1;
+		}
+
+write_bg1:
+		if (write) {
 			ret = ocfs2_write_group_desc(ost->ost_fs, 
 						     bg1->bg_blkno,
 						     (char *)bg1);
@@ -238,11 +319,9 @@
 					di->i_blkno);
 				ost->ost_write_error = 1;
 			}
-			break;
 		}
 	}
 
-	/* XXX exit if it isn't updated? */
 	if (cs->cs_total_bits != chain->c_total ||
 	    cs->cs_free_bits != chain->c_free) {
 		if (prompt(ost, PY, "Chain %d in allocator inode %"PRIu64" "
@@ -264,8 +343,9 @@
 
 /* If this returns 0 then the inode allocator had better be amenable to
  * iteration. */
-static errcode_t verify_inode_alloc(o2fsck_state *ost, ocfs2_dinode *di,
-				    char *buf1, char *buf2)
+static errcode_t verify_chain_alloc(o2fsck_state *ost, ocfs2_dinode *di,
+				    char *buf1, char *buf2,
+				    ocfs2_bitmap *allowed)
 {
 	struct chain_state cs = {0, };
 	ocfs2_chain_list *cl;
@@ -344,7 +424,7 @@
 		cs = (struct chain_state) {
 			.cs_chain_no = i,
 		};
-		changed |= check_chain(ost, di, &cs, cr, buf1, buf2);
+		changed |= check_chain(ost, di, &cs, cr, buf1, buf2, allowed);
 
 		if (cr->c_blkno != 0) {
 			free += cs.cs_free_bits;
@@ -353,8 +433,9 @@
 		}
 
 		if (prompt(ost, PY, "Chain %d in allocator inode %"PRIu64" "
-			   "isn't in use any more.  Remove it from the inode?",
-			   cs.cs_chain_no, di->i_blkno)) {
+			   "is empty.  Remove it from the chain record "
+			   "array in the inode and shift further chains "
+			   "into its place?", cs.cs_chain_no, di->i_blkno)) {
 
 			if (!trust_next_free) {
 				printf("Can't remove the chain becuase "
@@ -391,22 +472,175 @@
 	}
 
 	if (changed) {
-		/* if we're writing it anyway, we might as well clear the
-		 * unused chain entries */ 
-		if (cl->cl_next_free_rec != max_count)
-			memset(&cl->cl_recs[cl->cl_next_free_rec], 0,
-			       (max_count - cl->cl_next_free_rec) * 
-			       sizeof(ocfs2_chain_rec));
+		ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
+		if (ret) {
+			com_err(whoami, ret, "while writing inode alloc inode "
+				    "%"PRIu64, di->i_blkno);
+			ost->ost_write_error = 1;
+			ret = 0;
+		}
+	}
 
+out:
+	return ret;
+}
+
+/* we know that the bitmap descs are at predictable places in the fs.  we
+ * walk these locations and make sure there are valid group descs
+ * there.  We fill a bitmap with the valid ones so that when we later walk
+ * the chains we can restrict it to the set of expected blocks and also
+ * be sure to add blocks that aren't linked in */
+static errcode_t verify_bitmap_descs(o2fsck_state *ost, ocfs2_dinode *di,
+				     char *buf1, char *buf2)
+{
+	struct ocfs2_cluster_group_sizes cgs;
+	uint32_t i, max_recs;
+	uint16_t bits;
+	uint64_t blkno;
+	ocfs2_group_desc *bg = (ocfs2_group_desc *)buf1;
+	errcode_t ret;
+	struct chain_state cs;
+	int changed = 0;
+	ocfs2_chain_rec *rec;
+	ocfs2_bitmap *bitmap_descs = NULL;
+
+	ret = ocfs2_block_bitmap_new(ost->ost_fs, "bitmap group descriptors",
+				     &bitmap_descs);
+	if (ret) {
+		com_err(whoami, ret, "while allocating bitmap descs bitmap");
+		goto out;
+	}
+	
+	ocfs2_calc_cluster_groups(ost->ost_fs->fs_clusters,
+				  ost->ost_fs->fs_blocksize, &cgs);
+
+	max_recs = ocfs2_chain_recs_per_inode(ost->ost_fs->fs_blocksize);
+
+	for (i = 0; i < cgs.cgs_cluster_groups; i++) {
+		if (i == 0)
+			blkno = OCFS2_SUPER_BLOCK_BLKNO + 1;
+		else
+			blkno = i * cgs.cgs_cpg * 
+				(ost->ost_fs->fs_clustersize /
+				 ost->ost_fs->fs_blocksize);
+
+		verbosef("looking for cluster bitmap desc at %"PRIu64"\n",
+			 blkno);
+
+		if (i == cgs.cgs_cluster_groups - 1)
+			bits = cgs.cgs_tail_group_bits;
+		else
+			bits = cgs.cgs_cpg;
+
+		cs.cs_chain_no = i % max_recs;
+
+		ret = ocfs2_read_group_desc(ost->ost_fs, blkno, (char *)bg);
+		if (ret) {
+			com_err(whoami, ret, "while reading a cluster bitmap "
+				"group descriptor from block %"PRIu64,
+				blkno);
+			continue;
+		}
+
+		/* XXX this is kind of awkward.  check_group_desc may change
+		 * bg_chain for a given descriptor but won't update the
+		 * linkage.  So when we call in from the iterator we'll just
+		 * link it back under a given chain.  I'm willing to live with
+		 * that for now. */
+		ret = check_group_desc(ost, di, &cs, bg, blkno);
+		if (ret == OCFS2_ET_BAD_GROUP_DESC_MAGIC &&
+		    prompt(ost, PY, "Cluster group descriptor at block "
+			   "%"PRIu64" doesn't even have a valid signature. "
+			   "Initialize it and mark it for inclusion in the "
+			   "cluster group chain?", blkno)) {
+
+			ocfs2_init_group_desc(ost->ost_fs, bg, blkno,
+					      di->i_generation, di->i_blkno,
+					      bits, cs.cs_chain_no);
+
+			ret = ocfs2_write_group_desc(ost->ost_fs, bg->bg_blkno,
+						     (char *)bg);
+			if (ret) {
+				com_err(whoami, ret, "while writing a cluster "
+					"group descriptor at block %"PRIu64,
+					blkno);
+				ost->ost_write_error = 1;
+				continue;
+			}
+		}
+		if (ret == 0)
+			ocfs2_bitmap_set(bitmap_descs, blkno, NULL);
+	}
+
+	ret = verify_chain_alloc(ost, di, buf1, buf2, bitmap_descs);
+	if (ret) {
+		com_err(whoami, ret, "while looking up chain allocator inode "
+			"%"PRIu64, di->i_blkno);
+		goto out;
+	}
+
+	/* find the blocks that we think should have been in the chains
+	 * but which weren't found */
+	for (blkno = OCFS2_SUPER_BLOCK_BLKNO + 1;
+	     !ocfs2_bitmap_find_next_set(bitmap_descs, blkno, &blkno);
+	     blkno++) {
+
+		if (!prompt(ost, PY, "Block %"PRIu64" should be a group "
+			    "descriptor for the bitmap chain allocator but it "
+			    "wasn't found in any chains.  Link it into the "
+			    "chain allocator?", blkno))
+			continue;
+
+		ret = ocfs2_read_group_desc(ost->ost_fs, blkno, (char *)bg);
+		if (ret) {
+			com_err(whoami, ret, "while reading a cluster bitmap "
+				"group descriptor from block %"PRIu64,
+				blkno);
+			continue;
+		}
+		
+		/* XXX the rest of this block links a desc into the chain
+		 * and should probably be in libocfs2 */
+		/* XXX should be more paranoid in verifying the desc? */
+		rec = &di->id2.i_chain.cl_recs[bg->bg_chain];
+		bg->bg_next_group = rec->c_blkno;
+
+		ret = ocfs2_write_group_desc(ost->ost_fs, bg->bg_blkno,
+					     (char *)bg);
+		if (ret) {
+			com_err(whoami, ret, "while writing a cluster group "
+				"descriptor at block %"PRIu64, blkno);
+			ost->ost_write_error = 1;
+			continue;
+		}
+
+		rec->c_free += bg->bg_free_bits_count;
+		rec->c_total += bg->bg_bits;
+		rec->c_blkno = blkno;
+		if (di->id2.i_chain.cl_next_free_rec <= bg->bg_chain)
+			di->id2.i_chain.cl_next_free_rec = bg->bg_chain;
+		di->id1.bitmap1.i_used += bg->bg_bits - bg->bg_free_bits_count;
+		di->id1.bitmap1.i_total += bg->bg_bits;
+		changed = 1;
+	}
+
+	/* XXX maybe we should verify the chain again now.  we might have
+	 * inserted a desc at its fixed position after some chains that
+	 * weren't in use. */
+
+	if (changed) {
 		ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
 		if (ret) {
 			com_err(whoami, ret, "while writing inode alloc inode "
 				    "%"PRIu64, di->i_blkno);
 			ost->ost_write_error = 1;
+			ret = 0;
 		}
 	}
 
 out:
+	if (bitmap_descs)
+		ocfs2_bitmap_free(bitmap_descs);
 	return ret;
 }
 
@@ -424,7 +658,7 @@
 	int max_nodes = OCFS2_RAW_SB(fs->fs_super)->s_max_nodes;
 	int i, type;
 
-	printf("Pass 0: Checking allocation structures\n");
+	printf("Pass 0a: Checking cluster allocation chains\n");
 
 	ret = ocfs2_malloc_blocks(fs->fs_io, 3, &blocks);
 	if (ret) {
@@ -440,6 +674,32 @@
 		goto out;
 	}
 
+	ret = ocfs2_lookup_system_inode(fs, GLOBAL_BITMAP_SYSTEM_INODE,
+					0, &blkno);
+	if (ret) {
+		com_err(whoami, ret, "while looking up the inode "
+			"allocator type %d for node %d\n", type, i);
+		goto out;
+	}
+
+	ret = ocfs2_read_inode(ost->ost_fs, blkno, (char *)di);
+	if (ret) {
+		com_err(whoami, ret, "reading inode alloc inode "
+			"%"PRIu64" for verification", blkno);
+		goto out;
+	}
+
+	verbosef("found inode alloc %"PRIu64" at block %"PRIu64"\n",
+		 di->i_blkno, blkno);
+
+	ret = verify_bitmap_descs(ost, di, blocks + ost->ost_fs->fs_blocksize,
+				  blocks + (ost->ost_fs->fs_blocksize * 2));
+
+	if (ret)
+		goto out;
+
+	printf("Pass 0b: Checking inode allocation chains\n");
+
 	/* first the global inode alloc and then each of the node's
 	 * inode allocators */
 	type = GLOBAL_INODE_ALLOC_SYSTEM_INODE;
@@ -463,10 +723,10 @@
 		verbosef("found inode alloc %"PRIu64" at block %"PRIu64"\n",
 			 di->i_blkno, blkno);
 
-		ret = verify_inode_alloc(ost, di,
+		ret = verify_chain_alloc(ost, di,
 					 blocks + ost->ost_fs->fs_blocksize,
 					 blocks + 
-					 (ost->ost_fs->fs_blocksize * 2));
+					 (ost->ost_fs->fs_blocksize * 2), NULL);
 
 		/* XXX maybe helped by the alternate super block */
 		if (ret)

Modified: trunk/libocfs2/chainalloc.c
===================================================================
--- trunk/libocfs2/chainalloc.c	2004-11-12 22:52:03 UTC (rev 396)
+++ trunk/libocfs2/chainalloc.c	2004-11-12 23:26:25 UTC (rev 397)
@@ -32,6 +32,7 @@
 #include "ocfs2.h"
 
 #include "bitmap.h"
+#include "bitops.h"
 #include "kernel-rbtree.h"
 
 
@@ -363,7 +364,26 @@
 	return ocfs2_bitmap_test(cinode->ci_chains, blkno, oldval);
 }
 
+void ocfs2_init_group_desc(ocfs2_filesys *fs, ocfs2_group_desc *gd,
+			   uint64_t blkno, uint32_t generation,
+			   uint64_t parent_inode, uint16_t bits,
+			   uint16_t chain)
+{
+	memset(gd, 0, fs->fs_blocksize);
 
+	strcpy(gd->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
+	gd->bg_generation = generation;
+	gd->bg_size = ocfs2_group_bitmap_size(fs->fs_blocksize);
+	gd->bg_bits = bits;
+	gd->bg_chain = chain;
+	gd->bg_parent_dinode = parent_inode;
+	gd->bg_blkno = blkno;
+
+	/* First bit set to account for the descriptor block */
+	ocfs2_set_bit(0, gd->bg_bitmap);
+	gd->bg_free_bits_count = gd->bg_bits - 1;
+}
+
 #ifdef DEBUG_EXE
 #include <stdlib.h>
 #include <getopt.h>

Modified: trunk/libocfs2/include/ocfs2.h
===================================================================
--- trunk/libocfs2/include/ocfs2.h	2004-11-12 22:52:03 UTC (rev 396)
+++ trunk/libocfs2/include/ocfs2.h	2004-11-12 23:26:25 UTC (rev 397)
@@ -433,6 +433,10 @@
 
 errcode_t ocfs2_test_inode_allocated(ocfs2_filesys *fs, uint64_t blkno,
 				     int *is_allocated);
+void ocfs2_init_group_desc(ocfs2_filesys *fs, ocfs2_group_desc *gd,
+			   uint64_t blkno, uint32_t generation,
+			   uint64_t parent_inode, uint16_t bits,
+			   uint16_t chain);
 
 errcode_t ocfs2_new_dir_block(ocfs2_filesys *fs, uint64_t dir_ino,
 			      uint64_t parent_ino, char **block);
@@ -494,6 +498,27 @@
 	return (block < OCFS2_SUPER_BLOCK_BLKNO) || (block > fs->fs_blocks);
 }
 
+struct ocfs2_cluster_group_sizes {
+	uint16_t	cgs_cpg;
+	uint16_t	cgs_tail_group_bits;
+	uint32_t	cgs_cluster_groups;
+};
+static inline void ocfs2_calc_cluster_groups(uint64_t clusters, 
+					     uint64_t blocksize,
+				     struct ocfs2_cluster_group_sizes *cgs)
+{
+	uint16_t max_bits = 8 * ocfs2_group_bitmap_size(blocksize);
 
+	cgs->cgs_cpg = max_bits;
+	if (max_bits > clusters)
+		cgs->cgs_cpg = clusters;
 
+	cgs->cgs_cluster_groups = (clusters + cgs->cgs_cpg - 1) / 
+				  cgs->cgs_cpg;
+
+	cgs->cgs_tail_group_bits = clusters % cgs->cgs_cpg;
+	if (cgs->cgs_tail_group_bits == 0)
+		cgs->cgs_tail_group_bits = cgs->cgs_cpg;
+}
+
 #endif  /* _FILESYS_H */

Modified: trunk/libocfs2/include/ocfs2_fs.h
===================================================================
--- trunk/libocfs2/include/ocfs2_fs.h	2004-11-12 22:52:03 UTC (rev 396)
+++ trunk/libocfs2/include/ocfs2_fs.h	2004-11-12 23:26:25 UTC (rev 397)
@@ -466,12 +466,11 @@
 	return size;
 }
 
-static inline int ocfs2_group_bitmap_size(struct super_block *sb)
+static inline uint32_t ocfs2_group_bitmap_size(struct super_block *sb)
 {
-	int size;
+	uint32_t size;
 
-	size = sb->s_blocksize -
-		offsetof(struct _ocfs2_group_desc, bg_bitmap);
+	size = sb->s_blocksize - offsetof(struct _ocfs2_group_desc, bg_bitmap);
 
 	return size;
 }
@@ -516,12 +515,11 @@
 	return size;
 }
 
-static inline int ocfs2_group_bitmap_size(int blocksize)
+static inline uint32_t ocfs2_group_bitmap_size(int blocksize)
 {
-	int size;
+	uint32_t size;
 
-	size = blocksize -
-		offsetof(struct _ocfs2_group_desc, bg_bitmap);
+	size = blocksize - offsetof(struct _ocfs2_group_desc, bg_bitmap);
 
 	return size;
 }

Modified: trunk/mkfs.ocfs2/mkfs.c
===================================================================
--- trunk/mkfs.ocfs2/mkfs.c	2004-11-12 22:52:03 UTC (rev 396)
+++ trunk/mkfs.ocfs2/mkfs.c	2004-11-12 23:26:25 UTC (rev 397)
@@ -833,6 +833,7 @@
 	size_t pagesize;
 	errcode_t err;
 	uint32_t ret;
+	struct ocfs2_cluster_group_sizes cgs;
 
 	pagesize = getpagesize();
 
@@ -913,21 +914,12 @@
 	
 	s->reserved_tail_size = 0;
 
-	if (s->volume_size_in_clusters < 
-	    ( 8 * ocfs2_group_bitmap_size(s->blocksize))) {
-		/* small volume, only one cluster group. */
-		s->global_cpg = s->volume_size_in_clusters;
-		s->nr_cluster_groups = 1;
-		s->tail_group_bits = s->volume_size_in_clusters;
-	} else {
-		s->global_cpg = 8 * ocfs2_group_bitmap_size(s->blocksize);
-		s->nr_cluster_groups = s->volume_size_in_clusters / s->global_cpg;
-		if (s->volume_size_in_clusters % s->global_cpg) {
-			s->tail_group_bits = s->volume_size_in_clusters % s->global_cpg;
-			s->nr_cluster_groups++;
-		} else
-			s->tail_group_bits = s->global_cpg;
-	}
+	ocfs2_calc_cluster_groups(s->volume_size_in_clusters, s->blocksize,
+				  &cgs);
+	s->global_cpg = cgs.cgs_cpg;
+	s->nr_cluster_groups = cgs.cgs_cluster_groups;
+	s->tail_group_bits = cgs.cgs_tail_group_bits;
+
 #if 0
 	printf("volume_size_in_clusters = %u\n", s->volume_size_in_clusters);
 	printf("global_cpg = %u\n", s->global_cpg);



More information about the Ocfs2-tools-commits mailing list