Example #1
0
static void *ileaf_resize(struct btree *btree, tuxkey_t inum, vleaf *base, unsigned newsize)
{
	assert(ileaf_sniff(btree, base));
	struct ileaf *leaf = base;
	assert(inum >= ibase(leaf));
	be_u16 *dict = base + btree->sb->blocksize;

	unsigned at = inum - ibase(leaf);
	if (at >= btree->entries_per_leaf)
		return NULL;

	unsigned extend_empty = at < icount(leaf) ? 0 : at - icount(leaf) + 1;
	unsigned offset = at && icount(leaf) ? from_be_u16(*(dict - (at < icount(leaf) ? at : icount(leaf)))) : 0;
	unsigned size = at < icount(leaf) ? from_be_u16(*(dict - at - 1)) - offset : 0;
	int more = newsize - size;
	if (more > 0 && sizeof(*dict) * extend_empty + more > ileaf_free(btree, leaf))
		return NULL;
	for (; extend_empty--; leaf->count = to_be_u16(from_be_u16(leaf->count) + 1))
		*(dict - icount(leaf) - 1) = to_be_u16(atdict(dict, icount(leaf)));
	assert(icount(leaf));
	unsigned itop = from_be_u16(*(dict - icount(leaf)));
	void *attrs = leaf->table + offset;
	printf("resize inum 0x%Lx at 0x%x from %x to %x\n", (L)inum, offset, size, newsize);

	assert(itop >= offset + size);
	memmove(attrs + newsize, attrs + size, itop - offset - size);
	for (int i = at + 1; i <= icount(leaf); i++)
		add_idict(dict - i, more);
	return attrs;
}
Example #2
0
File: ileaf.c Project: Zkin/tux3
static int ileaf_merge(struct btree *btree, void *vinto, void *vfrom)
{
	struct ileaf *into = vinto, *from = vfrom;
	unsigned fromcount = icount(from);

	/* If "from" is empty, does nothing */
	if (!fromcount)
		return 1;

	assert(ibase(from) > ibase(into));
	tuxkey_t fromibase = ibase(from);
	unsigned count = icount(into);
	int hole = fromibase - ibase(into) + count;

	__be16 *dict = ileaf_dict(btree, into);
	__be16 *fromdict = ileaf_dict(btree, from);
	int need_size = hole * sizeof(*dict) + ileaf_need(btree, from);

	if (ileaf_free(btree, into) < need_size)
		return 0;

	/* Fill hole of dict until from_ibase */
	unsigned limit = atdict(dict, count);
	__be16 __limit = cpu_to_be16(limit);
	while (hole--) {
		count++;
		*(dict - count) = __limit;
	}

	/* Copy data from "from" */
	unsigned fromlimit = atdict(fromdict, fromcount);
	memcpy(into->table + limit, from->table, fromlimit);

	/* Adjust copying fromdict */
	if (limit) {
		int i;
		for (i = 1; i <= fromcount; i++)
			add_idict(dict - i, limit);
	}
	veccopy(dict - count - fromcount, fromdict - fromcount, fromcount);

	into->count = cpu_to_be16(count + fromcount);

	return 1;
}
Example #3
0
File: ileaf.c Project: Zkin/tux3
static void ileaf_dump(struct btree *btree, void *vleaf)
{
	if (!tux3_trace)
		return;

	struct ileaf_attr_ops *attr_ops = btree->ops->private_ops;
	struct ileaf *leaf = vleaf;
	inum_t inum = ibase(leaf);
	__be16 *dict = ileaf_dict(btree, leaf);
	unsigned offset = 0;

	trace_on("inode table block 0x%Lx/%i (%x bytes free)",
		 ibase(leaf), icount(leaf), ileaf_free(btree, leaf));

	for (int i = 0; i < icount(leaf); i++, inum++) {
		int limit = __atdict(dict, i + 1), size = limit - offset;
		if (!size)
			continue;
		if (size < 0)
			trace_on("  0x%Lx: <corrupt>\n", inum);
		else if (!size)
			trace_on("  0x%Lx: <empty>\n", inum);
		else if (attr_ops == &iattr_ops) {
			/* FIXME: this doesn't work in kernel */
			struct tux3_inode tuxnode = {};
			struct inode *inode = &tuxnode.vfs_inode;
			void *attrs = leaf->table + offset;

			inode->i_sb = vfs_sb(btree->sb),
			attr_ops->decode(btree, inode, attrs, size);

			free_xcache(inode);
		}
		offset = limit;
	}
}
Example #4
0
File: ileaf.c Project: Zkin/tux3
static void *ileaf_resize(struct btree *btree, tuxkey_t inum, void *vleaf,
			  int newsize)
{
	struct ileaf *ileaf = vleaf;
	__be16 *dict = ileaf_dict(btree, ileaf);
	unsigned count = icount(ileaf);
	tuxkey_t at = inum - ibase(ileaf);
	int extend_dict, offset, size;

	assert(inum >= ibase(ileaf));

	/* Get existent attributes, and calculate expand/shrink size */
	if (at + 1 > count) {
		/* Check size roughly to avoid overflow int */
		if ((at + 1) * sizeof(*dict) >= btree->sb->blocksize)
			goto overflow;

		/* Need to extend dict */
		extend_dict = (at + 1 - count) * sizeof(*dict);
		offset = atdict(dict, count);
		size = 0;
	} else {
		/* "at" is in dict, so get attr size */
		extend_dict = 0;
		offset = atdict(dict, at);
		size = __atdict(dict, at + 1) - offset;
	}

	if (ileaf_free(btree, ileaf) < newsize - size + extend_dict) {
overflow:
		return NULL;
	}

	/* Extend dict */
	if (extend_dict) {
		__be16 limit = cpu_to_be16(atdict(dict, count));
		while (count < at + 1) {
			count++;
			*(dict - count) = limit;
		}
		ileaf->count = cpu_to_be16(count);
	}

	void *attrs = ileaf->table + offset;
	if (newsize != size) {
		/* Expand/Shrink attr space */
		unsigned limit = __atdict(dict, count);
		assert(limit >= offset + size);
		memmove(attrs + newsize, attrs + size, limit - offset - size);

		/* Adjust dict */
		int diff = newsize - size;
		at++;
		while (at <= count) {
			add_idict(dict - at, diff);
			at++;
		}
	}

	return attrs;
}
Example #5
0
static void ileaf_dump(struct btree *btree, vleaf *vleaf)
{
	struct sb *sb = btree->sb;
	struct ileaf *leaf = vleaf;
	inum_t inum = ibase(leaf);
	be_u16 *dict = vleaf + sb->blocksize;
	unsigned offset = 0;
	printf("inode table block 0x%Lx/%i (%x bytes free)\n", (L)ibase(leaf), icount(leaf), ileaf_free(btree, leaf));
	//hexdump(dict - icount(leaf), icount(leaf) * 2);
	for (int i = -1; -i <= icount(leaf); i--, inum++) {
		int limit = from_be_u16(dict[i]), size = limit - offset;
		if (!size)
			continue;
		printf("  0x%Lx: ", (L)inum);
		//printf("[%x] ", offset);
		if (size < 0)
			printf("<corrupt>\n");
		else if (!size)
			printf("<empty>\n");
		else {
			/* FIXME: this doesn't work in kernel */
			struct inode inode = { .i_sb = vfs_sb(btree->sb) };
			unsigned xsize = decode_xsize(&inode, leaf->table + offset, size);
			tux_inode(&inode)->xcache = xsize ? new_xcache(xsize) : NULL;
			decode_attrs(&inode, leaf->table + offset, size);
			dump_attrs(&inode);
			xcache_dump(&inode);
			free(tux_inode(&inode)->xcache);
		}
		offset = limit;
	}
}

void *ileaf_lookup(struct btree *btree, inum_t inum, struct ileaf *leaf, unsigned *result)
{
	assert(inum >= ibase(leaf));
	assert(inum < ibase(leaf) + btree->entries_per_leaf);
	unsigned at = inum - ibase(leaf), size = 0;
	void *attrs = NULL;
	printf("lookup inode 0x%Lx, %Lx + %x\n", (L)inum, (L)ibase(leaf), at);
	if (at < icount(leaf)) {
		be_u16 *dict = (void *)leaf + btree->sb->blocksize;
		unsigned offset = atdict(dict, at);
		if ((size = from_be_u16(*(dict - at - 1)) - offset))
			attrs = leaf->table + offset;
	}
	*result = size;
	return attrs;
}