Re: [PATCH 4/5] btrfs: droptree implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13.04.2012 04:53, Tsutomu Itoh wrote:
> Hi, Arne,
> 
> (2012/04/13 0:54), Arne Jansen wrote:
>> This is an implementation of snapshot deletion using the readahead
>> framework. Multiple snapshots can be deleted at once and the trees
>> are not enumerated sequentially but in parallel in many branches.
>> This way readahead can reorder the request to better utilize all
>> disks. For a more detailed description see inline comments.
>>
>> Signed-off-by: Arne Jansen<sensille@xxxxxxx>
>> ---

[snip]

>> +/*
>> + * read the saved state from the droptree inode and prepare everything so
>> + * it gets started by droptree_restart
>> + */
>> +static int droptree_read_state(struct btrfs_fs_info *fs_info,
>> +			       struct inode *inode,
>> +			       struct reada_control *top_rc,
>> +			       struct list_head *droplist)
>> +{
>> +	struct io_ctl io_ctl;
>> +	u32 version;
>> +	u64 generation;
>> +	struct droptree_node **stack;
>> +	int ret = 0;
>> +
>> +	stack = kmalloc(sizeof(*stack) * BTRFS_MAX_LEVEL, GFP_NOFS);
>> +	if (!stack)
>> +		return -ENOMEM;
>> +
>> +	io_ctl_init(&io_ctl, inode, fs_info->tree_root);
>> +	io_ctl.check_crcs = 0;
>> +	io_ctl_prepare_pages(&io_ctl, inode, 1);
>> +
>> +	version = io_ctl_get_u32(&io_ctl);
>> +	if (version != DROPTREE_VERSION) {
>> +		printk(KERN_ERR "btrfs: snapshot deletion state has been saved "
>> +				"with a different version, ignored\n");
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +	/* FIXME generation is currently not needed */
>> +	generation = io_ctl_get_u64(&io_ctl);
>> +
>> +	while (1) {
>> +		struct btrfs_key key;
>> +		int ret;
>> +		struct btrfs_root *del_root;
>> +		struct droptree_root *dr;
>> +		int level;
>> +		int max_level;
>> +		struct droptree_node *root_dn;
>> +
>> +		key.objectid = io_ctl_get_u64(&io_ctl);
>> +		if (key.objectid == 0)
>> +			break;
>> +
>> +		key.type = BTRFS_ROOT_ITEM_KEY;
>> +		key.offset = io_ctl_get_u64(&io_ctl);
>> +		max_level = level = io_ctl_get_u8(&io_ctl);
>> +
>> +		BUG_ON(level<  0 || level>= BTRFS_MAX_LEVEL); /* incons. fs */
>> +		del_root = btrfs_read_fs_root_no_radix(fs_info->tree_root,
>> +							&key);
>> +		if (IS_ERR(del_root)) {
>> +			ret = PTR_ERR(del_root);
>> +			BUG(); /* inconsistent fs */
>> +		}
>> +
>> +		root_dn = droptree_alloc_node(NULL);
>> +		/*
>> +		 * FIXME in this phase is should still be possible to undo
>> +		 * everything and return a failure. Same goes for the allocation
>> +		 * failures below
>> +		 */
>> +		BUG_ON(!root_dn); /* can't back out */
>> +		dr = droptree_add_droproot(droplist, root_dn, del_root);
>> +		BUG_ON(!dr); /* can't back out */
>> +
>> +		stack[level] = root_dn;
>> +
>> +		while (1) {
>> +			u64 start;
>> +			u64 len;
>> +			u64 nritems;
>> +			u32 *map;
>> +			int n;
>> +			int i;
>> +			int parent_slot;
>> +			struct droptree_node *dn;
>> +
>> +			parent_slot = io_ctl_get_u16(&io_ctl);
>> +			if (parent_slot == DROPTREE_STATE_GO_UP) {
>> +				++level;
>> +				BUG_ON(level>  max_level); /* incons. fs */
>> +				continue;
>> +			}
>> +			if (parent_slot == DROPTREE_STATE_GO_DOWN) {
>> +				--level;
>> +				BUG_ON(level<  0); /* incons. fs */
>> +				continue;
>> +			}
>> +			if (parent_slot == DROPTREE_STATE_END)
>> +				break;
>> +			start = io_ctl_get_u64(&io_ctl);
>> +			if (start == 0)
>> +				break;
>> +
>> +			len = io_ctl_get_u64(&io_ctl);
>> +			nritems = io_ctl_get_u16(&io_ctl);
>> +			n = DT_BITS_TO_U32(nritems);
>> +			BUG_ON(n>  999999); /* incons. fs */
>> +			BUG_ON(n == 0); /* incons. fs */
>> +
>> +			map = kmalloc(n * sizeof(u32), GFP_NOFS);
>> +			BUG_ON(!map); /* can't back out */
>> +
>> +			for (i = 0; i<  n; ++i)
>> +				map[i] = io_ctl_get_u32(&io_ctl);
>> +
>> +			if (level == max_level) {
>> +				/* only for root node */
>> +				dn = stack[level];
>> +			} else {
>> +				dn = droptree_alloc_node(dr);
>> +				BUG_ON(!dn); /* can't back out */
>> +				dn->parent = stack[level + 1];
>> +				dn->parent_slot = parent_slot;
>> +				list_add_tail(&dn->next,
>> +					&stack[level+1]->children);
>> +				stack[level] = dn;
>> +			}
>> +			dn->level = level;
>> +			dn->start = start;
>> +			dn->len = len;
>> +			dn->map = map;
>> +			dn->nritems = nritems;
>> +			dn->generation = 0;
>> +		}
>> +		ret = droptree_reada_root(top_rc, dr);
>> +		BUG_ON(ret); /* can't back out */
>> +	}
>> +out:
>> +	io_ctl_drop_pages(&io_ctl);
>> +	io_ctl_free(&io_ctl);
>> +	kfree(stack);
>> +
>> +	return ret;
>> +}
>> +
>> +/*
>> + * called from transaction.c with a list of roots to delete
>> + */
>> +void droptree_drop_list(struct btrfs_fs_info *fs_info, struct list_head *list)
>> +{
>> +	struct btrfs_root *root = fs_info->tree_root;
>> +	struct inode *inode = NULL;
>> +	struct btrfs_path *path = NULL;
>> +	int ret;
>> +	struct btrfs_trans_handle *trans;
>> +	u64 alloc_hint = 0;
>> +	u64 prealloc;
>> +	loff_t oldsize;
>> +	long max_nodes;
>> +	int i;
>> +	struct list_head droplist;
>> +	struct droptree_root *dr;
>> +	struct droptree_root *dtmp;
>> +	int running_roots = 0;
>> +	struct reada_control *top_rc = NULL;
>> +
>> +	if (btrfs_fs_closing(fs_info))
>> +		return;
>> +
>> +	inode = droptree_get_inode(fs_info);
> 
>> +	if (IS_ERR(inode))
> 
> 	if (IS_ERR_OR_NULL(inode))

got it, thanks for catching it.

-Arne

> 
> Thanks,
> Tsutomu
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux