* InodeFile
* The inode may have a linkcount of 0 and if so, it should
* be truncated and removed
+ * The inode might have blocks beyond EOF in which case they
+ * should be truncated.
* Directory
- * An index block might not have been incorporated into the
- * index tree yet.
- * An index block might be under full and so need to be merged
- * with a neighbour
- * A leaf block may be completely empty and so should be
- * moved from the part-free list to the free-list
+ * An internal chain from this block might be being released...
+ * see dir.c for further details.
*
* Each entry in the orphan file is 16 bytes holding 4 u32s
* in little_endian.
bnum = (om->nextfree + om->reserved) >>
(fs->prime_sb->s_blocksize_bits-4);
- b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL, MKREF(orphan));
+ b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL,
+ MKREF(orphan_reserve));
if (b) {
err = lafs_read_block(b);
if (err) {
- putdref(b, MKREF(orphan));
+ putdref(b, MKREF(orphan_reserve));
oi->reserved = 0;
} else {
om->reserved++;
ob = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL, MKREF(orphan));
/* that *must* succeed as we own a reference on the block already */
BUG_ON(ob == NULL);
+
lafs_phase_wait(&ob->b);
oi->ob = ob;
atomic_inc(&ob->pincnt);
if (err) {
atomic_dec(&ob->pincnt);
mutex_unlock(&fs->orphans->i_mutex);
+ putdref(ob, MKREF(orphan));
+ oi->ob = NULL;
return err;
}
b->orphan_slot = slot;
oi->reserved = 0;
om->nextfree++;
om->reserved--;
+ putdref(ob, MKREF(orphan_reserve));
or = map_dblock(ob);
ent = slot - (bnum << (fs->prime_sb->s_blocksize_bits-4));
void lafs_orphan_commit(struct orphan_info *oi)
{
- /* All the interesting work was done in _lock.
+ /* All the interesting work was done in _pin.
* Just mark the block dirty and clean up
*/
/* If block was already an orphan, we didn't do any work in 'pin',
- * So there is nothing to do here
+ * So there is not much to do here
*/
if (oi->ob) {
BUG_ON(!test_bit(B_PinPending, &oi->ob->b.flags));
if (atomic_dec_and_test(&oi->ob->pincnt))
/* FIXME this is racy */
clear_bit(B_PinPending, &oi->ob->b.flags);
- putdref(oi->ob, MKREF(orphan));
+ /* We don't 'put' the reference. It is now held through
+ * the B_Orphan flag and the orphan_slot field.
+ */
+ oi->ob = NULL;
}
+ /* Otherwise we might still hold a reservation which
+ * we can drop by calling orphan_abort
+ */
+ lafs_orphan_abort(oi);
}
/* Note that we don't 'unmark' the block from being an orphan.
!= bnum)
lafs_erase_dblock(b);
- putdref(b, MKREF(orphan));
+ putdref(b, MKREF(orphan_reserve));
mutex_unlock(&fs->orphans->i_mutex);
}
+ /* FIXME maybe discard this altogether */
if (oi->ob) {
if (atomic_dec_and_test(&oi->ob->pincnt))
/* FIXME this is racy */
clear_bit(B_PinPending, &oi->ob->b.flags);
- putdref(oi->ob, MKREF(orphan));
+ //putdref(oi->ob, MKREF(orphan));
oi->ob = NULL;
}
}
return;
mutex_lock_nested(&fs->orphans->i_mutex, I_MUTEX_QUOTA);
+ if (!test_bit(B_Orphan, &b->b.flags)) {
+ mutex_unlock(&fs->orphans->i_mutex);
+ return;
+ }
ob1 = lafs_get_block(fs->orphans, b->orphan_slot >> shift, NULL,
- GFP_KERNEL, MKREF(orphan));
+ GFP_KERNEL, MKREF(orphan_release));
+ /* We already own an 'orphan' reference on this block, so we
+ * don't need this one
+ */
+ BUG_ON(ob1 == NULL);
+ putdref(ob1, MKREF(orphan_release));
lafs_phase_wait(&ob1->b);
/* need to swap in the last entry */
struct datablock *bfs, *bi, *bbl;
ob2 = lafs_get_block(fs->orphans, (om->nextfree-1) >> shift,
- NULL, GFP_KERNEL, MKREF(orphan));
+ NULL, GFP_KERNEL, MKREF(orphan_move));
if (!ob2) {
/* Oh dear, we cannot effect the swap - sad */
printk("OUCH 1\n");
goto ouch;
}
if (lafs_read_block(ob2) != 0) {
- putdref(ob2, MKREF(orphan));
+ putdref(ob2, MKREF(orphan_move));
printk("OUCH 2\n");
goto ouch;
}
/* FIXME these should not create the block if it
* doesn't exist */
bfs = lafs_get_block(fs->ss[0].root, le32_to_cpu(last.filesys),
- NULL, GFP_KERNEL, MKREF(orphan));
+ NULL, GFP_KERNEL, MKREF(orphan_fs));
if (bfs && bfs->my_inode)
bi = lafs_get_block(bfs->my_inode,
le32_to_cpu(last.inum),
- NULL, GFP_KERNEL, MKREF(orphan));
+ NULL, GFP_KERNEL, MKREF(orphan_ino));
else
bi = NULL;
- putdref(bfs, MKREF(orphan));
+ putdref(bfs, MKREF(orphan_fs));
if (bi && bi->my_inode)
bbl = lafs_get_block(bi->my_inode,
le32_to_cpu(last.addr),
- NULL, GFP_KERNEL, MKREF(orphan));
+ NULL, GFP_KERNEL, MKREF(orphan_blk));
else
bbl = NULL;
- putdref(bi, MKREF(orphan));
+ putdref(bi, MKREF(orphan_ino));
dprintk("O bfs=%p(%p) bi=%p bbl=%p lastent=%d "
"fs=%d in=%d a=%d\n",
bfs, bfs->my_inode, bi, bbl, lastent,
le32_to_cpu(last.addr)
);
if (!bbl) {
- putdref(ob2, MKREF(orphan));
+ putdref(ob2, MKREF(orphan_release2));
printk("OUCH 3\n");
BUG();
goto ouch;
or = map_dblock(ob1);
or[ent] = last;
bbl->orphan_slot = b->orphan_slot;
- putdref(bbl, MKREF(orphan));
+ putdref(bbl, MKREF(orphan_blk));
lafs_dirty_dblock(ob1);
lafs_dirty_dblock(ob2);
unmap_dblock(ob1, or);
- /* no longer hold a reservation reference
- * on this block, but do now on ob2
+ /* The orphan reference on ob2 has moved to ob1
+ * and ob2 is now a 'reservation' reference.
+ * So we drop ob2 and extra time, but not ob1 at all.
*/
- putdref(ob1, MKREF(orphan));
+ getdref(ob2, MKREF(orphan_reserve));
+ putdref(ob2, MKREF(orphan_move));
+ putdref(ob2, MKREF(orphan));
} else {
or = map_dblock(ob1);
or[ent].type = 0;
unmap_dblock(ob1, or);
lafs_dirty_dblock(ob1);
+ getdref(ob1, MKREF(orphan_reserve));
putdref(ob1, MKREF(orphan));
}
om->nextfree--;
/* Now drop the reservation we just synthesised */
om->reserved--;
bnum = (om->nextfree + om->reserved) >> (b->b.inode->i_blkbits-4);
- b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL, MKREF(orphan));
+ b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL,
+ MKREF(orphan_release3));
/* Note that we now own two references to this block, one
* we just got and one we are trying to get rid of
*/
- putdref(b, MKREF(orphan));
+ putdref(b, MKREF(orphan_release3));
/* If this was the last block in the file,
* we need to punch a hole
/* FIXME share code with orphan_abort */
lafs_erase_dblock(b);
- putdref(b, MKREF(orphan));
+ putdref(b, MKREF(orphan_reserve));
ouch: /* FIXME */
mutex_unlock(&fs->orphans->i_mutex);