void lafs_incorporate(struct fs *fs, struct indexblock *ib)
{
int offset; /* start of block where indexing is */
- struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt;
+ struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt, *prv;
struct block *uninc = NULL, **bp;
int rv = 0;
u32 next;
nxt = NULL;
if (ib->b.siblings.next != &ib->b.parent->children)
nxt = list_entry(ib->b.siblings.next, struct indexblock, b.siblings);
+ prv = NULL;
+ if (ib->b.siblings.prev != &ib->b.parent->children)
+ prv = list_entry(ib->b.siblings.prev, struct indexblock, b.siblings);
+ /* we don't need to move to the inode->free_index list as that will
+ * happen when refile drops the ->parent link.
+ * If we completely remove from the list, refile will get confused in
+ * consistency checks. So just move to the end of the list
+ * to avoid confusing PrimaryRef chains.
+ */
+ list_move_tail(&ib->b.siblings, &ib->b.parent->children);
lafs_unhash_iblock(ib);
if (test_and_clear_bit(B_PrimaryRef, &ib->b.flags)) {
- int cr = 0;
/* This was not incorporated yet, revert the uninc status */
if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
/* I was in a PrimaryRef chain */
putiref(ib, MKREF(primary));
} else {
- struct indexblock *prev = list_entry(ib->b.siblings.prev,
- struct indexblock,
- b.siblings);
- putiref(prev, MKREF(primary));
+ LAFS_BUG(!prv, &ib->b);
+ putiref(prv, MKREF(primary));
}
- list_del_init(&ib->b.siblings);
- clear_bit(B_Uninc, &ib->b.flags);
- if (test_and_clear_bit(B_Dirty, &ib->b.flags))
- cr++;
- if (test_and_clear_bit(B_UnincCredit, &ib->b.flags))
- cr++;
- lafs_space_return(fs, cr);
} else if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
/* Next block is not incorporated yet, so simply re-address
* it to replace this block.
*/
+ clear_bit(B_PrimaryRef, &nxt->b.flags);
+ putiref(ib, MKREF(primary));
readdress_index(ib->b.inode, nxt->b.fileaddr, nxt->depth,
ib->b.fileaddr);
if (test_bit(B_PhysValid, &nxt->b.flags)) {
LAFS_BUG(nxt->b.physaddr == 0, &nxt->b);
update_index(ib->b.parent, ib->b.fileaddr, nxt->b.physaddr);
}
- clear_bit(B_PrimaryRef, &nxt->b.flags);
- putiref(ib, MKREF(primary));
} else if ((next = update_index(ib->b.parent, ib->b.fileaddr, 0)) != 0) {
/* Found a 'next' block in the parent and have updated the parent.
* Need to check for block in cache and re-address