summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--convert.c264
-rw-r--r--ctree.c17
-rw-r--r--disk-io.c8
-rw-r--r--extent-tree.c24
4 files changed, 145 insertions, 168 deletions
diff --git a/convert.c b/convert.c
index 9f466031..d2c9efa9 100644
--- a/convert.c
+++ b/convert.c
@@ -141,6 +141,9 @@ static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)
bytenr + STRIPE_LEN - 1, 0);
}
+ clear_extent_dirty(&root->fs_info->free_space_cache,
+ 0, BTRFS_SUPER_INFO_OFFSET - 1, 0);
+
return 0;
}
@@ -364,7 +367,7 @@ static int record_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item *fi;
struct btrfs_key ins_key;
struct btrfs_path path;
- struct btrfs_extent_item extent_item;
+ struct btrfs_extent_item *ei;
u32 blocksize = root->sectorsize;
u64 nbytes;
u64 bytes_used;
@@ -432,13 +435,25 @@ static int record_file_extent(struct btrfs_trans_handle *trans,
bytes_used = btrfs_root_used(&root->root_item);
btrfs_set_root_used(&root->root_item, bytes_used + num_bytes);
+ btrfs_release_path(root, &path);
+
ins_key.objectid = disk_bytenr;
ins_key.offset = num_bytes;
- btrfs_set_key_type(&ins_key, BTRFS_EXTENT_ITEM_KEY);
- btrfs_set_stack_extent_refs(&extent_item, 0);
- ret = btrfs_insert_item(trans, extent_root, &ins_key,
- &extent_item, sizeof(extent_item));
+ ins_key.type = BTRFS_EXTENT_ITEM_KEY;
+
+ ret = btrfs_insert_empty_item(trans, extent_root, &path,
+ &ins_key, sizeof(*ei));
if (ret == 0) {
+ leaf = path.nodes[0];
+ ei = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_extent_item);
+
+ btrfs_set_extent_refs(leaf, ei, 0);
+ btrfs_set_extent_generation(leaf, ei, 0);
+ btrfs_set_extent_flags(leaf, ei, BTRFS_EXTENT_FLAG_DATA);
+
+ btrfs_mark_buffer_dirty(leaf);
+
bytes_used = btrfs_super_bytes_used(&info->super_copy);
btrfs_set_super_bytes_used(&info->super_copy, bytes_used +
num_bytes);
@@ -451,9 +466,9 @@ static int record_file_extent(struct btrfs_trans_handle *trans,
}
btrfs_extent_post_op(trans, extent_root);
- ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes,
- leaf->start, root->root_key.objectid,
- trans->transid, objectid);
+ ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0,
+ root->root_key.objectid,
+ objectid, file_pos);
if (ret)
goto fail;
ret = 0;
@@ -1239,17 +1254,16 @@ static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs,
struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_root *extent_root = fs_info->extent_root;
struct btrfs_trans_handle *trans;
- struct btrfs_extent_ref *ref_item;
+ struct btrfs_extent_item *ei;
+ struct btrfs_extent_inline_ref *iref;
+ struct btrfs_extent_data_ref *dref;
u64 bytenr;
u64 num_bytes;
- u64 ref_root;
- u64 ref_owner;
u64 objectid;
u64 last_byte;
u64 first_free;
u64 total_bytes;
u32 sectorsize = root->sectorsize;
- int file_extent;
total_bytes = btrfs_super_total_bytes(&fs_info->super_copy);
first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize * 2 - 1;
@@ -1315,43 +1329,28 @@ next:
path.slots[0]++;
goto next;
}
- /*
- * Check backref to distinguish extent items for normal
- * files (files that correspond to files in Ext2fs) from
- * extent items for ctree blocks.
- */
+
bytenr = key.objectid;
num_bytes = key.offset;
- file_extent = 0;
- while (1) {
- if (path.slots[0] >= btrfs_header_nritems(leaf)) {
- ret = btrfs_next_leaf(extent_root, &path);
- if (ret > 0)
- break;
- if (ret < 0)
- goto fail;
- leaf = path.nodes[0];
- }
- btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
- if (key.objectid != bytenr)
- break;
- if (key.type != BTRFS_EXTENT_REF_KEY) {
- path.slots[0]++;
- continue;
- }
- ref_item = btrfs_item_ptr(leaf, path.slots[0],
- struct btrfs_extent_ref);
- ref_root = btrfs_ref_root(leaf, ref_item);
- ref_owner = btrfs_ref_objectid(leaf, ref_item);
- if ((ref_root == BTRFS_FS_TREE_OBJECTID) &&
- (ref_owner >= BTRFS_FIRST_FREE_OBJECTID)) {
- file_extent = 1;
- break;
- }
+ ei = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_extent_item);
+ if (!(btrfs_extent_flags(leaf, ei) & BTRFS_EXTENT_FLAG_DATA)) {
path.slots[0]++;
+ goto next;
}
- if (!file_extent)
+
+ BUG_ON(btrfs_item_size_nr(leaf, path.slots[0]) != sizeof(*ei) +
+ btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY));
+
+ iref = (struct btrfs_extent_inline_ref *)(ei + 1);
+ key.type = btrfs_extent_inline_ref_type(leaf, iref);
+ BUG_ON(key.type != BTRFS_EXTENT_DATA_REF_KEY);
+ dref = (struct btrfs_extent_data_ref *)(&iref->offset);
+ if (btrfs_extent_data_ref_root(leaf, dref) !=
+ BTRFS_FS_TREE_OBJECTID) {
+ path.slots[0]++;
goto next;
+ }
if (bytenr > last_byte) {
ret = create_image_file_range(trans, root, objectid,
@@ -1727,7 +1726,6 @@ static int create_subvol(struct btrfs_trans_handle *trans,
ret = btrfs_make_root_dir(trans, new_root, BTRFS_FIRST_FREE_OBJECTID);
BUG_ON(ret);
- btrfs_free_fs_root(root->fs_info, new_root);
return 0;
}
@@ -1737,6 +1735,7 @@ static int init_btrfs(struct btrfs_root *root)
struct btrfs_key location;
struct btrfs_trans_handle *trans;
struct btrfs_fs_info *fs_info = root->fs_info;
+ struct extent_buffer *tmp;
trans = btrfs_start_transaction(root, 1);
BUG_ON(!trans);
@@ -1775,6 +1774,11 @@ static int init_btrfs(struct btrfs_root *root)
ret = create_subvol(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
BUG_ON(ret);
+ ret = __btrfs_cow_block(trans, fs_info->csum_root,
+ fs_info->csum_root->node, NULL, 0, &tmp, 0, 0);
+ BUG_ON(ret);
+ free_extent_buffer(tmp);
+
ret = btrfs_commit_transaction(trans, root);
BUG_ON(ret);
err:
@@ -1906,7 +1910,7 @@ fail:
static int relocate_one_reference(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 extent_start, u64 extent_size,
- u64 objectid, struct btrfs_key *leaf_key,
+ struct btrfs_key *extent_key,
struct extent_io_tree *reloc_tree)
{
struct extent_buffer *leaf;
@@ -1916,72 +1920,32 @@ static int relocate_one_reference(struct btrfs_trans_handle *trans,
struct btrfs_inode_item inode;
struct blk_iterate_data data;
u64 bytenr;
- u64 offset;
u64 num_bytes;
u64 cur_offset;
u64 new_pos;
u64 nbytes;
- u64 root_gen;
- u64 root_owner;
u64 sector_end;
- u32 nritems;
u32 sectorsize = root->sectorsize;
unsigned long ptr;
- int found = 0;
int datacsum;
int fd;
int ret;
- memcpy(&key, leaf_key, sizeof(key));
- if (key.objectid < objectid ||
- (key.objectid == objectid &&
- key.type < BTRFS_EXTENT_DATA_KEY)) {
- key.objectid = objectid;
- key.type = BTRFS_EXTENT_DATA_KEY;
- key.offset = 0;
- }
btrfs_init_path(&path);
-recow:
- ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
- if (ret < 0)
+ ret = btrfs_search_slot(trans, root, extent_key, &path, -1, 1);
+ if (ret)
goto fail;
leaf = path.nodes[0];
- nritems = btrfs_header_nritems(leaf);
- while (1) {
- if (path.slots[0] >= nritems) {
- ret = btrfs_next_leaf(root, &path);
- if (ret < 0)
- goto fail;
- if (ret > 0)
- break;
- btrfs_item_key_to_cpu(path.nodes[0], &key,
- path.slots[0]);
- btrfs_release_path(root, &path);
- goto recow;
- }
- btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
- if (key.objectid != objectid ||
- key.type != BTRFS_EXTENT_DATA_KEY)
- break;
- fi = btrfs_item_ptr(leaf, path.slots[0],
- struct btrfs_file_extent_item);
- if (extent_start == btrfs_file_extent_disk_bytenr(leaf, fi) &&
- extent_size == btrfs_file_extent_disk_num_bytes(leaf, fi)) {
- offset = key.offset;
- found = 1;
- break;
- }
- path.slots[0]++;
- }
-
- if (!found) {
+ fi = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_file_extent_item);
+ BUG_ON(btrfs_file_extent_offset(leaf, fi) > 0);
+ if (extent_start != btrfs_file_extent_disk_bytenr(leaf, fi) ||
+ extent_size != btrfs_file_extent_disk_num_bytes(leaf, fi)) {
ret = 1;
goto fail;
}
- root_gen = btrfs_header_generation(leaf);
- root_owner = btrfs_header_owner(leaf);
bytenr = extent_start + btrfs_file_extent_offset(leaf, fi);
num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
@@ -1989,15 +1953,15 @@ recow:
if (ret)
goto fail;
- ret = btrfs_free_extent(trans, root,
- extent_start, extent_size, leaf->start,
- root_owner, root_gen, objectid, 0);
+ ret = btrfs_free_extent(trans, root, extent_start, extent_size, 0,
+ root->root_key.objectid,
+ extent_key->objectid, extent_key->offset);
if (ret)
goto fail;
btrfs_release_path(root, &path);
- key.objectid = objectid;
+ key.objectid = extent_key->objectid;
key.offset = 0;
key.type = BTRFS_INODE_ITEM_KEY;
ret = btrfs_lookup_inode(trans, root, &path, &key, 0);
@@ -2018,8 +1982,8 @@ recow:
.trans = trans,
.root = root,
.inode = &inode,
- .objectid = objectid,
- .first_block = offset / sectorsize,
+ .objectid = extent_key->objectid,
+ .first_block = extent_key->offset / sectorsize,
.disk_block = 0,
.num_blocks = 0,
.boundary = (u64)-1,
@@ -2027,7 +1991,7 @@ recow:
.errcode = 0,
};
- cur_offset = offset;
+ cur_offset = extent_key->offset;
while (num_bytes > 0) {
sector_end = bytenr + sectorsize - 1;
if (test_range_bit(reloc_tree, bytenr, sector_end,
@@ -2040,7 +2004,7 @@ recow:
goto fail;
new_pos = key.objectid;
- if (cur_offset == offset) {
+ if (cur_offset == extent_key->offset) {
fd = root->fs_info->fs_devices->latest_bdev;
readahead(fd, bytenr, num_bytes);
}
@@ -2068,14 +2032,15 @@ recow:
}
if (data.num_blocks > 0) {
- ret = record_file_blocks(trans, root, objectid, &inode,
+ ret = record_file_blocks(trans, root,
+ extent_key->objectid, &inode,
data.first_block, data.disk_block,
data.num_blocks, datacsum);
if (ret)
goto fail;
}
- key.objectid = objectid;
+ key.objectid = extent_key->objectid;
key.offset = 0;
key.type = BTRFS_INODE_ITEM_KEY;
ret = btrfs_lookup_inode(trans, root, &path, &key, 1);
@@ -2101,21 +2066,22 @@ static int relocate_extents_range(struct btrfs_root *fs_root,
struct btrfs_root *extent_root = info->extent_root;
struct btrfs_root *cur_root = NULL;
struct btrfs_trans_handle *trans;
- struct btrfs_extent_ref *ref_item;
+ struct btrfs_extent_data_ref *dref;
+ struct btrfs_extent_inline_ref *iref;
+ struct btrfs_extent_item *ei;
struct extent_buffer *leaf;
struct btrfs_key key;
- struct btrfs_key leaf_key;
+ struct btrfs_key extent_key;
struct btrfs_path path;
struct extent_io_tree reloc_tree;
+ unsigned long ptr;
+ unsigned long end;
u64 cur_byte;
u64 num_bytes;
u64 ref_root;
- u64 ref_owner;
- u64 num_refs;
- u64 leaf_start;
+ u64 num_extents;
int pass = 0;
int ret;
- int found;
btrfs_init_path(&path);
extent_io_tree_init(&reloc_tree);
@@ -2141,7 +2107,7 @@ static int relocate_extents_range(struct btrfs_root *fs_root,
btrfs_release_path(extent_root, &path);
again:
cur_root = (pass % 2 == 0) ? ext2_root : fs_root;
- num_refs = 0;
+ num_extents = 0;
trans = btrfs_start_transaction(cur_root, 1);
BUG_ON(!trans);
@@ -2175,53 +2141,47 @@ next:
if (key.objectid >= end_byte)
break;
+ num_extents++;
+
cur_byte = key.objectid;
num_bytes = key.offset;
- found = 0;
- while (1) {
- if (path.slots[0] >= btrfs_header_nritems(leaf)) {
- ret = btrfs_next_leaf(extent_root, &path);
- if (ret > 0)
- break;
- if (ret < 0)
- goto fail;
- leaf = path.nodes[0];
- }
+ ei = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_extent_item);
+ BUG_ON(!(btrfs_extent_flags(leaf, ei) &
+ BTRFS_EXTENT_FLAG_DATA));
- btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
- if (key.objectid != cur_byte)
- break;
- if (key.type != BTRFS_EXTENT_REF_KEY) {
- path.slots[0]++;
- continue;
- }
- ref_item = btrfs_item_ptr(leaf, path.slots[0],
- struct btrfs_extent_ref);
- ref_root = btrfs_ref_root(leaf, ref_item);
- ref_owner = btrfs_ref_objectid(leaf, ref_item);
- leaf_start = key.offset;
- num_refs++;
-
- BUG_ON(ref_owner < BTRFS_FIRST_FREE_OBJECTID);
- if (ref_root == cur_root->root_key.objectid) {
- found = 1;
+ ptr = btrfs_item_ptr_offset(leaf, path.slots[0]);
+ end = ptr + btrfs_item_size_nr(leaf, path.slots[0]);
+
+ ptr += sizeof(struct btrfs_extent_item);
+
+ while (ptr < end) {
+ iref = (struct btrfs_extent_inline_ref *)ptr;
+ key.type = btrfs_extent_inline_ref_type(leaf, iref);
+ BUG_ON(key.type != BTRFS_EXTENT_DATA_REF_KEY);
+ dref = (struct btrfs_extent_data_ref *)(&iref->offset);
+ ref_root = btrfs_extent_data_ref_root(leaf, dref);
+ extent_key.objectid =
+ btrfs_extent_data_ref_objectid(leaf, dref);
+ extent_key.offset =
+ btrfs_extent_data_ref_offset(leaf, dref);
+ extent_key.type = BTRFS_EXTENT_DATA_KEY;
+ BUG_ON(btrfs_extent_data_ref_count(leaf, dref) != 1);
+
+ if (ref_root == cur_root->root_key.objectid)
break;
- }
- path.slots[0]++;
+
+ ptr += btrfs_extent_inline_ref_size(key.type);
}
- if (!found)
- goto next;
- leaf = read_tree_block(cur_root, leaf_start,
- btrfs_level_size(cur_root, 0), 0);
- BUG_ON(!leaf);
- BUG_ON(btrfs_header_level(leaf) != 0);
- btrfs_item_key_to_cpu(leaf, &leaf_key, 0);
- free_extent_buffer(leaf);
+ if (ptr >= end) {
+ path.slots[0]++;
+ goto next;
+ }
ret = relocate_one_reference(trans, cur_root, cur_byte,
- num_bytes, ref_owner,
- &leaf_key, &reloc_tree);
+ num_bytes, &extent_key,
+ &reloc_tree);
if (ret < 0)
goto fail;
@@ -2240,10 +2200,10 @@ next:
ret = btrfs_commit_transaction(trans, cur_root);
BUG_ON(ret);
- if (num_refs > 0 && pass++ < 16)
+ if (num_extents > 0 && pass++ < 16)
goto again;
- ret = (num_refs > 0) ? -1 : 0;
+ ret = (num_extents > 0) ? -1 : 0;
fail:
btrfs_release_path(cur_root, &path);
extent_io_tree_cleanup(&reloc_tree);
@@ -2477,7 +2437,6 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
fprintf(stderr, "error during cleanup_sys_chunk %d\n", ret);
goto fail;
}
- btrfs_free_fs_root(ext2_root->fs_info, ext2_root);
ret = close_ctree(root);
if (ret) {
fprintf(stderr, "error during close_ctree %d\n", ret);
@@ -2706,7 +2665,6 @@ next_extent:
path.slots[0]++;
}
btrfs_release_path(ext2_root, &path);
- btrfs_free_fs_root(ext2_root->fs_info, ext2_root);
if (offset < total_bytes) {
fprintf(stderr, "unable to build extent mapping\n");
diff --git a/ctree.c b/ctree.c
index 2756dbf3..f70e10cc 100644
--- a/ctree.c
+++ b/ctree.c
@@ -1266,8 +1266,8 @@ again:
b = read_node_slot(root, b, slot);
} else {
p->slots[level] = slot;
- if (ins_len > 0 && btrfs_leaf_free_space(root, b) <
- sizeof(struct btrfs_item) + ins_len) {
+ if (ins_len > 0 &&
+ ins_len > btrfs_leaf_free_space(root, b)) {
int sret = split_leaf(trans, root, key,
p, ins_len, ret == 0);
BUG_ON(sret > 0);
@@ -1745,7 +1745,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
right = read_node_slot(root, upper, slot + 1);
free_space = btrfs_leaf_free_space(root, right);
- if (free_space < data_size + sizeof(struct btrfs_item)) {
+ if (free_space < data_size) {
free_extent_buffer(right);
return 1;
}
@@ -1758,7 +1758,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
return 1;
}
free_space = btrfs_leaf_free_space(root, right);
- if (free_space < data_size + sizeof(struct btrfs_item)) {
+ if (free_space < data_size) {
free_extent_buffer(right);
return 1;
}
@@ -1897,7 +1897,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
left = read_node_slot(root, path->nodes[1], slot - 1);
free_space = btrfs_leaf_free_space(root, left);
- if (free_space < data_size + sizeof(struct btrfs_item)) {
+ if (free_space < data_size) {
free_extent_buffer(left);
return 1;
}
@@ -1912,7 +1912,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
}
free_space = btrfs_leaf_free_space(root, left);
- if (free_space < data_size + sizeof(struct btrfs_item)) {
+ if (free_space < data_size) {
free_extent_buffer(left);
return 1;
}
@@ -2557,7 +2557,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
if (!root->node)
BUG();
- total_size = total_data + (nr - 1) * sizeof(struct btrfs_item);
+ total_size = total_data + nr * sizeof(struct btrfs_item);
ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1);
if (ret == 0) {
return -EEXIST;
@@ -2571,8 +2571,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
nritems = btrfs_header_nritems(leaf);
data_end = leaf_data_end(root, leaf);
- if (btrfs_leaf_free_space(root, leaf) <
- sizeof(struct btrfs_item) + total_size) {
+ if (btrfs_leaf_free_space(root, leaf) < total_size) {
btrfs_print_leaf(root, leaf);
printk("not enough freespace need %u have %d\n",
total_size, btrfs_leaf_free_space(root, leaf));
diff --git a/disk-io.c b/disk-io.c
index 2b5771cb..addebe19 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -755,6 +755,8 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
BUG_ON(ret);
find_and_setup_log_root(tree_root, fs_info, disk_super);
+
+ fs_info->generation = generation + 1;
btrfs_read_block_groups(fs_info->tree_root);
key.objectid = BTRFS_FS_TREE_OBJECTID;
@@ -771,6 +773,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
{
+ u8 fsid[BTRFS_FSID_SIZE];
struct btrfs_super_block buf;
int i;
int ret;
@@ -802,6 +805,11 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
sizeof(buf.magic)))
continue;
+ if (i == 0)
+ memcpy(fsid, buf.fsid, sizeof(fsid));
+ else if (memcmp(fsid, buf.fsid, sizeof(fsid)))
+ continue;
+
if (btrfs_super_generation(&buf) > transid) {
memcpy(sb, &buf, sizeof(*sb));
transid = btrfs_super_generation(&buf);
diff --git a/extent-tree.c b/extent-tree.c
index bc2fd616..6bc1cc80 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -2071,8 +2071,8 @@ static int __free_extent(struct btrfs_trans_handle *trans,
struct btrfs_key key;
struct btrfs_path *path;
- struct btrfs_fs_info *info = root->fs_info;
- struct btrfs_root *extent_root = info->extent_root;
+ struct btrfs_extent_ops *ops = root->fs_info->extent_ops;
+ struct btrfs_root *extent_root = root->fs_info->extent_root;
struct extent_buffer *leaf;
struct btrfs_extent_item *ei;
struct btrfs_extent_inline_ref *iref;
@@ -2218,6 +2218,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
}
} else {
int mark_free = 0;
+ int pin = 1;
if (found_extent) {
BUG_ON(is_data && refs_to_drop !=
@@ -2231,10 +2232,21 @@ static int __free_extent(struct btrfs_trans_handle *trans,
}
}
- ret = pin_down_bytes(trans, root, bytenr, num_bytes, is_data);
- if (ret > 0)
- mark_free = 1;
- BUG_ON(ret < 0);
+ if (ops && ops->free_extent) {
+ ret = ops->free_extent(root, bytenr, num_bytes);
+ if (ret > 0) {
+ pin = 0;
+ mark_free = 0;
+ }
+ }
+
+ if (pin) {
+ ret = pin_down_bytes(trans, root, bytenr, num_bytes,
+ is_data);
+ if (ret > 0)
+ mark_free = 1;
+ BUG_ON(ret < 0);
+ }
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
num_to_del);