[Ocfs2-tools-devel] [RFC 2/4] dx_dirs v1: libocfs2/dir_indexed.[ch]

Coly Li coly.li at suse.de
Sun Dec 20 10:02:17 PST 2009


This patch adds libocfs2/dir_indexed.h and libocfs2/dir_indexed.c for indexed dirs.

Signed-off-by: Coly Li <coly.li at suse.de>
---
diff --git a/libocfs2/dir_indexed.c b/libocfs2/dir_indexed.c
new file mode 100644
index 0000000..5e3366a
--- /dev/null
+++ b/libocfs2/dir_indexed.c
@@ -0,0 +1,239 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * Copyright (C) 2009 Novell.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2,  as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+#include <ocfs2/ocfs2.h>
+#include <ocfs2/bitops.h>
+#include <ocfs2/kernel-rbtree.h>
+#include "extent_tree.h"
+#include "dir_indexed.h"
+
+static inline uint64_t ocfs2_which_suballoc_group(uint64_t blk, uint32_t bit)
+{
+	uint64_t group = blk - (uint64_t)bit;
+	return group;
+}
+
+static int ocfs2_block_group_clear_bits(ocfs2_filesys *fs,
+		struct ocfs2_group_desc *grp,
+		struct ocfs2_dinode *sys_di,
+		uint32_t bit_off,
+		uint32_t bits_nr)
+{
+	unsigned int tmp;
+
+	tmp = bits_nr;
+	while(tmp--) {
+		ocfs2_clear_bit((bit_off + tmp),
+				(unsigned long *)grp->bg_bitmap);
+	}
+	grp->bg_free_bits_count += bits_nr;
+
+	return 0;
+
+}
+
+static int ocfs2_free_suballoc_bits(ocfs2_filesys *fs,
+				struct ocfs2_dinode *di,
+				uint32_t start_bit,
+				uint64_t bg_blkno,
+				uint32_t count)
+{
+	int ret = 0;
+	char *bg_desc_buf = NULL;
+	char *sysinode_buf = NULL;
+	struct ocfs2_group_desc *grp;
+	struct ocfs2_dinode *sys_di;
+	int chain_nr;
+	uint64_t blkno;
+	struct ocfs2_chain_list *cl;
+
+	chain_nr = di->i_suballoc_slot;
+
+	ret = ocfs2_lookup_system_inode(fs, INODE_ALLOC_SYSTEM_INODE, chain_nr, &blkno);
+	if (ret)
+		goto bail;
+	ret = ocfs2_malloc_block(fs->fs_io, &sysinode_buf);
+	if (ret)
+		goto bail;
+	ret = ocfs2_read_inode(fs, blkno, sysinode_buf);
+	if (ret)
+		goto bail;
+	sys_di = (struct ocfs2_dinode *)sysinode_buf;
+	cl = &sys_di->id2.i_chain;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &bg_desc_buf);
+	if (ret)
+		goto bail;
+	ret = ocfs2_read_group_desc(fs, bg_blkno, bg_desc_buf);
+	if (ret)
+		goto bail;
+	grp = (struct ocfs2_group_desc *)bg_desc_buf;
+
+	ret = ocfs2_block_group_clear_bits(fs, grp, sys_di, start_bit, count);
+	if (ret)
+		goto bail;
+
+	cl->cl_recs[grp->bg_chain].c_free += count;
+	sys_di->id1.bitmap1.i_used -= count;
+
+	ret = ocfs2_write_inode(fs, blkno, sysinode_buf);
+	if (ret)
+		goto bail;
+	ret = ocfs2_write_group_desc(fs, bg_blkno, bg_desc_buf);
+	if (ret)
+		goto bail;
+
+bail:
+	if (bg_desc_buf)
+		ocfs2_free(&bg_desc_buf);
+	if (sysinode_buf)
+		ocfs2_free(&sysinode_buf);
+	return ret;
+}
+
+static int ocfs2_dx_dir_remove_index(ocfs2_filesys *fs,
+					struct ocfs2_dinode *di,
+					struct ocfs2_dx_root_block *dx_root)
+{
+	uint64_t blk, bg_blkno;
+	uint16_t bit;
+	int ret = 0;
+
+	di->i_dyn_features &= ~OCFS2_INDEXED_DIR_FL;
+	di->i_dx_root = 0;
+	blk = dx_root->dr_blkno;
+	bit = dx_root->dr_suballoc_bit;
+	bg_blkno = ocfs2_which_suballoc_group(blk, bit);
+	ret = ocfs2_free_suballoc_bits(fs, di, bit, bg_blkno, 1);
+	return ret;
+}
+
+static int ocfs2_dx_dir_lookup_rec(ocfs2_filesys *fs,
+					struct ocfs2_dinode *di,
+					struct ocfs2_extent_list *el,
+					uint32_t major_hash,
+					uint64_t *ret_cpos,
+					uint64_t *ret_phys_blkno,
+					unsigned int *ret_clen)
+{
+	int ret = 0, i, found;
+	char *eb_buf = NULL;
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_rec *rec = NULL;
+
+	if (el->l_tree_depth) {
+		ret = ocfs2_tree_find_leaf(fs, el, di->i_blkno,
+			       (char *)di, major_hash, &eb_buf);
+		if (ret)
+			goto out;
+
+		eb = (struct ocfs2_extent_block *) eb_buf;
+		el = &eb->h_list;
+
+		if (el->l_tree_depth) {
+			ret = OCFS2_ET_CORRUPT_EXTENT_BLOCK;
+			goto out;
+		}
+	}
+
+	found = 0;
+	for (i = el->l_next_free_rec - 1; i >= 0; i--) {
+		rec = &el->l_recs[i];
+		if (rec->e_cpos <= major_hash) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		printf("does not find a leaf\n");
+		ret = OCFS2_ET_INTERNAL_FAILURE;
+		goto out;
+	}
+
+	if (ret_phys_blkno)
+		*ret_phys_blkno = rec->e_blkno;
+	if (ret_cpos)
+		*ret_cpos = rec->e_cpos;
+	if (ret_clen)
+		*ret_clen = rec->e_leaf_clusters;
+
+out:
+	if (eb_buf)
+		ocfs2_free(&eb_buf);
+	return ret;
+}
+
+int ocfs2_dx_dir_truncate(ocfs2_filesys *fs,
+			struct ocfs2_dinode *di)
+{
+	struct ocfs2_extent_tree et;
+	struct ocfs2_dx_root_block *dx_root;
+	char *dx_root_buf = NULL;
+	int ret;
+	uint64_t blkno, cpos, p_cpos;
+	uint32_t clen, major_hash = UINT_MAX;
+
+	if (!(di->i_dyn_features & OCFS2_INDEXED_DIR_FL))
+		return 0;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &dx_root_buf);
+	if (ret)
+		goto bail;
+	ret = ocfs2_read_dx_root(fs, (uint64_t)di->i_dx_root, dx_root_buf);
+	if (ret)
+		goto bail;
+	dx_root = (struct ocfs2_dx_root_block *)dx_root_buf;
+
+	if (dx_root->dr_flags & OCFS2_DX_FLAG_INLINE)
+		goto remove_index;
+
+	ocfs2_init_dx_root_extent_tree(&et, fs, (char *)dx_root, (uint64_t)di->i_dx_root);
+
+	while (dx_root->dr_clusters) {
+		ret = ocfs2_dx_dir_lookup_rec(fs, di, &dx_root->dr_list,
+			       major_hash, &cpos, &blkno, &clen );
+		if (ret) {
+			printf("error!!\n");
+			goto bail;
+		}
+
+		p_cpos = ocfs2_blocks_to_clusters(fs, blkno);
+		ret = ocfs2_remove_btree_range(fs, di, &et, cpos, p_cpos, clen);
+		if (ret) {
+			printf(" remove btree range error !!");
+			goto bail;
+		}
+		if (cpos == 0)
+			break;
+
+		major_hash = cpos - 1;
+	}
+
+remove_index:
+	ret = ocfs2_dx_dir_remove_index(fs, di, dx_root);
+
+bail:
+	if (dx_root_buf)
+		ocfs2_free(&dx_root_buf);
+	return ret;
+}
+
+
+
diff --git a/libocfs2/dir_indexed.h b/libocfs2/dir_indexed.h
new file mode 100644
index 0000000..a464a73
--- /dev/null
+++ b/libocfs2/dir_indexed.h
@@ -0,0 +1,20 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir_indexed.h
+ *
+ * Copyright (C) 2009 Novell.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+int __ocfs2_is_dir_trailer(ocfs2_filesys *fs, unsigned long de_off);
+int ocfs2_is_dir_trailer(ocfs2_filesys *fs, struct ocfs2_dinode *di,
+				unsigned long de_off);
diff --git a/libocfs2/dirblock.c b/libocfs2/dirblock.c
index 06a1b64..62e48af 100644
--- a/libocfs2/dirblock.c
+++ b/libocfs2/dirblock.c
@@ -32,7 +32,7 @@

 #include "ocfs2/byteorder.h"
 #include "ocfs2/ocfs2.h"
-
+#include "dir_indexed.h"

 unsigned int ocfs2_dir_trailer_blk_off(ocfs2_filesys *fs)
 {

-- 
Coly Li
SuSE Labs



More information about the Ocfs2-tools-devel mailing list