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

Tao Ma tao.ma at oracle.com
Sun Dec 20 20:46:35 PST 2009


Hi coly,

Coly Li wrote:
> 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)
oh, you really don't need to touch the bitmap here.All you need is call 
  ocfs2_chain_free_with_io and it will work for you. Just take 
ocfs2_delete_extent_block for reference.
> +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);You didn't fresh the di here, so you will write it back in the caller?
> +	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);
ocfs2_tree_find_leaf is used to find a leaf in the extent tree.
You use it in dx_tree, so here the root_blkno and root_buf should be the 
  root of the dx tree, not dinode tree.
> +		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 );
You don't need to iterate the extent tree by yourself. Take 
ocfs2_xattr_value_truncate for reference.
> +		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;
> +}

Regards,
Tao



More information about the Ocfs2-tools-devel mailing list