[Ocfs2-devel] [PATCH] ocfs2: support empty xattr bucket in find.

Tao Ma tao.ma at oracle.com
Thu Aug 28 18:19:26 PDT 2008


In ocfs2_xattr_buckets_find, when we meet with an empty
bucket, just skip it and try to find another non-empty one.

Note:
We erase empty bucket now when we find it has no xattr in it.
And there are actually many to-dos left if we really want to
disable automatic removal of empty buckets(e.g. when we insert
a new xattr cluster in xattr tree, we have to find a suitable
start hash, and an empty bucket can't give us such information.
That also means that we have to enhance our xattr bucket extension
process and so on). So I am not sure whether this patch should
be committed alone or with the future disabling patches.
Mark, it is up to you. ;)

Signed-off-by: Tao Ma <tao.ma at oracle.com>
---
 fs/ocfs2/xattr.c |  105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 2bc53b1..782abce 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -2241,6 +2241,80 @@ static int ocfs2_find_xe_in_bucket(struct inode *inode,
 }
 
 /*
+ * Try to find a non-empty bucket between low_bucket and high_bucket.
+ *
+ * First try to find one bucket that isn't empty between bucket and
+ * high_bucket. If none, try to find one bucket that isn't empty between
+ * bucket and low_bucket. If all are empty, return the lowest bucket.
+ */
+static int ocfs2_find_not_emtpy_bucket(struct inode *inode,
+				       struct buffer_head **bucket_bh,
+				       int *bucket,
+				       int low_bucket,
+				       int high_bucket,
+				       u64 p_blkno)
+{
+	int i, ret = 0;
+	int old_bucket = *bucket;
+	struct buffer_head *bh = NULL;
+	struct ocfs2_xattr_header *xh = NULL;
+	u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb);
+	u64 blkno;
+
+	for (i = old_bucket + 1; i <= high_bucket; i++) {
+		blkno = p_blkno + i * blk_per_bucket;
+
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,
+				       &bh, OCFS2_BH_CACHED, inode);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		xh = (struct ocfs2_xattr_header *)bh->b_data;
+
+		if (xh->xh_count)
+			goto find_out;
+
+		brelse(bh);
+		bh = NULL;
+	}
+
+	/*
+	 * In case old_bucket is already the lowest one, and we
+	 * haven't find one non-empty bucket above us, return it
+	 * by starting iteration from itself.
+	 */
+	i = old_bucket == low_bucket ? old_bucket : old_bucket - 1;
+	for (; i >= low_bucket; i--) {
+		brelse(bh);
+		bh = NULL;
+		blkno = p_blkno + i * blk_per_bucket;
+
+		ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), blkno,
+				       &bh, OCFS2_BH_CACHED, inode);
+		if (ret) {
+			mlog_errno(ret);
+			goto out;
+		}
+
+		xh = (struct ocfs2_xattr_header *)bh->b_data;
+
+		if (xh->xh_count)
+			break;
+	}
+
+find_out:
+	*bucket_bh = bh;
+	*bucket = i;
+
+	mlog(0, "Find non-empty Bucket %llu.\n",
+	     (unsigned long long)bh->b_blocknr);
+out:
+	return ret;
+}
+
+/*
  * Find the specified xattr entry in a series of buckets.
  * This series start from p_blkno and last for num_clusters.
  * The ocfs2_xattr_header.xh_num_buckets of the first bucket contains
@@ -2294,6 +2368,37 @@ static int ocfs2_xattr_bucket_find(struct inode *inode,
 		}
 
 		xh = (struct ocfs2_xattr_header *)bh->b_data;
+
+		if (!xh->xh_count) {
+			mlog(0, "Bucket %llu is empty.\n",
+			     (unsigned long long)bh->b_blocknr);
+			/*
+			 * this bucket is empty.
+			 * If we have comes to the end(low == high), just
+			 * exit the loop.
+			 *
+			 * If not, try to find one bucket which isn't empty.
+			 */
+			if (low_bucket == high_bucket)
+				break;
+
+			brelse(bh);
+			bh = NULL;
+			ret = ocfs2_find_not_emtpy_bucket(inode, &bh,
+							  &bucket,
+							  low_bucket,
+							  high_bucket,
+							  p_blkno);
+			if (ret) {
+				mlog_errno(ret);
+				goto out;
+			}
+
+			xh = (struct ocfs2_xattr_header *)bh->b_data;
+			if (!xh->xh_count)
+				break;
+		}
+
 		xe = &xh->xh_entries[0];
 		if (name_hash < le32_to_cpu(xe->xe_name_hash)) {
 			high_bucket = bucket - 1;
-- 
1.5.4.GIT




More information about the Ocfs2-devel mailing list