int insert_result(struct results_tree *res, unsigned char *digest, struct filerec *recs[2], uint64_t startoff[2], uint64_t endoff[2]) { struct extent *e0 = alloc_extent(recs[0], startoff[0]); struct extent *e1 = alloc_extent(recs[1], startoff[1]); struct dupe_extents *dext; uint64_t len = endoff[0] - startoff[0]; int add_score = 1; if (!e0 || !e1) return ENOMEM; dext = find_dupe_extents(res, digest, len); if (!dext) { dext = dupe_extents_new(res, digest, len); if (!dext) return ENOMEM; add_score = 0; } abort_on(dext->de_len != len); insert_extent_list_free(dext, &e0); insert_extent_list_free(dext, &e1); if (e0) { if (add_score) dext->de_score += len; e0->e_itnode.start = e0->e_loff; e0->e_itnode.last = extent_end(e0); interval_tree_insert(&e0->e_itnode, &recs[0]->extent_tree); #ifdef ITDEBUG recs[0]->num_extents++; #endif } if (e1) { if (add_score) dext->de_score += len; e1->e_itnode.start = e1->e_loff; e1->e_itnode.last = extent_end(e1); interval_tree_insert(&e1->e_itnode, &recs[1]->extent_tree); #ifdef ITDEBUG recs[1]->num_extents++; #endif } return 0; }
/* Create the all-encompassing root extent for buffer TX. */ void make_global_extent(Lisp_Buffer *tx) { tx->global_extent = alloc_extent(0); tx->global_extent->tx = tx; reset_global_extent(tx); }
void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_rec) { char *cp; /* Parse first extent. */ if (dir_rec->data_length_l > 0) { assert(i->extent == NULL); i->extent = alloc_extent(); i->extent->location = dir_rec->loc_extent_l + dir_rec->ext_attr_rec_length; i->extent->length = dir_rec->data_length_l / v_pri.logical_block_size_l; if (dir_rec->data_length_l % v_pri.logical_block_size_l) i->extent->length++; i->i_stat.st_size = dir_rec->data_length_l; } /* Parse timestamps (record date). */ i->i_stat.st_atime = i->i_stat.st_mtime = i->i_stat.st_ctime = i->i_stat.st_birthtime = date7_to_time_t(dir_rec->rec_date); if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) { i->i_stat.st_mode = S_IFDIR; i->i_stat.st_ino = i->extent->location * v_pri.logical_block_size_l; } else i->i_stat.st_mode = S_IFREG; i->i_stat.st_mode |= 0555; /* Parse file name. */ if (dir_rec->file_id[0] == 0) strcpy(i->i_name, "."); else if (dir_rec->file_id[0] == 1) strcpy(i->i_name, ".."); else { memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id); /* Truncate/ignore file version suffix. */ cp = strchr(i->i_name, ';'); if (cp != NULL) *cp = '\0'; /* Truncate dot if file has no extension. */ if (strchr(i->i_name, '.') + 1 == cp) *(cp-1) = '\0'; } /* Initialize stat. */ i->i_stat.st_dev = fs_dev; i->i_stat.st_blksize = v_pri.logical_block_size_l; i->i_stat.st_blocks = dir_rec->data_length_l / v_pri.logical_block_size_l; i->i_stat.st_nlink = 1; }
int insert_result(struct results_tree *res, unsigned char *digest, struct filerec *recs[2], uint64_t startoff[2], uint64_t endoff[2]) { struct extent *e0 = alloc_extent(recs[0], startoff[0]); struct extent *e1 = alloc_extent(recs[1], startoff[1]); struct dupe_extents *dext; uint64_t len = endoff[0] - startoff[0]; int add_score = 1; if (!e0 || !e1) return ENOMEM; dext = find_dupe_extents(res, digest, len); if (!dext) { dext = dupe_extents_new(res, digest, len); if (!dext) return ENOMEM; add_score = 0; } abort_on(dext->de_len != len); insert_extent_list_free(dext, &e0); insert_extent_list_free(dext, &e1); if (e0) { if (add_score) dext->de_score += len; list_add_tail(&e0->e_file_extents, &recs[0]->extent_list); } if (e1) { if (add_score) dext->de_score += len; list_add_tail(&e1->e_file_extents, &recs[1]->extent_list); } return 0; }
/* * This does not do all the work of insert_result(), just enough for * the dedupe phase of block-dedupe to work properly. */ int insert_one_result(struct results_tree *res, unsigned char *digest, struct filerec *file, uint64_t startoff, uint64_t len) { struct extent *extent = alloc_extent(file, startoff); struct dupe_extents *dext; if (!extent) return ENOMEM; dext = find_dupe_extents(res, digest, len); if (!dext) { dext = dupe_extents_new(res, digest, len); if (!dext) return ENOMEM; } abort_on(dext->de_len != len); insert_extent_list_free(dext, &extent); return 0; }
struct inode* get_inode(ino_t i) { struct inode *i_node; struct dir_extent *extent; if (i == 0) return NULL; /* Try to get inode from cache. */ i_node = find_inode(i); if (i_node != NULL) { dup_inode(i_node); return i_node; } /* * Inode wasn't in cache, try to load it. * FIXME: a fake extent of one logical block is created for * read_inode(). Reading a inode this way could be problematic if * additional extents are stored behind the block boundary. */ i_node = alloc_inode(); extent = alloc_extent(); extent->location = i / v_pri.logical_block_size_l; extent->length = 1; if (read_inode(i_node, extent, i % v_pri.logical_block_size_l, NULL) != OK) { free_extent(extent); put_inode(i_node); return NULL; } free_extent(extent); return i_node; }
/* * helper function to allocate a block for a given tree * returns the tree buffer or NULL. */ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, struct btrfs_root *root) { struct btrfs_key ins; int ret; struct btrfs_buffer *buf; ret = alloc_extent(trans, root, root->root_key.objectid, 1, 0, (unsigned long)-1, &ins); if (ret) { BUG(); return NULL; } ret = update_block_group(trans, root, ins.objectid, ins.offset, 1); buf = find_tree_block(root, ins.objectid); btrfs_set_header_generation(&buf->node.header, root->root_key.offset + 1); btrfs_set_header_blocknr(&buf->node.header, buf->blocknr); memcpy(buf->node.header.fsid, root->fs_info->disk_super->fsid, sizeof(buf->node.header.fsid)); dirty_tree_block(trans, root, buf); return buf; }
/* Insert extent E into the tree rooted at extent ROOT. The row-positions in E are assumed to be relative to the row-position of ROOT. */ static void insert_extent(Lisp_Extent *e, Lisp_Extent *root) { Lisp_Extent *x; top: x = root->first_child; while(x != 0) { if(PPOS_LESS_EQUAL_P(&e->end, &x->start)) { /* Insert E before X */ e->parent = root; e->left_sibling = x->left_sibling; if(e->left_sibling != 0) e->left_sibling->right_sibling = e; x->left_sibling = e; e->right_sibling = x; if(root->first_child == x) root->first_child = e; assert_invariants (e); assert_invariants (x); return; } else if(PPOS_LESS_P(&e->start, &x->start)) { /* X overlaps E. The end of E clashes with the start of X. Break E into two fragments, insert the first before X, the second within X. */ Lisp_Extent *frag = alloc_extent(e); frag->end = x->start; e->start = x->start; frag->car |= EXTFF_OPEN_END; frag->frag_pred = e->frag_pred; if(e->frag_pred != 0) e->frag_pred->frag_next = frag; frag->frag_next = e; e->frag_pred = frag; assert_invariants (e); assert_invariants (x); assert_invariants (frag); insert_extent(frag, x->parent); assert_invariants (e); assert_invariants (x); assert_invariants (frag); continue; } else if(PPOS_LESS_P(&e->start, &x->end)) { /* E starts before X ends. */ if(PPOS_LESS_EQUAL_P(&e->end, &x->end)) { /* But E ends before X ends. So insert E in X. */ e->start.row -= x->start.row; e->end.row -= x->start.row; root = x; goto top; } else { /* E ends after X ends. So break E into two frags. */ Lisp_Extent *frag = alloc_extent(e); frag->start = x->end; e->end = x->end; frag->car |= EXTFF_OPEN_START; frag->frag_next = e->frag_next; if(e->frag_next != 0) e->frag_next->frag_pred = frag; frag->frag_pred = e; e->frag_next = frag; e->start.row -= x->start.row; e->end.row -= x->start.row; assert_invariants (e); assert_invariants (x); assert_invariants (frag); insert_extent(e, x); assert_invariants (e); assert_invariants (x); assert_invariants (frag); e = frag; continue; } } else { /* X ends before E starts, keep going.. */ } x = x->right_sibling; } /* Insert e at the end of the root. */ e->parent = root; e->left_sibling = root->last_child; if(root->last_child != 0) root->last_child->right_sibling = e; root->last_child = e; if(root->first_child == 0) root->first_child = e; assert_invariants (e); assert_invariants (root); }
void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec, struct dir_extent *extent, size_t *offset) { struct buf *bp; struct iso9660_dir_record *extent_rec; struct dir_extent *cur_extent = i->extent; int done = FALSE; /* * No need to search extents if file is empty or has final directory * record flag set. */ if (cur_extent == NULL || ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)) return; while (!done) { bp = fetch_inode(extent, offset); if (bp == NULL) return; bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l); extent_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % v_pri.logical_block_size_l); if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l) != OK) { lmfs_put_block(bp, FULL_DATA_BLOCK); return; } /* Extent entries should share the same name. */ if ((dir_rec->length_file_id == extent_rec->length_file_id) && (memcmp(dir_rec->file_id, extent_rec->file_id, dir_rec->length_file_id) == 0)) { /* Add the extent at the end of the linked list. */ assert(cur_extent->next == NULL); cur_extent->next = alloc_extent(); cur_extent->next->location = dir_rec->loc_extent_l + dir_rec->ext_attr_rec_length; cur_extent->next->length = dir_rec->data_length_l / v_pri.logical_block_size_l; if (dir_rec->data_length_l % v_pri.logical_block_size_l) cur_extent->next->length++; i->i_stat.st_size += dir_rec->data_length_l; i->i_stat.st_blocks += cur_extent->next->length; cur_extent = cur_extent->next; *offset += extent_rec->length; } else done = TRUE; /* Check if not last extent bit is not set. */ if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0) done = TRUE; lmfs_put_block(bp, FULL_DATA_BLOCK); } }