Skip to contentSkip to conversation

ocfs2: Support for discontiguous block group.

PATCH Superseded Tao Ma 3 participants 34 messages Apr 1, 2010 OCFS2

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Tao Ma

author
#0 lore raw

cover ocfs2: Support for discontiguous block group.

Hi all,
This patch set try to implement discontiguous block group in ocfs2. We
have meet with many ENOSPC problems because of file system fragmentation and among them a big part is that we can't allocate contiguouse 4M bytes to allocate a new inode/extent block group. So this patch set is going to resolve this by supporting discontiguous block group.

01-11 are the original patches from Joel Becker, I didn't touch them so that Joel could skip them for review. ;)
12 is a patch fixing some tiny problems in 01-11. I separate it out so that it can be reviewed by Joel easily and it will be integrated into the previous 01-11 when it get acked.
13-15 are the following patches.

[View]
http://oss.oracle.com/git/?p=tma/linux-2.6.git;a=shortlog;h=discontig-bg
[Pull]
git://oss.oracle.com/git/tma/linux-2.6.git discontig-bg

For the design doc, please see
http://oss.oracle.com/osswiki/OCFS2/DesignDocs/DiscontiguousBlockGroups

The patches for ocfs2-tools support will be sent to ocfs2-tools-devel.

Regards,
Tao

author
#1 lore raw

PATCH 1/15 ocfs2: Define data structures for discontiguous block groups.

From: Joel Becker <[email protected]>

Defines the OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG feature bit and modifies struct ocfs2_group_desc for the feature.

---
 fs/ocfs2/ocfs2_fs.h |   53 ++++++++++++++++++++++++++++++++++++++++++++------
 fs/ocfs2/resize.c   |    4 +-
 fs/ocfs2/suballoc.c |    2 +-
 fs/ocfs2/super.c    |    2 +-
 4 files changed, 50 insertions(+), 11 deletions(-)
fs/ocfs2/ocfs2_fs.h +46 -7
index bb37218..055cf07 100644
@@ -165,6 +165,9 @@
 /* Refcount tree support */
 #define OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE	0x1000
 
+/* Discontigous block groups */
+#define OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG	0x2000
+
 /*
  * backup superblock flag is used to indicate that this volume
  * has backup superblocks.
@@ -840,6 +843,13 @@ struct ocfs2_dx_leaf {
 };
 
 /*
+ * Largest bitmap for a block (suballocator) group in bytes.  This limit
+ * does not affect cluster groups (global allocator).  Cluster group
+ * bitmaps run to the end of the block.
+ */
+#define OCFS2_MAX_BG_BITMAP_SIZE	256
+
+/*
  * On disk allocator group structure for OCFS2
  */
 struct ocfs2_group_desc
@@ -860,7 +870,29 @@ struct ocfs2_group_desc
 	__le64   bg_blkno;               /* Offset on disk, in blocks */
 /*30*/	struct ocfs2_block_check bg_check;	/* Error checking */
 	__le64   bg_reserved2;
-/*40*/	__u8    bg_bitmap[0];
+/*40*/	union {
+		__u8    bg_bitmap[0];
+		struct {
+			/*
+			 * Block groups may be discontiguous when
+			 * OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG is set.
+			 * The extents of a discontigous block group are
+			 * stored in bg_list.  It is a flat list.
+			 * l_tree_depth must always be zero.  A
+			 * discontiguous group is signified by a non-zero
+			 * bg_list->l_next_free_rec.  Only block groups
+			 * can be discontiguous; Cluster groups cannot.
+			 * We've never made a block group with more than
+			 * 2048 blocks (256 bytes of bg_bitmap).  This
+			 * codifies that limit so that we can fit bg_list.
+			 * bg_size of a discontiguous block group will
+			 * be 256 to match bg_bitmap_filler.
+			 */
+			__u8 bg_bitmap_filler[OCFS2_MAX_BG_BITMAP_SIZE];
+/*140*/			struct ocfs2_extent_list bg_list;
+		};
+	};
+/* Actual on-disk size is one block */
 };
 
 struct ocfs2_refcount_rec {
@@ -1284,12 +1316,16 @@ static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
 	return size;
 }
 
-static inline int ocfs2_group_bitmap_size(struct super_block *sb)
+static inline int ocfs2_group_bitmap_size(struct super_block *sb,
+					  int suballocator)
 {
 	int size;
 
-	size = sb->s_blocksize -
-		offsetof(struct ocfs2_group_desc, bg_bitmap);
+	if (suballocator)
+		size = OCFS2_MAX_BG_BITMAP_SIZE;
+	else
+		size = sb->s_blocksize -
+			offsetof(struct ocfs2_group_desc, bg_bitmap);
 
 	return size;
 }
@@ -1412,12 +1448,15 @@ static inline int ocfs2_local_alloc_size(int blocksize)
 	return size;
 }
 
-static inline int ocfs2_group_bitmap_size(int blocksize)
+static inline int ocfs2_group_bitmap_size(int blocksize, int suballocator)
 {
 	int size;
 
-	size = blocksize -
-		offsetof(struct ocfs2_group_desc, bg_bitmap);
+	if (suballocator)
+		size = OCFS2_MAX_BG_BITMAP_SIZE;
+	else
+		size = blocksize -
+			offsetof(struct ocfs2_group_desc, bg_bitmap);
 
 	return size;
 }
fs/ocfs2/resize.c +2 -2
index 3c3d673..0ff4835 100644
@@ -319,7 +319,7 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
 	BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
 
 	if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
-				 ocfs2_group_bitmap_size(osb->sb) * 8) {
+				 ocfs2_group_bitmap_size(osb->sb, 0) * 8) {
 		mlog(ML_ERROR, "The disk is too old and small. "
 		     "Force to do offline resize.");
 		ret = -EINVAL;
@@ -500,7 +500,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
 	fe = (struct ocfs2_dinode *)main_bm_bh->b_data;
 
 	if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
-				 ocfs2_group_bitmap_size(osb->sb) * 8) {
+				 ocfs2_group_bitmap_size(osb->sb, 0) * 8) {
 		mlog(ML_ERROR, "The disk is too old and small."
 		     " Force to do offline resize.");
 		ret = -EINVAL;
fs/ocfs2/suballoc.c +1 -1
index c3c60bc..84125bf 100644
@@ -363,7 +363,7 @@ static int ocfs2_block_group_fill(handle_t *handle,
 	memset(bg, 0, sb->s_blocksize);
 	strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
 	bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
-	bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb));
+	bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1));
 	bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl));
 	bg->bg_chain = cpu_to_le16(my_chain);
 	bg->bg_next_group = cl->cl_recs[my_chain].c_blkno;
fs/ocfs2/super.c +1 -1
index dee0319..de8547f 100644
@@ -2226,7 +2226,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;
 	iput(inode);
 
-	osb->bitmap_cpg = ocfs2_group_bitmap_size(sb) * 8;
+	osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0) * 8;
 
 	status = ocfs2_init_slot_info(osb);
 	if (status < 0) {
Signature · 1 line
1.5.5
author
#2 lore raw

PATCH 2/15 ocfs2: Allocate discontiguous block groups.

In reply to Tao Ma

From: Joel Becker <[email protected]>

If we cannot get a contiguous region for a block group, allocate a discontiguous one when the filesystem supports it.

---
 fs/ocfs2/ocfs2.h    |    7 +
 fs/ocfs2/ocfs2_fs.h |   20 ++++
 fs/ocfs2/suballoc.c |  306 ++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 293 insertions(+), 40 deletions(-)
fs/ocfs2/ocfs2.h +7 -0
index 1238b49..b5fd76f 100644
@@ -482,6 +482,13 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
 	return 0;
 }
 
+static inline int ocfs2_supports_discontig_bh(struct ocfs2_super *osb)
+{
+	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
+		return 1;
+	return 0;
+}
+
 static inline unsigned int ocfs2_link_max(struct ocfs2_super *osb)
 {
 	if (ocfs2_supports_indexed_dirs(osb))
fs/ocfs2/ocfs2_fs.h +20 -0
index 055cf07..0508e4e 100644
@@ -1286,6 +1286,16 @@ static inline u16 ocfs2_extent_recs_per_eb(struct super_block *sb)
 	return size / sizeof(struct ocfs2_extent_rec);
 }
 
+static inline u16 ocfs2_extent_recs_per_gd(struct super_block *sb)
+{
+	int size;
+
+	size = sb->s_blocksize -
+		offsetof(struct ocfs2_group_desc, bg_list.l_recs);
+
+	return size / sizeof(struct ocfs2_extent_rec);
+}
+
 static inline int ocfs2_dx_entries_per_leaf(struct super_block *sb)
 {
 	int size;
@@ -1438,6 +1448,16 @@ static inline int ocfs2_extent_recs_per_eb(int blocksize)
 	return size / sizeof(struct ocfs2_extent_rec);
 }
 
+static inline int ocfs2_extent_recs_per_gd(int blocksize)
+{
+	int size;
+
+	size = blocksize -
+		offsetof(struct ocfs2_group_desc, bg_list.l_recs);
+
+	return size / sizeof(struct ocfs2_extent_rec);
+}
+
 static inline int ocfs2_local_alloc_size(int blocksize)
 {
 	int size;
fs/ocfs2/suballoc.c +266 -40

379 lines not on this page · raw message

Signature · 1 line
1.5.5
author
#3 lore raw

PATCH 3/15 ocfs2: Pass suballocation results back via a structure.

In reply to Tao Ma

From: Joel Becker <[email protected]>

We're going to be adding more info to a suballocator allocation. Rather than growing every function in the chain, let's pass a result structure around.

---
 fs/ocfs2/suballoc.c |  165 +++++++++++++++++++++-----------------------------
 fs/ocfs2/suballoc.h |    5 +-
 2 files changed, 72 insertions(+), 98 deletions(-)
fs/ocfs2/suballoc.c +69 -96
index 267d552..8bb20bb 100644
@@ -53,6 +53,12 @@
 
 #define OCFS2_MAX_TO_STEAL		1024
 
+struct ocfs2_suballoc_result {
+	u64		sr_bg_blkno;	/* The bg we allocated from */
+	unsigned int	sr_bit_offset;	/* The bit in the bg */
+	unsigned int	sr_bits;	/* How many bits we claimed */
+};
+
 static inline void ocfs2_debug_bg(struct ocfs2_group_desc *bg);
 static inline void ocfs2_debug_suballoc_inode(struct ocfs2_dinode *fe);
 static inline u16 ocfs2_find_victim_chain(struct ocfs2_chain_list *cl);
@@ -74,20 +80,18 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 				      struct buffer_head *group_bh,
 				      u32 bits_wanted, u32 min_bits,
 				      u64 max_block,
-				      u16 *bit_off, u16 *bits_found);
+				      struct ocfs2_suballoc_result *res);
 static int ocfs2_block_group_search(struct inode *inode,
 				    struct buffer_head *group_bh,
 				    u32 bits_wanted, u32 min_bits,
 				    u64 max_block,
-				    u16 *bit_off, u16 *bits_found);
+				    struct ocfs2_suballoc_result *res);
 static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 				     struct ocfs2_alloc_context *ac,
 				     handle_t *handle,
 				     u32 bits_wanted,
 				     u32 min_bits,
-				     u16 *bit_off,
-				     unsigned int *num_bits,
-				     u64 *bg_blkno);
+				     struct ocfs2_suballoc_result *res);
 static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
 					 int nr);
 static inline int ocfs2_block_group_set_bits(handle_t *handle,
@@ -1263,8 +1267,7 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
 					     struct buffer_head *bg_bh,
 					     unsigned int bits_wanted,
 					     unsigned int total_bits,
-					     u16 *bit_off,
-					     u16 *bits_found)
+					     struct ocfs2_suballoc_result *res)
 {
 	void *bitmap;
 	u16 best_offset, best_size;
@@ -1308,14 +1311,9 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
 		}
 	}
 
-	/* XXX: I think the first clause is equivalent to the second
-	 * 	- jlbec */
-	if (found == bits_wanted) {
-		*bit_off = start - found;
-		*bits_found = found;
-	} else if (best_size) {
-		*bit_off = best_offset;
-		*bits_found = best_size;
+	if (best_size) {
+		res->sr_bit_offset = best_offset;
+		res->sr_bits = best_size;
 	} else {
 		status = -ENOSPC;
 		/* No error log here -- see the comment above
@@ -1493,14 +1491,13 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 				      struct buffer_head *group_bh,
 				      u32 bits_wanted, u32 min_bits,
 				      u64 max_block,
-				      u16 *bit_off, u16 *bits_found)
+				      struct ocfs2_suballoc_result *res)
 {
 	int search = -ENOSPC;
 	int ret;
 	u64 blkoff;
 	struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data;
 	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-	u16 tmp_off, tmp_found;
 	unsigned int max_bits, gd_cluster_off;
 
 	BUG_ON(!ocfs2_is_cluster_bitmap(inode));
@@ -1527,15 +1524,15 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 
 		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
 							group_bh, bits_wanted,
-							max_bits,
-							&tmp_off, &tmp_found);
+							max_bits, res);
 		if (ret)
 			return ret;
 
 		if (max_block) {
 			blkoff = ocfs2_clusters_to_blocks(inode->i_sb,
 							  gd_cluster_off +
-							  tmp_off + tmp_found);
+							  res->sr_bit_offset +
+							  res->sr_bits);
 			mlog(0, "Checking %llu against %llu\n",
 			     (unsigned long long)blkoff,
 			     (unsigned long long)max_block);
@@ -1547,16 +1544,14 @@ static int ocfs2_cluster_group_search(struct inode *inode,
 		 * return success, but we still want to return
 		 * -ENOSPC unless it found the minimum number
 		 * of bits. */
-		if (min_bits <= tmp_found) {
-			*bit_off = tmp_off;
-			*bits_found = tmp_found;
+		if (min_bits <= res->sr_bits)
 			search = 0; /* success */
-		} else if (tmp_found) {
+		else if (res->sr_bits) {
 			/*
 			 * Don't show bits which we'll be returning
 			 * for allocation to the local alloc bitmap.
 			 */
-			ocfs2_local_alloc_seen_free_bits(osb, tmp_found);
+			ocfs2_local_alloc_seen_free_bits(osb, res->sr_bits);
 		}
 	}
 
@@ -1567,7 +1562,7 @@ static int ocfs2_block_group_search(struct inode *inode,
 				    struct buffer_head *group_bh,
 				    u32 bits_wanted, u32 min_bits,
 				    u64 max_block,
-				    u16 *bit_off, u16 *bits_found)
+				    struct ocfs2_suballoc_result *res)
 {
 	int ret = -ENOSPC;
 	u64 blkoff;
@@ -1580,10 +1575,10 @@ static int ocfs2_block_group_search(struct inode *inode,
 		ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb),
 							group_bh, bits_wanted,
 							le16_to_cpu(bg->bg_bits),
-							bit_off, bits_found);
+							res);
 		if (!ret && max_block) {
-			blkoff = le64_to_cpu(bg->bg_blkno) + *bit_off +
-				*bits_found;
+			blkoff = le64_to_cpu(bg->bg_blkno) +
+				res->sr_bit_offset + res->sr_bits;
 			mlog(0, "Checking %llu against %llu\n",
 			     (unsigned long long)blkoff,
 			     (unsigned long long)max_block);
@@ -1629,20 +1624,17 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 				  handle_t *handle,
 				  u32 bits_wanted,
 				  u32 min_bits,
-				  u16 *bit_off,
-				  unsigned int *num_bits,
-				  u64 gd_blkno,
+				  struct ocfs2_suballoc_result *res,
 				  u16 *bits_left)
 {
 	int ret;
-	u16 found;
 	struct buffer_head *group_bh = NULL;
 	struct ocfs2_group_desc *gd;
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
 	struct inode *alloc_inode = ac->ac_inode;
 
-	ret = ocfs2_read_group_descriptor(alloc_inode, di, gd_blkno,
-					  &group_bh);
+	ret = ocfs2_read_group_descriptor(alloc_inode, di,
+					  res->sr_bg_blkno, &group_bh);
 	if (ret < 0) {
 		mlog_errno(ret);
 		return ret;
@@ -1650,17 +1642,15 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 
 	gd = (struct ocfs2_group_desc *) group_bh->b_data;
 	ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits,
-				  ac->ac_max_block, bit_off, &found);
+				  ac->ac_max_block, res);
 	if (ret < 0) {
 		if (ret != -ENOSPC)
 			mlog_errno(ret);
 		goto out;
 	}
 
-	*num_bits = found;
-
 	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
-					       *num_bits,
+					       res->sr_bits,
 					       le16_to_cpu(gd->bg_chain));
 	if (ret < 0) {
 		mlog_errno(ret);
@@ -1668,7 +1658,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 	}
 
 	ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh,
-					 *bit_off, *num_bits);
+					 res->sr_bit_offset, res->sr_bits);
 	if (ret < 0)
 		mlog_errno(ret);
 
@@ -1684,13 +1674,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 			      handle_t *handle,
 			      u32 bits_wanted,
 			      u32 min_bits,
-			      u16 *bit_off,
-			      unsigned int *num_bits,
-			      u64 *bg_blkno,
+			      struct ocfs2_suballoc_result *res,
 			      u16 *bits_left)
 {
 	int status;
-	u16 chain, tmp_bits;
+	u16 chain;
 	u32 tmp_used;
 	u64 next_group;
 	struct inode *alloc_inode = ac->ac_inode;
@@ -1719,8 +1707,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 	 * the 1st group with any empty bits. */
 	while ((status = ac->ac_group_search(alloc_inode, group_bh,
 					     bits_wanted, min_bits,
-					     ac->ac_max_block, bit_off,
-					     &tmp_bits)) == -ENOSPC) {
+					     ac->ac_max_block,
+					     res)) == -ENOSPC) {
 		if (!bg->bg_next_group)
 			break;
 
@@ -1745,11 +1733,11 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 	}
 
 	mlog(0, "alloc succeeds: we give %u bits from block group %llu\n",
-	     tmp_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
+	     res->sr_bits, (unsigned long long)le64_to_cpu(bg->bg_blkno));
 
-	*num_bits = tmp_bits;
+	res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno);
 
-	BUG_ON(*num_bits == 0);
+	BUG_ON(res->sr_bits == 0);
 
 	/*
 	 * Keep track of previous block descriptor read. When
@@ -1766,7 +1754,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 	 */
 	if (ac->ac_allow_chain_relink &&
 	    (prev_group_bh) &&
-	    (ocfs2_block_group_reasonably_empty(bg, *num_bits))) {
+	    (ocfs2_block_group_reasonably_empty(bg, res->sr_bits))) {
 		status = ocfs2_relink_block_group(handle, alloc_inode,
 						  ac->ac_bh, group_bh,
 						  prev_group_bh, chain);
@@ -1788,8 +1776,8 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 	}
 
 	tmp_used = le32_to_cpu(fe->id1.bitmap1.i_used);
-	fe->id1.bitmap1.i_used = cpu_to_le32(*num_bits + tmp_used);
-	le32_add_cpu(&cl->cl_recs[chain].c_free, -(*num_bits));
+	fe->id1.bitmap1.i_used = cpu_to_le32(res->sr_bits + tmp_used);
+	le32_add_cpu(&cl->cl_recs[chain].c_free, -res->sr_bits);
 
 	status = ocfs2_journal_dirty(handle,
 				     ac->ac_bh);
@@ -1802,17 +1790,16 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 					    alloc_inode,
 					    bg,
 					    group_bh,
-					    *bit_off,
-					    *num_bits);
+					    res->sr_bit_offset,
+					    res->sr_bits);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 
-	mlog(0, "Allocated %u bits from suballocator %llu\n", *num_bits,
+	mlog(0, "Allocated %u bits from suballocator %llu\n", res->sr_bits,
 	     (unsigned long long)le64_to_cpu(fe->i_blkno));
 
-	*bg_blkno = le64_to_cpu(bg->bg_blkno);
 	*bits_left = le16_to_cpu(bg->bg_free_bits_count);
 bail:
 	brelse(group_bh);
@@ -1828,14 +1815,11 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 				     handle_t *handle,
 				     u32 bits_wanted,
 				     u32 min_bits,
-				     u16 *bit_off,
-				     unsigned int *num_bits,
-				     u64 *bg_blkno)
+				     struct ocfs2_suballoc_result *res)
 {
 	int status;
 	u16 victim, i;
 	u16 bits_left = 0;
-	u64 hint_blkno = ac->ac_last_group;
 	struct ocfs2_chain_list *cl;
 	struct ocfs2_dinode *fe;
 
@@ -1862,22 +1846,16 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 		goto bail;
 	}
 
-	if (hint_blkno) {
+	res->sr_bg_blkno = ac->ac_last_group;
+	if (res->sr_bg_blkno) {
 		/* Attempt to short-circuit the usual search mechanism
 		 * by jumping straight to the most recently used
 		 * allocation group. This helps us mantain some
 		 * contiguousness across allocations. */
 		status = ocfs2_search_one_group(ac, handle, bits_wanted,
-						min_bits, bit_off, num_bits,
-						hint_blkno, &bits_left);
-		if (!status) {
-			/* Be careful to update *bg_blkno here as the
-			 * caller is expecting it to be filled in, and
-			 * ocfs2_search_one_group() won't do that for
-			 * us. */
-			*bg_blkno = hint_blkno;
+						min_bits, res, &bits_left);
+		if (!status)
 			goto set_hint;
-		}
 		if (status < 0 && status != -ENOSPC) {
 			mlog_errno(status);
 			goto bail;
@@ -1890,8 +1868,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 	ac->ac_chain = victim;
 	ac->ac_allow_chain_relink = 1;
 
-	status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, bit_off,
-				    num_bits, bg_blkno, &bits_left);
+	status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
+				    res, &bits_left);
 	if (!status)
 		goto set_hint;
 	if (status < 0 && status != -ENOSPC) {
@@ -1915,8 +1893,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 
 		ac->ac_chain = i;
 		status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits,
-					    bit_off, num_bits, bg_blkno,
-					    &bits_left);
+					    res, &bits_left);
 		if (!status)
 			break;
 		if (status < 0 && status != -ENOSPC) {
@@ -1933,7 +1910,7 @@ set_hint:
 		if (bits_left < min_bits)
 			ac->ac_last_group = 0;
 		else
-			ac->ac_last_group = *bg_blkno;
+			ac->ac_last_group = res->sr_bg_blkno;
 	}
 
 bail:
@@ -1950,7 +1927,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
 			 u64 *blkno_start)
 {
 	int status;
-	u64 bg_blkno;
+	struct ocfs2_suballoc_result res;
 
 	BUG_ON(!ac);
 	BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
@@ -1961,17 +1938,17 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
 					   handle,
 					   bits_wanted,
 					   1,
-					   suballoc_bit_start,
-					   num_bits,
-					   &bg_blkno);
+					   &res);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 	atomic_inc(&osb->alloc_stats.bg_allocs);
 
-	*blkno_start = bg_blkno + (u64) *suballoc_bit_start;
-	ac->ac_bits_given += (*num_bits);
+	*suballoc_bit_start = res.sr_bit_offset;
+	*blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset);
+	ac->ac_bits_given += res.sr_bits;
+	*num_bits = res.sr_bits;
 	status = 0;
 bail:
 	mlog_exit(status);
@@ -2018,8 +1995,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
 			  u64 *fe_blkno)
 {
 	int status;
-	unsigned int num_bits;
-	u64 bg_blkno;
+	struct ocfs2_suballoc_result res;
 
 	mlog_entry_void();
 
@@ -2035,18 +2011,17 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
 					   handle,
 					   1,
 					   1,
-					   suballoc_bit,
-					   &num_bits,
-					   &bg_blkno);
+					   &res);
 	if (status < 0) {
 		mlog_errno(status);
 		goto bail;
 	}
 	atomic_inc(&osb->alloc_stats.bg_allocs);
 
-	BUG_ON(num_bits != 1);
+	BUG_ON(res.sr_bits != 1);
 
-	*fe_blkno = bg_blkno + (u64) (*suballoc_bit);
+	*suballoc_bit = res.sr_bit_offset;
+	*fe_blkno = res.sr_bg_blkno + (u64)(res.sr_bit_offset);
 	ac->ac_bits_given++;
 	ocfs2_save_inode_ac_group(dir, ac);
 	status = 0;
@@ -2126,8 +2101,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
 {
 	int status;
 	unsigned int bits_wanted = max_clusters;
-	u64 bg_blkno = 0;
-	u16 bg_bit_off;
+	struct ocfs2_suballoc_result res;
 
 	mlog_entry_void();
 
@@ -2164,14 +2138,12 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
 						   handle,
 						   bits_wanted,
 						   min_clusters,
-						   &bg_bit_off,
-						   num_clusters,
-						   &bg_blkno);
+						   &res);
 		if (!status) {
 			*cluster_start =
 				ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
-								 bg_blkno,
-								 bg_bit_off);
+								 res.sr_bg_blkno,
+								 res.sr_bit_offset);
 			atomic_inc(&osb->alloc_stats.bitmap_data);
 		}
 	}
@@ -2181,7 +2153,8 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
 		goto bail;
 	}
 
-	ac->ac_bits_given += *num_clusters;
+	ac->ac_bits_given += res.sr_bits;
+	*num_clusters = res.sr_bits;
 
 bail:
 	mlog_exit(status);
fs/ocfs2/suballoc.h +3 -2
index fa60723..fbf7f17 100644
@@ -26,13 +26,14 @@
 #ifndef _CHAINALLOC_H_
 #define _CHAINALLOC_H_
 
+struct ocfs2_suballoc_result;
 typedef int (group_search_t)(struct inode *,
 			     struct buffer_head *,
 			     u32,			/* bits_wanted */
 			     u32,			/* min_bits */
 			     u64,			/* max_block */
-			     u16 *,			/* *bit_off */
-			     u16 *);			/* *bits_found */
+			     struct ocfs2_suballoc_result *);
+							/* found bits */
 
 struct ocfs2_alloc_context {
 	struct inode *ac_inode;    /* which bitmap are we allocating from? */
Signature · 1 line
1.5.5
author
#4 lore raw

PATCH 4/15 ocfs2: Add suballoc_loc to metadata blocks.

In reply to Tao Ma

From: Joel Becker <[email protected]>

We need a suballoc_loc field on any suballocated block. Define them.

---
 fs/ocfs2/ocfs2_fs.h |   29 ++++++++++++++++++++++++-----
 1 files changed, 24 insertions(+), 5 deletions(-)
fs/ocfs2/ocfs2_fs.h +24 -5
index 0508e4e..42641f8 100644
@@ -515,7 +515,10 @@ struct ocfs2_extent_block
 					   block group */
 	__le32 h_fs_generation;		/* Must match super block */
 	__le64 h_blkno;			/* Offset on disk, in blocks */
-/*20*/	__le64 h_reserved3;
+/*20*/	__le64 h_suballoc_loc;		/* Suballocator block group this
+					   eb belongs to.  Only valid
+					   if allocated from a
+					   discontiguous block group */
 	__le64 h_next_leaf_blk;		/* Offset on disk, in blocks,
 					   of next leaf header pointing
 					   to data */
@@ -682,7 +685,11 @@ struct ocfs2_dinode {
 /*80*/	struct ocfs2_block_check i_check;	/* Error checking */
 /*88*/	__le64 i_dx_root;		/* Pointer to dir index root block */
 /*90*/	__le64 i_refcount_loc;
-	__le64 i_reserved2[4];
+	__le64 i_suballoc_loc;		/* Suballocator block group this
+					   inode belongs to.  Only valid
+					   if allocated from a
+					   discontiguous block group */
+/*A0*/	__le64 i_reserved2[3];
 /*B8*/	union {
 		__le64 i_pad1;		/* Generic way to refer to this
 					   64bit union */
@@ -817,7 +824,12 @@ struct ocfs2_dx_root_block {
 	__le32		dr_reserved2;
 	__le64		dr_free_blk;		/* Pointer to head of free
 						 * unindexed block list. */
-	__le64		dr_reserved3[15];
+	__le64		dr_suballoc_loc;	/* Suballocator block group
+						   this root belongs to.
+						   Only valid if allocated
+						   from a discontiguous
+						   block group */
+	__le64		dr_reserved3[14];
 	union {
 		struct ocfs2_extent_list dr_list; /* Keep this aligned to 128
 						   * bits for maximum space
@@ -937,7 +949,11 @@ struct ocfs2_refcount_block {
 /*40*/	__le32 rf_generation;		/* generation number. all be the same
 					 * for the same refcount tree. */
 	__le32 rf_reserved0;
-	__le64 rf_reserved1[7];
+	__le64 rf_suballoc_loc;		/* Suballocator block group this
+					   refcount block belongs to. Only
+					   valid if allocated from a
+					   discontiguous block group */
+/*50*/	__le64 rf_reserved1[6];
 /*80*/	union {
 		struct ocfs2_refcount_list rf_records;  /* List of refcount
 							  records */
@@ -1049,7 +1065,10 @@ struct ocfs2_xattr_block {
 					real xattr or a xattr tree. */
 	__le16	xb_reserved0;
 	__le32  xb_reserved1;
-	__le64	xb_reserved2;
+	__le64	xb_suballoc_loc;	/* Suballocator block group this
+					   xattr block belongs to. Only
+					   valid if allocated from a
+					   discontiguous block group */
 /*30*/	union {
 		struct ocfs2_xattr_header xb_header; /* xattr header if this
 							block contains xattr */
Signature · 1 line
1.5.5
author
#5 lore raw

PATCH 5/15 ocfs2: ocfs2_claim_suballoc_bits() doesn't need an osb argument.

In reply to Tao Ma

From: Joel Becker <[email protected]>

It's contained on ac->ac_inode->i_sb anyway.

---
 fs/ocfs2/suballoc.c |   18 +++++++-----------
 1 files changed, 7 insertions(+), 11 deletions(-)
fs/ocfs2/suballoc.c +7 -11
index 8bb20bb..298fb54 100644
@@ -86,8 +86,7 @@ static int ocfs2_block_group_search(struct inode *inode,
 				    u32 bits_wanted, u32 min_bits,
 				    u64 max_block,
 				    struct ocfs2_suballoc_result *res);
-static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
-				     struct ocfs2_alloc_context *ac,
+static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
 				     handle_t *handle,
 				     u32 bits_wanted,
 				     u32 min_bits,
@@ -1810,8 +1809,7 @@ bail:
 }
 
 /* will give out up to bits_wanted contiguous bits. */
-static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
-				     struct ocfs2_alloc_context *ac,
+static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac,
 				     handle_t *handle,
 				     u32 bits_wanted,
 				     u32 min_bits,
@@ -1837,7 +1835,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb,
 
 	if (le32_to_cpu(fe->id1.bitmap1.i_used) >=
 	    le32_to_cpu(fe->id1.bitmap1.i_total)) {
-		ocfs2_error(osb->sb, "Chain allocator dinode %llu has %u used "
+		ocfs2_error(ac->ac_inode->i_sb,
+			    "Chain allocator dinode %llu has %u used "
 			    "bits but only %u total.",
 			    (unsigned long long)le64_to_cpu(fe->i_blkno),
 			    le32_to_cpu(fe->id1.bitmap1.i_used),
@@ -1933,8 +1932,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
 	BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
 	BUG_ON(ac->ac_which != OCFS2_AC_USE_META);
 
-	status = ocfs2_claim_suballoc_bits(osb,
-					   ac,
+	status = ocfs2_claim_suballoc_bits(ac,
 					   handle,
 					   bits_wanted,
 					   1,
@@ -2006,8 +2004,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
 
 	ocfs2_init_inode_ac_group(dir, parent_fe_bh, ac);
 
-	status = ocfs2_claim_suballoc_bits(osb,
-					   ac,
+	status = ocfs2_claim_suballoc_bits(ac,
 					   handle,
 					   1,
 					   1,
@@ -2133,8 +2130,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
 		if (bits_wanted > (osb->bitmap_cpg - 1))
 			bits_wanted = osb->bitmap_cpg - 1;
 
-		status = ocfs2_claim_suballoc_bits(osb,
-						   ac,
+		status = ocfs2_claim_suballoc_bits(ac,
 						   handle,
 						   bits_wanted,
 						   min_clusters,
Signature · 1 line
1.5.5
author
#6 lore raw

PATCH 6/15 ocfs2: Trim suballocations if they cross discontiguous regions

In reply to Tao Ma

From: Joel Becker <[email protected]>

A discontiguous block group can find a range of free bits that straddle more than one region of its space. Callers can't handle that, so we trim the returned bits until they fit within one region.

Only cluster allocations ask for min_bits>1. Discontiguous block groups are only for block allocations. So min_bits doesn't matter here.

---
 fs/ocfs2/suballoc.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 48 insertions(+), 0 deletions(-)
fs/ocfs2/suballoc.c +48 -0
index 298fb54..1910f09 100644
@@ -1619,6 +1619,48 @@ out:
 	return ret;
 }
 
+static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res,
+					  struct ocfs2_extent_rec *rec,
+					  struct ocfs2_chain_list *cl)
+{
+	unsigned int bpc = le16_to_cpu(cl->cl_bpc);
+	unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
+	unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc;
+
+	if (res->sr_bit_offset < bitoff)
+		return 0;
+	if (res->sr_bit_offset >= (bitoff + bitcount))
+		return 0;
+	if ((res->sr_bit_offset + res->sr_bits) > (bitoff + bitcount))
+		res->sr_bits = (bitoff + bitcount) - res->sr_bit_offset;
+	return 1;
+}
+
+static void ocfs2_bg_discontig_trim_result(struct ocfs2_alloc_context *ac,
+					   struct ocfs2_group_desc *bg,
+					   struct ocfs2_suballoc_result *res)
+{
+	int i;
+	struct ocfs2_extent_rec *rec;
+	struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
+	struct ocfs2_chain_list *cl = &di->id2.i_chain;
+
+	if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)))
+		return;
+
+	if (ocfs2_is_cluster_bitmap(ac->ac_inode))
+		return;
+
+	if (!bg->bg_list.l_next_free_rec)
+		return;
+
+	for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) {
+		rec = &bg->bg_list.l_recs[i];
+		if (ocfs2_bg_discontig_trim_by_rec(res, rec, cl))
+			break;
+	}
+}
+
 static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 				  handle_t *handle,
 				  u32 bits_wanted,
@@ -1648,6 +1690,9 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 		goto out;
 	}
 
+	if (!ret)
+		ocfs2_bg_discontig_trim_result(ac, gd, res);
+
 	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
 					       res->sr_bits,
 					       le16_to_cpu(gd->bg_chain));
@@ -1737,6 +1782,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 	res->sr_bg_blkno = le64_to_cpu(bg->bg_blkno);
 
 	BUG_ON(res->sr_bits == 0);
+	if (!status)
+		ocfs2_bg_discontig_trim_result(ac, bg, res);
+
 
 	/*
 	 * Keep track of previous block descriptor read. When
Signature · 1 line
1.5.5
author
#7 lore raw

PATCH 7/15 ocfs2: ocfs2_claim_*() don't need an ocfs2_super argument.

In reply to Tao Ma

From: Joel Becker <[email protected]>

They all take an ocfs2_alloc_context, which has the allocation inode.

---
 fs/ocfs2/alloc.c        |    7 +++----
 fs/ocfs2/dir.c          |    8 ++++----
 fs/ocfs2/localalloc.c   |    4 ++--
 fs/ocfs2/namei.c        |    2 +-
 fs/ocfs2/refcounttree.c |    8 ++++----
 fs/ocfs2/suballoc.c     |   23 ++++++++++-------------
 fs/ocfs2/suballoc.h     |   12 ++++--------
 fs/ocfs2/xattr.c        |   13 ++++++-------
 8 files changed, 34 insertions(+), 43 deletions(-)
fs/ocfs2/alloc.c +3 -4
index 9f8bd91..57d7f7a 100644
@@ -1015,8 +1015,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
 
 	count = 0;
 	while (count < wanted) {
-		status = ocfs2_claim_metadata(osb,
-					      handle,
+		status = ocfs2_claim_metadata(handle,
 					      meta_ac,
 					      wanted - count,
 					      &suballoc_bit_start,
@@ -4866,7 +4865,7 @@ int ocfs2_add_clusters_in_btree(handle_t *handle,
 		goto leave;
 	}
 
-	status = __ocfs2_claim_clusters(osb, handle, data_ac, 1,
+	status = __ocfs2_claim_clusters(handle, data_ac, 1,
 					clusters_to_add, &bit_off, &num_bits);
 	if (status < 0) {
 		if (status != -ENOSPC)
@@ -7307,7 +7306,7 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
 			goto out_commit;
 		did_quota = 1;
 
-		ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
+		ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
 					   &num);
 		if (ret) {
 			mlog_errno(ret);
fs/ocfs2/dir.c +4 -4
index efd77d0..06522b5 100644
@@ -2411,7 +2411,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
 	struct ocfs2_dir_block_trailer *trailer =
 		ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
 
-	ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1, &dr_suballoc_bit,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &dr_suballoc_bit,
 				   &num_bits, &dr_blkno);
 	if (ret) {
 		mlog_errno(ret);
@@ -2558,7 +2558,7 @@ static int __ocfs2_dx_dir_new_cluster(struct inode *dir,
 	 * chance of contiguousness as the directory grows in number
 	 * of entries.
 	 */
-	ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1, 1, &phys, &num);
+	ret = __ocfs2_claim_clusters(handle, data_ac, 1, 1, &phys, &num);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
@@ -2991,7 +2991,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
 	 * if we only get one now, that's enough to continue. The rest
 	 * will be claimed after the conversion to extents.
 	 */
-	ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len);
+	ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off, &len);
 	if (ret) {
 		mlog_errno(ret);
 		goto out_commit;
@@ -3138,7 +3138,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
 	 * pass. Claim the 2nd cluster as a separate extent.
 	 */
 	if (alloc > len) {
-		ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off,
+		ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
 					   &len);
 		if (ret) {
 			mlog_errno(ret);
fs/ocfs2/localalloc.c +2 -2
index ca992d9..e51d75c 100644
@@ -1048,7 +1048,7 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb,
 	/* 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 = ocfs2_claim_clusters(osb, handle, ac, osb->local_alloc_bits,
+	status = ocfs2_claim_clusters(handle, ac, osb->local_alloc_bits,
 				      &cluster_off, &cluster_count);
 	if (status == -ENOSPC) {
 retry_enospc:
@@ -1061,7 +1061,7 @@ retry_enospc:
 		    OCFS2_LA_DISABLED)
 			goto bail;
 
-		status = ocfs2_claim_clusters(osb, handle, ac,
+		status = ocfs2_claim_clusters(handle, ac,
 					      osb->local_alloc_bits,
 					      &cluster_off,
 					      &cluster_count);
fs/ocfs2/namei.c +1 -1
index d9cd4e3..9c3e1fe 100644
@@ -482,7 +482,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
 
 	*new_fe_bh = NULL;
 
-	status = ocfs2_claim_new_inode(osb, handle, dir, parent_fe_bh,
+	status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh,
 				       inode_ac, &suballoc_bit, &fe_blkno);
 	if (status < 0) {
 		mlog_errno(status);
fs/ocfs2/refcounttree.c +4 -4
index 9e96921..4fb18af 100644
@@ -597,7 +597,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
 		goto out_commit;
 	}
 
-	ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
 				   &suballoc_bit_start, &num_got,
 				   &first_blkno);
 	if (ret) {
@@ -1299,7 +1299,7 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 		goto out;
 	}
 
-	ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
 				   &suballoc_bit_start, &num_got,
 				   &blkno);
 	if (ret) {
@@ -1549,7 +1549,7 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 		goto out;
 	}
 
-	ret = ocfs2_claim_metadata(OCFS2_SB(sb), handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
 				   &suballoc_bit_start, &num_got,
 				   &blkno);
 	if (ret) {
@@ -3283,7 +3283,7 @@ static int ocfs2_make_clusters_writable(struct super_block *sb,
 		} else {
 			delete = 1;
 
-			ret = __ocfs2_claim_clusters(osb, handle,
+			ret = __ocfs2_claim_clusters(handle,
 						     context->data_ac,
 						     1, set_len,
 						     &new_bit, &new_len);
fs/ocfs2/suballoc.c +10 -13
index 1910f09..0fd0357 100644
@@ -444,7 +444,7 @@ ocfs2_block_group_alloc_contig(struct ocfs2_super *osb, handle_t *handle,
 	struct buffer_head *bg_bh;
 	unsigned int alloc_rec = ocfs2_find_smallest_chain(cl);
 
-	status = ocfs2_claim_clusters(osb, handle, ac,
+	status = ocfs2_claim_clusters(handle, ac,
 				      le16_to_cpu(cl->cl_cpg), &bit_off,
 				      &num_bits);
 	if (status < 0) {
@@ -486,7 +486,7 @@ static int ocfs2_block_group_claim_bits(struct ocfs2_super *osb,
 	int status;
 
 	while (min_bits) {
-		status = ocfs2_claim_clusters(osb, handle, ac, min_bits,
+		status = ocfs2_claim_clusters(handle, ac, min_bits,
 					      bit_off, num_bits);
 		if (status != -ENOSPC)
 			break;
@@ -1965,8 +1965,7 @@ bail:
 	return status;
 }
 
-int ocfs2_claim_metadata(struct ocfs2_super *osb,
-			 handle_t *handle,
+int ocfs2_claim_metadata(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 bits_wanted,
 			 u16 *suballoc_bit_start,
@@ -1989,7 +1988,7 @@ int ocfs2_claim_metadata(struct ocfs2_super *osb,
 		mlog_errno(status);
 		goto bail;
 	}
-	atomic_inc(&osb->alloc_stats.bg_allocs);
+	atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
 
 	*suballoc_bit_start = res.sr_bit_offset;
 	*blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset);
@@ -2032,8 +2031,7 @@ static inline void ocfs2_save_inode_ac_group(struct inode *dir,
 	OCFS2_I(dir)->ip_last_used_slot = ac->ac_alloc_slot;
 }
 
-int ocfs2_claim_new_inode(struct ocfs2_super *osb,
-			  handle_t *handle,
+int ocfs2_claim_new_inode(handle_t *handle,
 			  struct inode *dir,
 			  struct buffer_head *parent_fe_bh,
 			  struct ocfs2_alloc_context *ac,
@@ -2061,7 +2059,7 @@ int ocfs2_claim_new_inode(struct ocfs2_super *osb,
 		mlog_errno(status);
 		goto bail;
 	}
-	atomic_inc(&osb->alloc_stats.bg_allocs);
+	atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
 
 	BUG_ON(res.sr_bits != 1);
 
@@ -2136,8 +2134,7 @@ static inline void ocfs2_block_to_cluster_group(struct inode *inode,
  * contig. allocation, set to '1' to indicate we can deal with extents
  * of any size.
  */
-int __ocfs2_claim_clusters(struct ocfs2_super *osb,
-			   handle_t *handle,
+int __ocfs2_claim_clusters(handle_t *handle,
 			   struct ocfs2_alloc_context *ac,
 			   u32 min_clusters,
 			   u32 max_clusters,
@@ -2147,6 +2144,7 @@ int __ocfs2_claim_clusters(struct ocfs2_super *osb,
 	int status;
 	unsigned int bits_wanted = max_clusters;
 	struct ocfs2_suballoc_result res;
+	struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb);
 
 	mlog_entry_void();
 
@@ -2205,8 +2203,7 @@ bail:
 	return status;
 }
 
-int ocfs2_claim_clusters(struct ocfs2_super *osb,
-			 handle_t *handle,
+int ocfs2_claim_clusters(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 min_clusters,
 			 u32 *cluster_start,
@@ -2214,7 +2211,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
 {
 	unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given;
 
-	return __ocfs2_claim_clusters(osb, handle, ac, min_clusters,
+	return __ocfs2_claim_clusters(handle, ac, min_clusters,
 				      bits_wanted, cluster_start, num_clusters);
 }
 
fs/ocfs2/suballoc.h +4 -8
index fbf7f17..28096dc 100644
@@ -81,22 +81,19 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
 			   u32 bits_wanted,
 			   struct ocfs2_alloc_context **ac);
 
-int ocfs2_claim_metadata(struct ocfs2_super *osb,
-			 handle_t *handle,
+int ocfs2_claim_metadata(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 bits_wanted,
 			 u16 *suballoc_bit_start,
 			 u32 *num_bits,
 			 u64 *blkno_start);
-int ocfs2_claim_new_inode(struct ocfs2_super *osb,
-			  handle_t *handle,
+int ocfs2_claim_new_inode(handle_t *handle,
 			  struct inode *dir,
 			  struct buffer_head *parent_fe_bh,
 			  struct ocfs2_alloc_context *ac,
 			  u16 *suballoc_bit,
 			  u64 *fe_blkno);
-int ocfs2_claim_clusters(struct ocfs2_super *osb,
-			 handle_t *handle,
+int ocfs2_claim_clusters(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 min_clusters,
 			 u32 *cluster_start,
@@ -105,8 +102,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb,
  * Use this variant of ocfs2_claim_clusters to specify a maxiumum
  * number of clusters smaller than the allocation reserved.
  */
-int __ocfs2_claim_clusters(struct ocfs2_super *osb,
-			   handle_t *handle,
+int __ocfs2_claim_clusters(handle_t *handle,
 			   struct ocfs2_alloc_context *ac,
 			   u32 min_clusters,
 			   u32 max_clusters,
fs/ocfs2/xattr.c +6 -7
index d1b0d38..e8997ca 100644
@@ -2848,7 +2848,6 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 	u32 num_got;
 	u64 first_blkno;
 	struct ocfs2_dinode *di =  (struct ocfs2_dinode *)inode_bh->b_data;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct buffer_head *new_bh = NULL;
 	struct ocfs2_xattr_block *xblk;
 
@@ -2859,7 +2858,7 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 		goto end;
 	}
 
-	ret = ocfs2_claim_metadata(osb, ctxt->handle, ctxt->meta_ac, 1,
+	ret = ocfs2_claim_metadata(ctxt->handle, ctxt->meta_ac, 1,
 				   &suballoc_bit_start, &num_got,
 				   &first_blkno);
 	if (ret < 0) {
@@ -2884,7 +2883,8 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 	strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
 	xblk->xb_suballoc_slot = cpu_to_le16(ctxt->meta_ac->ac_alloc_slot);
 	xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
-	xblk->xb_fs_generation = cpu_to_le32(osb->fs_generation);
+	xblk->xb_fs_generation =
+		cpu_to_le32(OCFS2_SB(inode->i_sb)->fs_generation);
 	xblk->xb_blkno = cpu_to_le64(first_blkno);
 	if (indexed) {
 		struct ocfs2_xattr_tree_root *xr = &xblk->xb_attrs.xb_root;
@@ -4249,7 +4249,6 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
 	u32 bit_off, len;
 	u64 blkno;
 	handle_t *handle = ctxt->handle;
-	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 	struct ocfs2_inode_info *oi = OCFS2_I(inode);
 	struct buffer_head *xb_bh = xs->xattr_bh;
 	struct ocfs2_xattr_block *xb =
@@ -4277,7 +4276,7 @@ static int ocfs2_xattr_create_index_block(struct inode *inode,
 		goto out;
 	}
 
-	ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac,
+	ret = __ocfs2_claim_clusters(handle, ctxt->data_ac,
 				     1, 1, &bit_off, &len);
 	if (ret) {
 		mlog_errno(ret);
@@ -5099,7 +5098,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode,
 		goto leave;
 	}
 
-	ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, 1,
+	ret = __ocfs2_claim_clusters(handle, ctxt->data_ac, 1,
 				     clusters_to_add, &bit_off, &num_bits);
 	if (ret < 0) {
 		if (ret != -ENOSPC)
@@ -6937,7 +6936,7 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode,
 		goto out;
 	}
 
-	ret = ocfs2_claim_clusters(osb, handle, data_ac,
+	ret = ocfs2_claim_clusters(handle, data_ac,
 				   len, &p_cluster, &num_clusters);
 	if (ret) {
 		mlog_errno(ret);
Signature · 1 line
1.5.5
author
#8 lore raw

PATCH 8/15 ocfs2: Return allocated metadata blknos on the ocfs2_suballoc_result.

In reply to Tao Ma

From: Joel Becker <[email protected]>

Rather than calculating the resulting block number, return it on the ocfs2_suballoc_result structure. This way we can calculate block numbers for discontiguous block groups.

Cluster groups keep doing it the old way.

---
 fs/ocfs2/suballoc.c |   43 ++++++++++++++++++++++++-------------------
 1 files changed, 24 insertions(+), 19 deletions(-)
fs/ocfs2/suballoc.c +24 -19
index 0fd0357..6ac9884 100644
@@ -55,6 +55,7 @@
 
 struct ocfs2_suballoc_result {
 	u64		sr_bg_blkno;	/* The bg we allocated from */
+	u64		sr_blkno;	/* The first allocated block */
 	unsigned int	sr_bit_offset;	/* The bit in the bg */
 	unsigned int	sr_bits;	/* How many bits we claimed */
 };
@@ -1619,9 +1620,9 @@ out:
 	return ret;
 }
 
-static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res,
-					  struct ocfs2_extent_rec *rec,
-					  struct ocfs2_chain_list *cl)
+static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res,
+					 struct ocfs2_extent_rec *rec,
+					 struct ocfs2_chain_list *cl)
 {
 	unsigned int bpc = le16_to_cpu(cl->cl_bpc);
 	unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
@@ -1631,32 +1632,35 @@ static int ocfs2_bg_discontig_trim_by_rec(struct ocfs2_suballoc_result *res,
 		return 0;
 	if (res->sr_bit_offset >= (bitoff + bitcount))
 		return 0;
+	res->sr_blkno = le64_to_cpu(rec->e_blkno) +
+		(res->sr_bit_offset - bitoff);
 	if ((res->sr_bit_offset + res->sr_bits) > (bitoff + bitcount))
 		res->sr_bits = (bitoff + bitcount) - res->sr_bit_offset;
 	return 1;
 }
 
-static void ocfs2_bg_discontig_trim_result(struct ocfs2_alloc_context *ac,
-					   struct ocfs2_group_desc *bg,
-					   struct ocfs2_suballoc_result *res)
+static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac,
+					  struct ocfs2_group_desc *bg,
+					  struct ocfs2_suballoc_result *res)
 {
 	int i;
 	struct ocfs2_extent_rec *rec;
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
 	struct ocfs2_chain_list *cl = &di->id2.i_chain;
 
-	if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)))
-		return;
-
-	if (ocfs2_is_cluster_bitmap(ac->ac_inode))
+	if (ocfs2_is_cluster_bitmap(ac->ac_inode)) {
+		res->sr_blkno = 0;
 		return;
+	}
 
-	if (!bg->bg_list.l_next_free_rec)
+	res->sr_blkno = res->sr_bg_blkno + res->sr_bit_offset;
+	if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)) ||
+	    !bg->bg_list.l_next_free_rec)
 		return;
 
 	for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) {
 		rec = &bg->bg_list.l_recs[i];
-		if (ocfs2_bg_discontig_trim_by_rec(res, rec, cl))
+		if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl))
 			break;
 	}
 }
@@ -1691,7 +1695,7 @@ static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac,
 	}
 
 	if (!ret)
-		ocfs2_bg_discontig_trim_result(ac, gd, res);
+		ocfs2_bg_discontig_fix_result(ac, gd, res);
 
 	ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh,
 					       res->sr_bits,
@@ -1783,7 +1787,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 
 	BUG_ON(res->sr_bits == 0);
 	if (!status)
-		ocfs2_bg_discontig_trim_result(ac, bg, res);
+		ocfs2_bg_discontig_fix_result(ac, bg, res);
 
 
 	/*
@@ -1973,7 +1977,7 @@ int ocfs2_claim_metadata(handle_t *handle,
 			 u64 *blkno_start)
 {
 	int status;
-	struct ocfs2_suballoc_result res;
+	struct ocfs2_suballoc_result res = { .sr_blkno = 0, };
 
 	BUG_ON(!ac);
 	BUG_ON(ac->ac_bits_wanted < (ac->ac_bits_given + bits_wanted));
@@ -1991,7 +1995,7 @@ int ocfs2_claim_metadata(handle_t *handle,
 	atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
 
 	*suballoc_bit_start = res.sr_bit_offset;
-	*blkno_start = res.sr_bg_blkno + (u64)(res.sr_bit_offset);
+	*blkno_start = res.sr_blkno;
 	ac->ac_bits_given += res.sr_bits;
 	*num_bits = res.sr_bits;
 	status = 0;
@@ -2039,7 +2043,7 @@ int ocfs2_claim_new_inode(handle_t *handle,
 			  u64 *fe_blkno)
 {
 	int status;
-	struct ocfs2_suballoc_result res;
+	struct ocfs2_suballoc_result res = { .sr_blkno = 0, };
 
 	mlog_entry_void();
 
@@ -2064,7 +2068,7 @@ int ocfs2_claim_new_inode(handle_t *handle,
 	BUG_ON(res.sr_bits != 1);
 
 	*suballoc_bit = res.sr_bit_offset;
-	*fe_blkno = res.sr_bg_blkno + (u64)(res.sr_bit_offset);
+	*fe_blkno = res.sr_blkno;
 	ac->ac_bits_given++;
 	ocfs2_save_inode_ac_group(dir, ac);
 	status = 0;
@@ -2143,7 +2147,7 @@ int __ocfs2_claim_clusters(handle_t *handle,
 {
 	int status;
 	unsigned int bits_wanted = max_clusters;
-	struct ocfs2_suballoc_result res;
+	struct ocfs2_suballoc_result res = { .sr_blkno = 0, };
 	struct ocfs2_super *osb = OCFS2_SB(ac->ac_inode->i_sb);
 
 	mlog_entry_void();
@@ -2182,6 +2186,7 @@ int __ocfs2_claim_clusters(handle_t *handle,
 						   min_clusters,
 						   &res);
 		if (!status) {
+			BUG_ON(res.sr_blkno); /* cluster alloc can't set */
 			*cluster_start =
 				ocfs2_desc_bitmap_to_cluster_off(ac->ac_inode,
 								 res.sr_bg_blkno,
Signature · 1 line
1.5.5
author
#9 lore raw

PATCH 9/15 ocfs2: Set suballoc_loc on allocated metadata.

In reply to Tao Ma

From: Joel Becker <[email protected]>

Get the suballoc_loc from ocfs2_claim_new_inode() or ocfs2_claim_metadata(). Store it on the appropriate field of the block we just allocated.

---
 fs/ocfs2/alloc.c        |    4 +++-
 fs/ocfs2/dir.c          |    7 ++++---
 fs/ocfs2/namei.c        |    6 ++++--
 fs/ocfs2/refcounttree.c |   15 +++++++++------
 fs/ocfs2/suballoc.c     |   16 +++++++++++++---
 fs/ocfs2/suballoc.h     |    2 ++
 fs/ocfs2/xattr.c        |    7 ++++---
 7 files changed, 39 insertions(+), 18 deletions(-)
fs/ocfs2/alloc.c +3 -1
index 57d7f7a..6b59b6f 100644
@@ -1006,7 +1006,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
 	int count, status, i;
 	u16 suballoc_bit_start;
 	u32 num_got;
-	u64 first_blkno;
+	u64 suballoc_loc, first_blkno;
 	struct ocfs2_super *osb =
 		OCFS2_SB(ocfs2_metadata_cache_get_super(et->et_ci));
 	struct ocfs2_extent_block *eb;
@@ -1018,6 +1018,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
 		status = ocfs2_claim_metadata(handle,
 					      meta_ac,
 					      wanted - count,
+					      &suballoc_loc,
 					      &suballoc_bit_start,
 					      &num_got,
 					      &first_blkno);
@@ -1051,6 +1052,7 @@ static int ocfs2_create_new_meta_bhs(handle_t *handle,
 			eb->h_fs_generation = cpu_to_le32(osb->fs_generation);
 			eb->h_suballoc_slot =
 				cpu_to_le16(meta_ac->ac_alloc_slot);
+			eb->h_suballoc_loc = cpu_to_le64(suballoc_loc);
 			eb->h_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 			eb->h_list.l_count =
 				cpu_to_le16(ocfs2_extent_recs_per_eb(osb->sb));
fs/ocfs2/dir.c +4 -3
index 06522b5..48b591d 100644
@@ -2404,15 +2404,15 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
 	int ret;
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
 	u16 dr_suballoc_bit;
-	u64 dr_blkno;
+	u64 suballoc_loc, dr_blkno;
 	unsigned int num_bits;
 	struct buffer_head *dx_root_bh = NULL;
 	struct ocfs2_dx_root_block *dx_root;
 	struct ocfs2_dir_block_trailer *trailer =
 		ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
 
-	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &dr_suballoc_bit,
-				   &num_bits, &dr_blkno);
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
+				   &dr_suballoc_bit, &num_bits, &dr_blkno);
 	if (ret) {
 		mlog_errno(ret);
 		goto out;
@@ -2440,6 +2440,7 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
 	memset(dx_root, 0, osb->sb->s_blocksize);
 	strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
 	dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+	dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc);
 	dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
 	dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
 	dx_root->dr_blkno = cpu_to_le64(dr_blkno);
fs/ocfs2/namei.c +4 -2
index 9c3e1fe..6ec584e 100644
@@ -476,14 +476,15 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
 	int status = 0;
 	struct ocfs2_dinode *fe = NULL;
 	struct ocfs2_extent_list *fel;
-	u64 fe_blkno = 0;
+	u64 suballoc_loc, fe_blkno = 0;
 	u16 suballoc_bit;
 	u16 feat;
 
 	*new_fe_bh = NULL;
 
 	status = ocfs2_claim_new_inode(handle, dir, parent_fe_bh,
-				       inode_ac, &suballoc_bit, &fe_blkno);
+				       inode_ac, &suballoc_loc,
+				       &suballoc_bit, &fe_blkno);
 	if (status < 0) {
 		mlog_errno(status);
 		goto leave;
@@ -520,6 +521,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
 	fe->i_generation = cpu_to_le32(inode->i_generation);
 	fe->i_fs_generation = cpu_to_le32(osb->fs_generation);
 	fe->i_blkno = cpu_to_le64(fe_blkno);
+	fe->i_suballoc_loc = cpu_to_le64(suballoc_loc);
 	fe->i_suballoc_bit = cpu_to_le16(suballoc_bit);
 	fe->i_suballoc_slot = cpu_to_le16(inode_ac->ac_alloc_slot);
 	fe->i_uid = cpu_to_le32(inode->i_uid);
fs/ocfs2/refcounttree.c +9 -6
index 4fb18af..3fc675f 100644
@@ -571,7 +571,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
 	struct ocfs2_refcount_tree *new_tree = NULL, *tree = NULL;
 	u16 suballoc_bit_start;
 	u32 num_got;
-	u64 first_blkno;
+	u64 suballoc_loc, first_blkno;
 
 	BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
 
@@ -597,7 +597,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
 		goto out_commit;
 	}
 
-	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
 				   &suballoc_bit_start, &num_got,
 				   &first_blkno);
 	if (ret) {
@@ -627,6 +627,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
 	memset(rb, 0, inode->i_sb->s_blocksize);
 	strcpy((void *)rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
 	rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+	rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
 	rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	rb->rf_fs_generation = cpu_to_le32(osb->fs_generation);
 	rb->rf_blkno = cpu_to_le64(first_blkno);
@@ -1285,7 +1286,7 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 	int ret;
 	u16 suballoc_bit_start;
 	u32 num_got;
-	u64 blkno;
+	u64 suballoc_loc, blkno;
 	struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
 	struct buffer_head *new_bh = NULL;
 	struct ocfs2_refcount_block *new_rb;
@@ -1299,7 +1300,7 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 		goto out;
 	}
 
-	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
 				   &suballoc_bit_start, &num_got,
 				   &blkno);
 	if (ret) {
@@ -1331,6 +1332,7 @@ static int ocfs2_expand_inline_ref_root(handle_t *handle,
 
 	new_rb = (struct ocfs2_refcount_block *)new_bh->b_data;
 	new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+	new_rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
 	new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	new_rb->rf_blkno = cpu_to_le64(blkno);
 	new_rb->rf_cpos = cpu_to_le32(0);
@@ -1525,7 +1527,7 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 	int ret;
 	u16 suballoc_bit_start;
 	u32 num_got, new_cpos;
-	u64 blkno;
+	u64 suballoc_loc, blkno;
 	struct super_block *sb = ocfs2_metadata_cache_get_super(ci);
 	struct ocfs2_refcount_block *root_rb =
 			(struct ocfs2_refcount_block *)ref_root_bh->b_data;
@@ -1549,7 +1551,7 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 		goto out;
 	}
 
-	ret = ocfs2_claim_metadata(handle, meta_ac, 1,
+	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
 				   &suballoc_bit_start, &num_got,
 				   &blkno);
 	if (ret) {
@@ -1577,6 +1579,7 @@ static int ocfs2_new_leaf_refcount_block(handle_t *handle,
 	memset(new_rb, 0, sb->s_blocksize);
 	strcpy((void *)new_rb, OCFS2_REFCOUNT_BLOCK_SIGNATURE);
 	new_rb->rf_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
+	new_rb->rf_suballoc_loc = cpu_to_le64(suballoc_loc);
 	new_rb->rf_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	new_rb->rf_fs_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
 	new_rb->rf_blkno = cpu_to_le64(blkno);
fs/ocfs2/suballoc.c +13 -3
index 6ac9884..0ee6548 100644
@@ -54,7 +54,9 @@
 #define OCFS2_MAX_TO_STEAL		1024
 
 struct ocfs2_suballoc_result {
-	u64		sr_bg_blkno;	/* The bg we allocated from */
+	u64		sr_bg_blkno;	/* The bg we allocated from.  Set
+					   to 0 when a block group is
+					   contiguous. */
 	u64		sr_blkno;	/* The first allocated block */
 	unsigned int	sr_bit_offset;	/* The bit in the bg */
 	unsigned int	sr_bits;	/* How many bits we claimed */
@@ -1644,6 +1646,7 @@ static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac,
 					  struct ocfs2_suballoc_result *res)
 {
 	int i;
+	u64 bg_blkno = res->sr_bg_blkno;  /* Save off */
 	struct ocfs2_extent_rec *rec;
 	struct ocfs2_dinode *di = (struct ocfs2_dinode *)ac->ac_bh->b_data;
 	struct ocfs2_chain_list *cl = &di->id2.i_chain;
@@ -1654,14 +1657,17 @@ static void ocfs2_bg_discontig_fix_result(struct ocfs2_alloc_context *ac,
 	}
 
 	res->sr_blkno = res->sr_bg_blkno + res->sr_bit_offset;
+	res->sr_bg_blkno = 0;  /* Clear it for contig block groups */
 	if (!ocfs2_supports_discontig_bh(OCFS2_SB(ac->ac_inode->i_sb)) ||
 	    !bg->bg_list.l_next_free_rec)
 		return;
 
 	for (i = 0; i < le16_to_cpu(bg->bg_list.l_next_free_rec); i++) {
 		rec = &bg->bg_list.l_recs[i];
-		if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl))
+		if (ocfs2_bg_discontig_fix_by_rec(res, rec, cl)) {
+			res->sr_bg_blkno = bg_blkno;  /* Restore */
 			break;
+		}
 	}
 }
 
@@ -1972,6 +1978,7 @@ bail:
 int ocfs2_claim_metadata(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 bits_wanted,
+			 u64 *suballoc_loc,
 			 u16 *suballoc_bit_start,
 			 unsigned int *num_bits,
 			 u64 *blkno_start)
@@ -1994,6 +2001,7 @@ int ocfs2_claim_metadata(handle_t *handle,
 	}
 	atomic_inc(&OCFS2_SB(ac->ac_inode->i_sb)->alloc_stats.bg_allocs);
 
+	*suballoc_loc = res.sr_bg_blkno;
 	*suballoc_bit_start = res.sr_bit_offset;
 	*blkno_start = res.sr_blkno;
 	ac->ac_bits_given += res.sr_bits;
@@ -2039,11 +2047,12 @@ int ocfs2_claim_new_inode(handle_t *handle,
 			  struct inode *dir,
 			  struct buffer_head *parent_fe_bh,
 			  struct ocfs2_alloc_context *ac,
+			  u64 *suballoc_loc,
 			  u16 *suballoc_bit,
 			  u64 *fe_blkno)
 {
 	int status;
-	struct ocfs2_suballoc_result res = { .sr_blkno = 0, };
+	struct ocfs2_suballoc_result res;
 
 	mlog_entry_void();
 
@@ -2067,6 +2076,7 @@ int ocfs2_claim_new_inode(handle_t *handle,
 
 	BUG_ON(res.sr_bits != 1);
 
+	*suballoc_loc = res.sr_bg_blkno;
 	*suballoc_bit = res.sr_bit_offset;
 	*fe_blkno = res.sr_blkno;
 	ac->ac_bits_given++;
fs/ocfs2/suballoc.h +2 -0
index 28096dc..c6e1ee7 100644
@@ -84,6 +84,7 @@ int ocfs2_reserve_clusters(struct ocfs2_super *osb,
 int ocfs2_claim_metadata(handle_t *handle,
 			 struct ocfs2_alloc_context *ac,
 			 u32 bits_wanted,
+			 u64 *suballoc_loc,
 			 u16 *suballoc_bit_start,
 			 u32 *num_bits,
 			 u64 *blkno_start);
@@ -91,6 +92,7 @@ int ocfs2_claim_new_inode(handle_t *handle,
 			  struct inode *dir,
 			  struct buffer_head *parent_fe_bh,
 			  struct ocfs2_alloc_context *ac,
+			  u64 *suballoc_loc,
 			  u16 *suballoc_bit,
 			  u64 *fe_blkno);
 int ocfs2_claim_clusters(handle_t *handle,
fs/ocfs2/xattr.c +4 -3
index e8997ca..863ad7a 100644
@@ -2846,7 +2846,7 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 	int ret;
 	u16 suballoc_bit_start;
 	u32 num_got;
-	u64 first_blkno;
+	u64 suballoc_loc, first_blkno;
 	struct ocfs2_dinode *di =  (struct ocfs2_dinode *)inode_bh->b_data;
 	struct buffer_head *new_bh = NULL;
 	struct ocfs2_xattr_block *xblk;
@@ -2859,8 +2859,8 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 	}
 
 	ret = ocfs2_claim_metadata(ctxt->handle, ctxt->meta_ac, 1,
-				   &suballoc_bit_start, &num_got,
-				   &first_blkno);
+				   &suballoc_loc, &suballoc_bit_start,
+				   &num_got, &first_blkno);
 	if (ret < 0) {
 		mlog_errno(ret);
 		goto end;
@@ -2882,6 +2882,7 @@ static int ocfs2_create_xattr_block(struct inode *inode,
 	memset(xblk, 0, inode->i_sb->s_blocksize);
 	strcpy((void *)xblk, OCFS2_XATTR_BLOCK_SIGNATURE);
 	xblk->xb_suballoc_slot = cpu_to_le16(ctxt->meta_ac->ac_alloc_slot);
+	xblk->xb_suballoc_loc = cpu_to_le64(suballoc_loc);
 	xblk->xb_suballoc_bit = cpu_to_le16(suballoc_bit_start);
 	xblk->xb_fs_generation =
 		cpu_to_le32(OCFS2_SB(inode->i_sb)->fs_generation);
Signature · 1 line
1.5.5
author
#10 lore raw

PATCH 10/15 ocfs2: Grow discontig block groups in one transaction.

In reply to Tao Ma

From: Joel Becker <[email protected]>

Rather than extending the transaction every time we add an extent to a discontiguous block group, we grab enough credits to fill the extent list up front. This means we can free the bits in the same transaction if we end up not getting enough space.

---
 fs/ocfs2/journal.h  |   12 ++++++++++++
 fs/ocfs2/suballoc.c |   48 ++++++++++++++++++++++--------------------------
 2 files changed, 34 insertions(+), 26 deletions(-)
fs/ocfs2/journal.h +12 -0
index 3f74e09..45035f5 100644
@@ -562,6 +562,18 @@ static inline int ocfs2_calc_group_alloc_credits(struct super_block *sb,
 	return blocks;
 }
 
+/*
+ * Allocating a discontiguous block group requires the credits from
+ * ocfs2_calc_group_alloc_credits() as well as enough credits to fill
+ * the group descriptor's extent list.  The caller already has started
+ * the transaction with ocfs2_calc_group_alloc_credits().  They extend
+ * it with these credits.
+ */
+static inline int ocfs2_calc_bg_discontig_credits(struct super_block *sb)
+{
+	return ocfs2_extent_recs_per_gd(sb);
+}
+
 static inline int ocfs2_calc_tree_trunc_credits(struct super_block *sb,
 						unsigned int clusters_to_del,
 						struct ocfs2_dinode *fe,
fs/ocfs2/suballoc.c +22 -26

108 lines not on this page · raw message

Signature · 1 line
1.5.5
author
#11 lore raw

PATCH 11/15 ocfs2: Don't relink cluster groups when allocating discontig block groups

In reply to Tao Ma

From: Joel Becker <[email protected]>

We don't have enough credits, and the filesystem is in a full state anyway.

---
 fs/ocfs2/suballoc.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
fs/ocfs2/suballoc.c +8 -0
index 679ac4d..0d2cd75 100644
@@ -613,6 +613,14 @@ ocfs2_block_group_alloc_discontig(handle_t *handle,
 		goto bail;
 	}
 
+	/*
+	 * We're going to be grabbing from multiple cluster groups.
+	 * We don't have enough credits to relink them all, and the
+	 * cluster groups will be staying in cache for the duration of
+	 * this operation.
+	 */
+	ac->ac_allow_chain_relink = 0;
+
 	/* Claim the first region */
 	status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits,
 					      &bit_off, &num_bits);
Signature · 1 line
1.5.5
author
#12 lore raw

PATCH 12/15 ocfs2: Some tiny bug fixes for discontiguous block allocation.

In reply to Tao Ma

The fixes include:
1. some endian problems.
2. we should use bit/bpc in ocfs2_block_group_grow_discontig to allocate clusters.
3. set num_clusters properly in __ocfs2_claim_clusters.
4. change name from ocfs2_supports_discontig_bh to ocfs2_supports_discontig_bg.

---
 fs/ocfs2/ocfs2.h    |    2 +-
 fs/ocfs2/suballoc.c |   41 ++++++++++++++++++++++-------------------
 2 files changed, 23 insertions(+), 20 deletions(-)
fs/ocfs2/ocfs2.h +1 -1
index b5fd76f..85a0899 100644
@@ -482,7 +482,7 @@ static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb)
 	return 0;
 }
 
-static inline int ocfs2_supports_discontig_bh(struct ocfs2_super *osb)
+static inline int ocfs2_supports_discontig_bg(struct ocfs2_super *osb)
 {
 	if (osb->s_feature_incompat & OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
 		return 1;
fs/ocfs2/suballoc.c +22 -19

121 lines not on this page · raw message

Signature · 1 line
1.5.5
author
#16 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

---
 fs/ocfs2/ocfs2_fs.h |    5 +++--
 fs/ocfs2/resize.c   |    4 ++--
 fs/ocfs2/suballoc.c |    3 ++-
 fs/ocfs2/super.c    |    2 +-
 4 files changed, 8 insertions(+), 6 deletions(-)
fs/ocfs2/ocfs2_fs.h +3 -2
index 42641f8..29f32ad 100644
@@ -1346,11 +1346,12 @@ static inline u16 ocfs2_local_alloc_size(struct super_block *sb)
 }
 
 static inline int ocfs2_group_bitmap_size(struct super_block *sb,
-					  int suballocator)
+					  int suballocator,
+					  int support_discontig_bg)
 {
 	int size;
 
-	if (suballocator)
+	if (suballocator && support_discontig_bg)
 		size = OCFS2_MAX_BG_BITMAP_SIZE;
 	else
 		size = sb->s_blocksize -
fs/ocfs2/resize.c +2 -2
index 0ff4835..e6eca60 100644
@@ -319,7 +319,7 @@ int ocfs2_group_extend(struct inode * inode, int new_clusters)
 	BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
 
 	if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
-				 ocfs2_group_bitmap_size(osb->sb, 0) * 8) {
+				 ocfs2_group_bitmap_size(osb->sb, 0, 0) * 8) {
 		mlog(ML_ERROR, "The disk is too old and small. "
 		     "Force to do offline resize.");
 		ret = -EINVAL;
@@ -500,7 +500,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
 	fe = (struct ocfs2_dinode *)main_bm_bh->b_data;
 
 	if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
-				 ocfs2_group_bitmap_size(osb->sb, 0) * 8) {
+				 ocfs2_group_bitmap_size(osb->sb, 0, 0) * 8) {
 		mlog(ML_ERROR, "The disk is too old and small."
 		     " Force to do offline resize.");
 		ret = -EINVAL;
fs/ocfs2/suballoc.c +2 -1
index 0878b5d..0bf6151 100644
@@ -394,7 +394,8 @@ static int ocfs2_block_group_fill(handle_t *handle,
 	memset(bg, 0, sb->s_blocksize);
 	strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE);
 	bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation);
-	bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1));
+	bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb, 1,
+				  ocfs2_supports_discontig_bg(osb)));
 	bg->bg_chain = cpu_to_le16(my_chain);
 	bg->bg_next_group = cl->cl_recs[my_chain].c_blkno;
 	bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno);
fs/ocfs2/super.c +1 -1
index de8547f..b6171df 100644
@@ -2226,7 +2226,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno;
 	iput(inode);
 
-	osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0) * 8;
+	osb->bitmap_cpg = ocfs2_group_bitmap_size(sb, 0, 0) * 8;
 
 	status = ocfs2_init_slot_info(osb);
 	if (status < 0) {
Signature · 1 line
1.5.5
author
#30 lore raw

PATCH 14/15 ocfs2: Free block to the right block group.

In reply to Tao Ma

In case the block we are going to free is allocated from a discontiguous block group, we have to use suballoc_loc to be the right group.

---
 fs/ocfs2/alloc.c        |   18 ++++++++++++------
 fs/ocfs2/alloc.h        |    2 +-
 fs/ocfs2/dir.c          |    5 ++++-
 fs/ocfs2/refcounttree.c |    6 +++++-
 fs/ocfs2/suballoc.c     |    2 ++
 fs/ocfs2/xattr.c        |    5 ++++-
 6 files changed, 28 insertions(+), 10 deletions(-)
fs/ocfs2/alloc.c +12 -6
index 6b59b6f..2f87ac0 100644
@@ -6299,6 +6299,7 @@ int ocfs2_truncate_log_init(struct ocfs2_super *osb)
  */
 struct ocfs2_cached_block_free {
 	struct ocfs2_cached_block_free		*free_next;
+	u64					free_bg;
 	u64					free_blk;
 	unsigned int				free_bit;
 };
@@ -6345,8 +6346,11 @@ static int ocfs2_free_cached_blocks(struct ocfs2_super *osb,
 	}
 
 	while (head) {
-		bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
-						      head->free_bit);
+		if (head->free_bg)
+			bg_blkno = head->free_bg;
+		else
+			bg_blkno = ocfs2_which_suballoc_group(head->free_blk,
+							      head->free_bit);
 		mlog(0, "Free bit: (bit %u, blkno %llu)\n",
 		     head->free_bit, (unsigned long long)head->free_blk);
 
@@ -6394,7 +6398,7 @@ int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
 	int ret = 0;
 	struct ocfs2_cached_block_free *item;
 
-	item = kmalloc(sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_NOFS);
 	if (item == NULL) {
 		ret = -ENOMEM;
 		mlog_errno(ret);
@@ -6534,8 +6538,8 @@ ocfs2_find_per_slot_free_list(int type,
 }
 
 int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
-			      int type, int slot, u64 blkno,
-			      unsigned int bit)
+			      int type, int slot, u64 suballoc,
+			      u64 blkno, unsigned int bit)
 {
 	int ret;
 	struct ocfs2_per_slot_free_list *fl;
@@ -6548,7 +6552,7 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
 		goto out;
 	}
 
-	item = kmalloc(sizeof(*item), GFP_NOFS);
+	item = kzalloc(sizeof(*item), GFP_NOFS);
 	if (item == NULL) {
 		ret = -ENOMEM;
 		mlog_errno(ret);
@@ -6558,6 +6562,7 @@ int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
 	mlog(0, "Insert: (type %d, slot %u, bit %u, blk %llu)\n",
 	     type, slot, bit, (unsigned long long)blkno);
 
+	item->free_bg = suballoc;
 	item->free_blk = blkno;
 	item->free_bit = bit;
 	item->free_next = fl->f_first;
@@ -6574,6 +6579,7 @@ static int ocfs2_cache_extent_block_free(struct ocfs2_cached_dealloc_ctxt *ctxt,
 {
 	return ocfs2_cache_block_dealloc(ctxt, EXTENT_ALLOC_SYSTEM_INODE,
 					 le16_to_cpu(eb->h_suballoc_slot),
+					 le64_to_cpu(eb->h_suballoc_loc),
 					 le64_to_cpu(eb->h_blkno),
 					 le16_to_cpu(eb->h_suballoc_bit));
 }
fs/ocfs2/alloc.h +1 -1
index 1db4359..fc28d64 100644
@@ -209,7 +209,7 @@ static inline void ocfs2_init_dealloc_ctxt(struct ocfs2_cached_dealloc_ctxt *c)
 int ocfs2_cache_cluster_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
 				u64 blkno, unsigned int bit);
 int ocfs2_cache_block_dealloc(struct ocfs2_cached_dealloc_ctxt *ctxt,
-			      int type, int slot, u64 blkno,
+			      int type, int slot, u64 suballoc, u64 blkno,
 			      unsigned int bit);
 static inline int ocfs2_dealloc_has_cluster(struct ocfs2_cached_dealloc_ctxt *c)
 {
fs/ocfs2/dir.c +4 -1
index 48b591d..9cb92d3 100644
@@ -4491,7 +4491,10 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
 
 	blk = le64_to_cpu(dx_root->dr_blkno);
 	bit = le16_to_cpu(dx_root->dr_suballoc_bit);
-	bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+	if (dx_root->dr_suballoc_loc)
+		bg_blkno = le64_to_cpu(dx_root->dr_suballoc_loc);
+	else
+		bg_blkno = ocfs2_which_suballoc_group(blk, bit);
 	ret = ocfs2_free_suballoc_bits(handle, dx_alloc_inode, dx_alloc_bh,
 				       bit, bg_blkno, 1);
 	if (ret)
fs/ocfs2/refcounttree.c +5 -1
index 3fc675f..668a018 100644
@@ -792,7 +792,10 @@ int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh)
 	if (le32_to_cpu(rb->rf_count) == 1) {
 		blk = le64_to_cpu(rb->rf_blkno);
 		bit = le16_to_cpu(rb->rf_suballoc_bit);
-		bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+		if (rb->rf_suballoc_loc)
+			bg_blkno = le64_to_cpu(rb->rf_suballoc_loc);
+		else
+			bg_blkno = ocfs2_which_suballoc_group(blk, bit);
 
 		alloc_inode = ocfs2_get_system_file_inode(osb,
 					EXTENT_ALLOC_SYSTEM_INODE,
@@ -2116,6 +2119,7 @@ static int ocfs2_remove_refcount_extent(handle_t *handle,
 	 */
 	ret = ocfs2_cache_block_dealloc(dealloc, EXTENT_ALLOC_SYSTEM_INODE,
 					le16_to_cpu(rb->rf_suballoc_slot),
+					le64_to_cpu(rb->rf_suballoc_loc),
 					le64_to_cpu(rb->rf_blkno),
 					le16_to_cpu(rb->rf_suballoc_bit));
 	if (ret) {
fs/ocfs2/suballoc.c +2 -0
index 0bf6151..bb0dbb9 100644
@@ -2382,6 +2382,8 @@ int ocfs2_free_dinode(handle_t *handle,
 	u16 bit = le16_to_cpu(di->i_suballoc_bit);
 	u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
 
+	if (di->i_suballoc_loc)
+		bg_blkno = le64_to_cpu(di->i_suballoc_loc);
 	return ocfs2_free_suballoc_bits(handle, inode_alloc_inode,
 					inode_alloc_bh, bit, bg_blkno, 1);
 }
fs/ocfs2/xattr.c +4 -1
index 863ad7a..2447e14 100644
@@ -2479,7 +2479,10 @@ static int ocfs2_xattr_free_block(struct inode *inode,
 	xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
 	blk = le64_to_cpu(xb->xb_blkno);
 	bit = le16_to_cpu(xb->xb_suballoc_bit);
-	bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+	if (xb->xb_suballoc_loc)
+		bg_blkno = le64_to_cpu(xb->xb_suballoc_loc);
+	else
+		bg_blkno = ocfs2_which_suballoc_group(blk, bit);
 
 	xb_alloc_inode = ocfs2_get_system_file_inode(osb,
 				EXTENT_ALLOC_SYSTEM_INODE,
Signature · 1 line
1.5.5
author
#32 lore raw

PATCH 15/15 ocfs2: enable discontig block group support.

In reply to Tao Ma
---
 fs/ocfs2/ocfs2_fs.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
fs/ocfs2/ocfs2_fs.h +2 -1
index 29f32ad..3e3f3b4 100644
@@ -100,7 +100,8 @@
 					 | OCFS2_FEATURE_INCOMPAT_XATTR \
 					 | OCFS2_FEATURE_INCOMPAT_META_ECC \
 					 | OCFS2_FEATURE_INCOMPAT_INDEXED_DIRS \
-					 | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE)
+					 | OCFS2_FEATURE_INCOMPAT_REFCOUNT_TREE \
+					 | OCFS2_FEATURE_INCOMPAT_DISCONTIG_BG)
 #define OCFS2_FEATURE_RO_COMPAT_SUPP	(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN \
 					 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA \
 					 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)
Signature · 1 line
1.5.5
#13 lore raw

PATCH 12/15 ocfs2: Some tiny bug fixes for discontiguous block allocation.

In reply to Tao Ma

fs/ocfs2/ocfs2.h static inline int ocfs2_supports_indexed_dirs(struct ocfs2_super *osb) · line 485

Quoted 2 lines · Tao Ma
fs/ocfs2/ocfs2.h +1 -1
-static inline int ocfs2_supports_discontig_bh(struct ocfs2_super *osb)
+static inline int ocfs2_supports_discontig_bg(struct ocfs2_super *osb)
	D'oh!

fs/ocfs2/suballoc.c static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, · line 351

Quoted 2 lines
fs/ocfs2/suballoc.c +1 -1
-	rec->e_blkno = p_blkno;
+	rec->e_blkno = cpu_to_le64(p_blkno);
	D'oh!!

fs/ocfs2/suballoc.c static void ocfs2_bg_discontig_add_extent(struct ocfs2_super *osb, · line 357

Quoted 2 lines
fs/ocfs2/suballoc.c +2 -0
+	le16_add_cpu(&bg->bg_free_bits_count,
+		     clusters * le16_to_cpu(cl->cl_bpc));
	D'oh!!!

fs/ocfs2/suballoc.c static int ocfs2_block_group_grow_discontig(handle_t *handle, · line 517

Quoted 8 lines
fs/ocfs2/suballoc.c +2 -2
@@ -511,8 +513,8 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle,
 	struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
 	struct ocfs2_group_desc *bg =
 		(struct ocfs2_group_desc *)bg_bh->b_data;
-	unsigned int needed =
-		ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits);
+	unsigned int needed = le16_to_cpu(cl->cl_cpg) -
+			 le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc);

Ouch! But can you put parens around the divide? Make the
intention clear.

fs/ocfs2/suballoc.c static int ocfs2_block_group_alloc(struct ocfs2_super *osb, · line 739

Quoted 8 lines
fs/ocfs2/suballoc.c +2 -1
@@ -733,18 +734,20 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 		goto bail;
 	}
 
-	le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_free,
+	alloc_rec = le16_to_cpu(bg->bg_chain);
+	le32_add_cpu(&cl->cl_recs[alloc_rec].c_free,
 		     le16_to_cpu(bg->bg_free_bits_count));
	D'oh!!!!
Quoted 4 lines
fs/ocfs2/suballoc.c +1 -2
-	le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_total,
+	le32_add_cpu(&cl->cl_recs[alloc_rec].c_total,
 		     le16_to_cpu(bg->bg_bits));
-	cl->cl_recs[bg->bg_chain].c_blkno  = cpu_to_le64(bg_blkno);

fs/ocfs2/suballoc.c static int ocfs2_block_group_alloc(struct ocfs2_super *osb, · line 750

Quoted 10 lines
fs/ocfs2/suballoc.c +3 -1
+	cl->cl_recs[alloc_rec].c_blkno  = cpu_to_le64(bg->bg_blkno);
 	if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count))
 		le16_add_cpu(&cl->cl_next_free_rec, 1);
 
 	le32_add_cpu(&fe->id1.bitmap1.i_used, le16_to_cpu(bg->bg_bits) -
 					le16_to_cpu(bg->bg_free_bits_count));
 	le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits));
-	le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg));
+	le32_add_cpu(&fe->i_clusters,
+		     le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc));

You don't need to change this. Either we've allocated cpg or
we've failed out.

Joel

Signature · 12 lines
"There is shadow under this red rock.
 (Come in under the shadow of this red rock)
 And I will show you something different from either
 Your shadow at morning striding behind you
 Or your shadow at evening rising to meet you.
 I will show you fear in a handful of dust."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#17 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

Joel

Signature · 8 lines
"Get right to the heart of matters.
 It's the heart that matters more."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#31 lore raw

PATCH 14/15 ocfs2: Free block to the right block group.

In reply to Tao Ma
Quoted 5 lines · Tao Ma

In case the block we are going to free is allocated from a discontiguous block group, we have to use suballoc_loc to be the right group.

Boy, this was easier than I expected it to be.

Joel

Signature · 8 lines
 The zen have a saying:
 "When you learn how to listen, ANYONE can be your teacher."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#33 lore raw

PATCH 15/15 ocfs2: enable discontig block group support.

In reply to Tao Ma
Quoted 1 line · Tao Ma

No brainer.

Signature · 10 lines
"I'm drifting and drifting
 Just like a ship out on the sea.
 Cause I ain't got nobody, baby,
 In this world to care for me."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
author
#18 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Joel Becker

Hi Joel,

Quoted 8 lines · Joel Becker
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

No, it hurts.
So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see chainalloc_process_group in libocfs2).

Regards,
Tao

author
#14 lore raw

PATCH 12/15 ocfs2: Some tiny bug fixes for discontiguous block allocation.

In reply to Joel Becker

Hi Joel,

Quoted 12 lines · Joel Becker

fs/ocfs2/suballoc.c static int ocfs2_block_group_grow_discontig(handle_t *handle, · line 517

Quoted 8 lines · Tao Ma
fs/ocfs2/suballoc.c +2 -2
@@ -511,8 +513,8 @@ static int ocfs2_block_group_grow_discontig(handle_t *handle,
 	struct ocfs2_super *osb = OCFS2_SB(alloc_inode->i_sb);
 	struct ocfs2_group_desc *bg =
 		(struct ocfs2_group_desc *)bg_bh->b_data;
-	unsigned int needed =
-		ocfs2_bits_per_group(cl) - le16_to_cpu(bg->bg_bits);
+	unsigned int needed = le16_to_cpu(cl->cl_cpg) -
+			 le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc);

Ouch! But can you put parens around the divide? Make the
intention clear.

no problem.

Quoted 20 lines

fs/ocfs2/suballoc.c static int ocfs2_block_group_alloc(struct ocfs2_super *osb, · line 739

Quoted 9 lines
fs/ocfs2/suballoc.c +2 -1
@@ -733,18 +734,20 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 		goto bail;
 	}
 
-	le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_free,
+	alloc_rec = le16_to_cpu(bg->bg_chain);
+	le32_add_cpu(&cl->cl_recs[alloc_rec].c_free,
 		     le16_to_cpu(bg->bg_free_bits_count));
	D'oh!!!!
Quoted 8 lines
fs/ocfs2/suballoc.c +2 -2
-	le32_add_cpu(&cl->cl_recs[bg->bg_chain].c_total,
+	le32_add_cpu(&cl->cl_recs[alloc_rec].c_total,
 		     le16_to_cpu(bg->bg_bits));
-	cl->cl_recs[bg->bg_chain].c_blkno  = cpu_to_le64(bg_blkno);
+	cl->cl_recs[alloc_rec].c_blkno  = cpu_to_le64(bg->bg_blkno);
 	if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count))
 		le16_add_cpu(&cl->cl_next_free_rec, 1);
 
Quoted 9 lines

fs/ocfs2/suballoc.c static int ocfs2_block_group_alloc(struct ocfs2_super *osb, · line 750

Quoted 6 lines
fs/ocfs2/suballoc.c +2 -1
 	le32_add_cpu(&fe->id1.bitmap1.i_used, le16_to_cpu(bg->bg_bits) -
 					le16_to_cpu(bg->bg_free_bits_count));
 	le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits));
-	le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg));
+	le32_add_cpu(&fe->i_clusters,
+		     le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc));

You don't need to change this. Either we've allocated cpg or
we've failed out.

Current we don't fail out in ocfs2_block_group_grow_discontig when we used up all the extent record in the list. So actually our bitmap size can be less than cpg. So you think we need to bail out?

I removed your
if (needed > 0) {
}
in this function. So maybe I am wrong? ;)

To bail out is simple, we just need to set the status to ENOSPC in this case and it should be enough for us.

Regards,
Tao

#19 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 4 lines · Tao Ma

Hi Joel,

Quoted 1 line · Joel Becker

On Thu, Apr 01, 2010 at 10:59:10AM +0800, Tao Ma wrote:

Quoted 8 lines
Quoted 7 lines
Quoted 2 lines

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

No, it hurts.

Hi,

Quoted 3 lines

So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see chainalloc_process_group in libocfs2).

Just for my info.
Is "old ocfs2-tools + new kernel" supported?

regards,
wengang.

author
#20 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

Hi wengang,

Quoted 13 lines · Wengang Wang
Quoted 11 lines · Tao Ma

Hi Joel,

Quoted 7 lines · Joel Becker
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

No, it hurts.

Quoted 7 lines

Hi,

Quoted 3 lines

So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see chainalloc_process_group in libocfs2).

Just for my info.
Is "old ocfs2-tools + new kernel" supported?

I guess yes? I am not sure whether a user can use a 2.6.35 kernel(the next merge window) while using an ocfs2-tools 1.4.

Regards,
Tao

author
#21 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

Quoted 15 lines · Tao Ma

Hi wengang,

Quoted 12 lines · Wengang Wang
Quoted 11 lines · Tao Ma

Hi Joel,

Quoted 7 lines · Joel Becker
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

No, it hurts.

Quoted 8 lines
Quoted 6 lines

Hi,

Quoted 3 lines

So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see chainalloc_process_group in libocfs2).

Just for my info.
Is "old ocfs2-tools + new kernel" supported?

I guess yes? I am not sure whether a user can use a 2.6.35 kernel(the next merge window) while using an ocfs2-tools 1.4.

actually the most worse thing I am worried about it that: the old fsck.ocfs2 refused to fsck the volume even in case we don't enable discontig-bg because the new kernel set bg_size=256 so the new inode group will be considered corrupted. I don't think it is endurable for a user.

Regards,
Tao

#25 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 9 lines · Tao Ma
Quoted 8 lines · Joel Becker
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

Quoted 5 lines

No, it hurts.
So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see
chainalloc_process_group in libocfs2).

*facepalm*

Well, we shot ourselves in the foot. The entire point of having
the size stored is so that we can vary it and the code still works. Consider that "validation" of bg_size a bug. The correct validation is ((bg_bits + 7) / 8) <= bg_size.
So we do need the kernel to store the old-style bg_size in order
to keep compatibility. But we can do better. First, you don't need the supports_discontig_bg argument. You already have the superblock, just check ocfs2_supports_discontig_bg(OCFS2_SB(sb)).
Secondly, that function needs a big fat comment.

static inline int ocfs2_group_bitmap_size(struct super_block *sb,
int suballocator)

{
	int size = sb->s_blocksize -
		offsetof(struct ocfs2_group_desc, bg_bitmap);

	/*
	 * The cluster allocator uses the entire block.  Suballocators have
	 * never used more than OCFS2_MAX_BG_BITMAP_SIZE.  Unfortunately, older
	 * code expects bg_size set to the maximum.  Thus we must keep
	 * bg_size as-is unless discontig_bg is enabled.
	 */
	if (suballocator && ocfs2_supports_discontig_bg(OCFS2_SB(sb)))
		size = OCFS2_MAX_BG_BITMAP_SIZE;

	return size;
}

Joel

Signature · 9 lines
Life's Little Instruction Book #450

	"Don't be afraid to say, 'I need help.'"

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#24 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Wengang Wang
Quoted 2 lines · Wengang Wang

Just for my info.
Is "old ocfs2-tools + new kernel" supported?

Absolutely. As is "old kernel + new ocfs2-tools". As long as
the features of the particular formatted filesystem are understood by both tools and kernel, they should work.

Joel

Signature · 9 lines
Life's Little Instruction Book #30

	"Never buy a house without a fireplace."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#23 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 4 lines · Tao Ma
Quoted 1 line · Wengang Wang

Is "old ocfs2-tools + new kernel" supported?

I guess yes? I am not sure whether a user can use a 2.6.35 kernel(the next merge window) while using an ocfs2-tools 1.4.

Yes. Even ocfs2-tools 1.2 will work, as long as the filesystem
was formatted with --feature-level=max-compat.

Joel

Signature · 10 lines
"In the arms of the angel, fly away from here,
 From this dark, cold hotel room and the endlessness that you fear.
 You are pulled from the wreckage of your silent reverie.
 In the arms of the angel, may you find some comfort here."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#22 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 5 lines · Tao Ma

actually the most worse thing I am worried about it that: the old fsck.ocfs2 refused to fsck the volume even in case we don't enable discontig-bg because the new kernel set bg_size=256 so the new inode group will be considered corrupted. I don't think it is endurable for a user.

You are absolutely right. We have to make that work.

Joel

Signature · 9 lines
"Reader, suppose you were and idiot.  And suppose you were a member of
 Congress.  But I repeat myself."
	- Mark Twain

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
author
#26 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Joel Becker

Hi Joel,

Quoted 17 lines · Joel Becker
Quoted 8 lines · Tao Ma
Quoted 7 lines · Joel Becker
Quoted 2 lines · Tao Ma

ocfs2_group_bitmap_size has to handle the case when the volume don't have discontiguous block group support.

NAK. We specify 256 in all cases. This doesn't hurt old code
because we've never used more bits. Even though our old bg_size values were much larger, we never used that space because bg_bits was set to the smaller value.

Quoted 5 lines

No, it hurts.
So with an old ocfs2-tools and a new kernel, the new kernel will set it to 256 while the old ocfs2-tools refused to work by checking bg_size(see
chainalloc_process_group in libocfs2).

*facepalm*

Quoted 8 lines

Well, we shot ourselves in the foot. The entire point of having
the size stored is so that we can vary it and the code still works. Consider that "validation" of bg_size a bug. The correct validation is ((bg_bits + 7) / 8) <= bg_size.
So we do need the kernel to store the old-style bg_size in order
to keep compatibility. But we can do better. First, you don't need the supports_discontig_bg argument. You already have the superblock, just check ocfs2_supports_discontig_bg(OCFS2_SB(sb)).

I have thought of this before, but finally I gave up. The reason is that OCFS2_SB(sb) use ocfs2_super which is declared in ocfs2.h. So you see, I don't want to overlap these 2 head files.

Quoted 4 lines

Secondly, that function needs a big fat comment.

static inline int ocfs2_group_bitmap_size(struct super_block *sb,
int suballocator)

Quoted 12 lines
{
	int size = sb->s_blocksize -
		offsetof(struct ocfs2_group_desc, bg_bitmap);

	/*
	 * The cluster allocator uses the entire block.  Suballocators have
	 * never used more than OCFS2_MAX_BG_BITMAP_SIZE.  Unfortunately, older
	 * code expects bg_size set to the maximum.  Thus we must keep
	 * bg_size as-is unless discontig_bg is enabled.
	 */
	if (suballocator && ocfs2_supports_discontig_bg(OCFS2_SB(sb)))
		size = OCFS2_MAX_BG_BITMAP_SIZE;

yes, I can add the comments.

Regards,
Tao

#15 lore raw

PATCH 12/15 ocfs2: Some tiny bug fixes for discontiguous block allocation.

In reply to Tao Ma
Quoted 9 lines · Tao Ma
Quoted 8 lines · Joel Becker

fs/ocfs2/suballoc.c static int ocfs2_block_group_alloc(struct ocfs2_super *osb, · line 750

Quoted 4 lines · Tao Ma
	le32_add_cpu(&fe->id1.bitmap1.i_total, le16_to_cpu(bg->bg_bits));
fs/ocfs2/suballoc.c +2 -1
-	le32_add_cpu(&fe->i_clusters, le16_to_cpu(cl->cl_cpg));
+	le32_add_cpu(&fe->i_clusters,
+		     le16_to_cpu(bg->bg_bits) / le16_to_cpu(cl->cl_bpc));

You don't need to change this. Either we've allocated cpg or
we've failed out.

Quoted 7 lines

Current we don't fail out in ocfs2_block_group_grow_discontig when we used up all the extent record in the list. So actually our bitmap size can be less than cpg. So you think we need to bail out?

I removed your
if (needed > 0) {
}

Um, there's supposed to be the -ENOSPC in there. Looks like
something I didn't complete.
We will NOT support block groups that are smaller than cpg.

Joel

Signature · 12 lines
"But then she looks me in the eye
 And says, 'We're going to last forever,'
 And man you know I can't begin to doubt it.
 Cause it just feels so good and so free and so right,
 I know we ain't never going to change our minds about it, Hey!
 Here comes my girl."

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
#27 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

In reply to Tao Ma
Quoted 8 lines · Tao Ma
Quoted 4 lines · Joel Becker

So we do need the kernel to store the old-style bg_size in order
to keep compatibility. But we can do better. First, you don't need the supports_discontig_bg argument. You already have the superblock, just check ocfs2_supports_discontig_bg(OCFS2_SB(sb)).

I have thought of this before, but finally I gave up. The reason is that OCFS2_SB(sb) use ocfs2_super which is declared in ocfs2.h. So you see, I don't want to overlap these 2 head files.

You're right about OCFS2_SB(). This comes back to your
userspace version of the interface too, where we don't even have the superblock.
Perhaps the ocfs2_fs.h version of the function needs the awful
integer arguments. Maybe we can define a wrapper interface in ocfs2.h that takes the smarter arguments. This would allow most call sites to read better.
We could also define it as ocfs2_group_bitmap_size(struct
super_block *sb, int sysfile_type, u32 feature_incompat). This requires we pass in arguments that are obvious on their face. We're going to have to know the information when we call the function anyway.

Joel

Signature · 9 lines
Life's Little Instruction Book #450

	"Don't be afraid to say, 'I need help.'"

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127
author
#28 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

Quoted 14 lines · Joel Becker
Quoted 11 lines · Tao Ma
Quoted 5 lines · Joel Becker

So we do need the kernel to store the old-style bg_size in order
to keep compatibility. But we can do better. First, you don't need the supports_discontig_bg argument. You already have the superblock, just check ocfs2_supports_discontig_bg(OCFS2_SB(sb)).

I have thought of this before, but finally I gave up. The reason is that OCFS2_SB(sb) use ocfs2_super which is declared in ocfs2.h. So you see, I don't want to overlap these 2 head files.

Quoted 12 lines

You're right about OCFS2_SB(). This comes back to your
userspace version of the interface too, where we don't even have the superblock.
Perhaps the ocfs2_fs.h version of the function needs the awful
integer arguments. Maybe we can define a wrapper interface in ocfs2.h that takes the smarter arguments. This would allow most call sites to read better.
We could also define it as ocfs2_group_bitmap_size(struct
super_block *sb, int sysfile_type, u32 feature_incompat). This requires we pass in arguments that are obvious on their face. We're going to have to know the information when we call the function anyway.

I just went through all the callers of ocfs2_group_bitmap_size and it seems that it is called in 2 scenarios:
1. set bg_size.
2. check some situation in resize.

So how about change it to
ocfs2_group_bitmap_size(struct super_block *sb, struct ocfs2_group_desc *gd) so if gd is NULL, we returns the old value, if not, just return bg_size.

As for place of setting bg_size, we can set bg_bits first and then set bg_size to (bg_bits +7)/8.

Regards,
Tao

Quoted 4 lines

Joel

#29 lore raw

PATCH 13/15 ocfs2: ocfs2_group_bitmap_size has to handle old volume.

Quoted 8 lines · Tao Ma

I just went through all the callers of ocfs2_group_bitmap_size and it seems that it is called in 2 scenarios:
1. set bg_size.
2. check some situation in resize.

So how about change it to
ocfs2_group_bitmap_size(struct super_block *sb, struct ocfs2_group_desc *gd) so if gd is NULL, we returns the old value, if not, just return bg_size.

That makes no sense, because we're asking for "what it should
be", not "what it is".

Quoted 2 lines

As for place of setting bg_size, we can set bg_bits first and then set bg_size to (bg_bits +7)/8.

But when we grow a group, we'll set bg_size to 256, which blows
up tools.

Joel

Signature · 10 lines
You can use a screwdriver to screw in screws or to clean your ears,
however, the latter needs real skill, determination and a lack of fear
of injuring yourself.  It is much the same with JavaScript.
	- Chris Heilmann

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127