/* * Chop inums * return value: * < 0 - error * 1 - modified * 0 - not modified */ static int ileaf_chop(struct btree *btree, tuxkey_t start, u64 len, void *leaf) { struct ileaf *ileaf = leaf; __be16 *dict = ileaf_dict(btree, leaf); tuxkey_t base = ibase(ileaf); unsigned count = icount(ileaf); tuxkey_t at = start - base; void *startp, *endp, *tailp; unsigned size; if (at + 1 > count) return 0; len = min_t(u64, len, count - at); startp = ileaf->table + atdict(dict, at); endp = ileaf->table + atdict(dict, at + len); if (startp == endp) return 0; /* Remove data */ tailp = ileaf->table + atdict(dict, count); memmove(startp, endp, tailp - endp); /* Adjust dict */ size = endp - startp; while (at < count) { at++; add_idict(dict - at, -size); } ileaf_trim(btree, leaf); return 1; }
static tuxkey_t ileaf_split(struct btree *btree, tuxkey_t hint, void *from, void *into) { assert(ileaf_sniff(btree, from)); struct ileaf *leaf = from, *dest = into; __be16 *dict = ileaf_dict(btree, from); __be16 *destdict = ileaf_dict(btree, into); #ifdef SPLIT_AT_INUM /* * This is to prevent to have same ibase on both of from and into * FIXME: we would want to split at better position. */ if (hint == ibase(leaf)) hint++; trace("split at inum 0x%Lx", hint); unsigned at = min_t(tuxkey_t, hint - ibase(leaf), icount(leaf)); #else /* binsearch inum starting nearest middle of block */ unsigned at = 1, hi = icount(leaf); while (at < hi) { int mid = (at + hi) / 2; if (*(dict - mid) < (btree->sb->blocksize / 2)) at = mid + 1; else hi = mid; } #endif /* should trim leading empty inodes on copy */ unsigned split = atdict(dict, at), free = atdict(dict, icount(leaf)); trace("split at %x of %x", at, icount(leaf)); trace("copy out %x bytes at %x", free - split, split); assert(free >= split); memcpy(dest->table, leaf->table + split, free - split); dest->count = cpu_to_be16(icount(leaf) - at); veccopy(destdict - icount(dest), dict - icount(leaf), icount(dest)); for (int i = 1; i <= icount(dest); i++) add_idict(destdict - i, -split); #ifdef SPLIT_AT_INUM /* round down to multiple of 64 above ibase */ inum_t round = hint & ~(inum_t)(btree->entries_per_leaf - 1); dest->ibase = cpu_to_be64(round > ibase(leaf) + icount(leaf) ? round : hint); #else dest->ibase = cpu_to_be64(ibase(leaf) + at); #endif leaf->count = cpu_to_be16(at); memset(leaf->table + split, 0, (char *)(dict - icount(leaf)) - (leaf->table + split)); ileaf_trim(btree, leaf); return ibase(dest); }
int ileaf_purge(struct btree *btree, inum_t inum, struct ileaf *leaf) { if (inum < ibase(leaf) || inum - ibase(leaf) >= btree->entries_per_leaf) return -EINVAL; be_u16 *dict = (void *)leaf + btree->sb->blocksize; unsigned at = inum - ibase(leaf); unsigned offset = atdict(dict, at); unsigned size = from_be_u16(*(dict - at - 1)) - offset; printf("delete inode %Lx from %p[%x/%x]\n", (L)inum, leaf, at, size); if (!size) return -ENOENT; unsigned free = from_be_u16(*(dict - icount(leaf))), tail = free - offset - size; assert(offset + size + tail <= free); memmove(leaf->table + offset, leaf->table + offset + size, tail); for (int i = at + 1; i <= icount(leaf); i++) add_idict(dict - i, -size); ileaf_trim(btree, leaf); return 0; }
static tuxkey_t ileaf_split(struct btree *btree, tuxkey_t inum, vleaf *from, vleaf *into) { assert(ileaf_sniff(btree, from)); struct ileaf *leaf = from, *dest = into; be_u16 *dict = from + btree->sb->blocksize, *destdict = into + btree->sb->blocksize; #ifdef SPLIT_AT_INUM printf("split at inum 0x%Lx\n", (L)inum); assert(inum >= ibase(leaf)); unsigned at = inum - ibase(leaf) < icount(leaf) ? inum - ibase(leaf) : icount(leaf); #else /* binsearch inum starting nearest middle of block */ unsigned at = 1, hi = icount(leaf); while (at < hi) { int mid = (at + hi) / 2; if (*(dict - mid) < (btree->sb->blocksize / 2)) at = mid + 1; else hi = mid; } #endif /* should trim leading empty inodes on copy */ unsigned split = atdict(dict, at), free = from_be_u16(*(dict - icount(leaf))); printf("split at %x of %x\n", at, icount(leaf)); printf("copy out %x bytes at %x\n", free - split, split); assert(free >= split); memcpy(dest->table, leaf->table + split, free - split); dest->count = to_be_u16(icount(leaf) - at); veccopy(destdict - icount(dest), dict - icount(leaf), icount(dest)); for (int i = 1; i <= icount(dest); i++) add_idict(destdict - i, -split); #ifdef SPLIT_AT_INUM /* round down to multiple of 64 above ibase */ inum_t round = inum & ~(inum_t)(btree->entries_per_leaf - 1); dest->ibase = to_be_u64(round > ibase(leaf) + icount(leaf) ? round : inum); #else dest->ibase = to_be_u64(ibase(leaf) + at); #endif leaf->count = to_be_u16(at); memset(leaf->table + split, 0, (char *)(dict - icount(leaf)) - (leaf->table + split)); ileaf_trim(btree, leaf); return ibase(dest); }