Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
0
/*
 * 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;

}
Exemplo n.º 8
0
/* 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);
}
Exemplo n.º 9
0
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);
	}
}