} else
blk = getref(&b->b, MKREF(pindb));
+ LAFS_BUG(!test_bit(B_PinPending, &b->b.flags), &b->b);
if (LAFSI(b->b.inode)->type != TypeSegmentMap) {
- /* FIXME test is a hack until we get a better
- * phase wait. TypeSegmentMap does it's own
- * dirty management so doesn't need this.
- */
LAFS_BUG(!test_phase_locked(fs), &b->b);
- lafs_phase_wait(blk);
+ lafs_iolock_written(&b->b);
+ lafs_iounlock_block(&b->b);
}
- set_bit(B_PinPending, &b->b.flags);
err = lafs_reserve_block(blk, alloc_type);
if (err) {
- clear_bit(B_PinPending, &b->b.flags);
putref(blk, MKREF(pindb));
return err;
}
b2->parent =
getiref(b->parent, MKREF(child));
LAFS_BUG(b->parent != b2->parent, b);
- set_bit(B_PinPending, &b2->flags);
+ set_bit(B_PinPending, &b2->flags); // FIXME is this right?
set_phase(b2, test_bit(B_Phase1,
&b->flags));
lafs_refile(b2, 0);
if (!test_and_clear_bit(B_ICredit, &b2->flags))
credits--;
}
- clear_bit(B_PinPending, &b2->flags);
+ clear_bit(B_PinPending, &b2->flags); // FIXME not sure this is right
LAFS_BUG(credits < 0, b2);
lafs_space_return(fs, credits);
/* make sure 'dirty' status is registered */
memcpy(buf, n1, blocksize);
unmap_dblock(doh->new, buf);
set_bit(B_Valid, &doh->new->b.flags);
+ set_bit(B_PinPending, &doh->new->b.flags);
kfree(n1);
doh->temp = n2;
return 0;
err = lafs_make_orphan(fs, inodb);
if (err)
goto abort;
+ lafs_iolock_block(&inodb->b);
+ set_bit(B_PinPending, &inodb->b.flags);
+ lafs_iounlock_block(&inodb->b);
retry:
lafs_checkpoint_lock(fs);
err = lafs_make_orphan(fs, inodb);
if (err)
goto abort;
+ lafs_iolock_block(&inodb->b);
+ set_bit(B_PinPending, &inodb->b.flags);
+ lafs_iounlock_block(&inodb->b);
retry:
lafs_checkpoint_lock(fs);
iput(ino);
return -ENOMEM;
}
+ set_bit(B_PinPending, &b->b.flags);
err = dir_create_prepare(fs, dir, de->d_name.name, de->d_name.len,
ino->i_ino, DT_LNK, &doh);
err = PTR_ERR(newdb);
if (last && !err)
err = lafs_make_orphan(fs, newdb);
+ lafs_iolock_block(&newdb->b);
+ set_bit(B_PinPending, &newdb->b.flags);
+ lafs_iounlock_block(&newdb->b);
} else
/* create new link */
err = dir_create_prepare(fs, new_dir,
if (err)
goto abort;
+ lafs_iolock_block(&olddb->b);
+ set_bit(B_PinPending, &olddb->b.flags);
+ lafs_iounlock_block(&olddb->b);
retry:
lafs_checkpoint_lock(fs);
dprintk("HANDLE ORPHAN h=%x %s\n", (unsigned)hash, strblk(&b->b));
+ if (!lafs_iolock_written_async(&b->b))
+ return -EAGAIN;
+ set_bit(B_PinPending, &b->b.flags);
+ lafs_iounlock_block(&b->b);
+
lafs_checkpoint_lock(fs);
if (!test_bit(B_Valid, &b->b.flags)) {
NULL)->target == 0);
unmap_dblock(b, buf);
lafs_dirty_dblock(b);
- clear_bit(B_PinPending, &b->b.flags);
} else
unmap_dblock(b2, buf2);
buf = map_dblock(b);
buf = map_dblock(b);
lafs_dir_del_ent(buf, bits, seed, hash);
lafs_dirty_dblock(b);
- clear_bit(B_PinPending, &b->b.flags);
}
if (lafs_dir_empty(buf)) {
lafs_dirty_inode(dir);
}
lafs_erase_dblock(b);
- clear_bit(B_PinPending, &b->b.flags);
} else
unmap_dblock(b, buf);
err = 0;
abort:
+ clear_bit(B_PinPending, &b->b.flags);
putdref(b2, MKREF(dir_orphan));
lafs_checkpoint_unlock(fs);
return err;
return -EINVAL;
goto retry;
}
+ lafs_iolock_written(&imni->mb->b);
+ set_bit(B_PinPending, &imni->mb->b.flags);
+ lafs_iounlock_block(&imni->mb->b);
+ set_bit(B_PinPending, &b->b.flags);
b->my_inode = NULL;
imni->ib = b;
return 0;
lafs_erase_dblock(imni->mb);
else
lafs_dirty_dblock(imni->mb);
- clear_bit(B_PinPending, &imni->ib->b.flags);
putdref(imni->ib, MKREF(cfi_ino));
putdref(imni->mb, MKREF(cfi_map));
}
} else
lafs_cluster_update_commit(&ui, b, 0,
LAFSI(ino)->metadata_size);
- clear_bit(B_PinPending, &b->b.flags);
LAFS_BUG(LAFSI(ino)->dblock != b, &b->b);
LAFS_BUG(b->my_inode != ino, &b->b);
lafs_checkpoint_unlock(fs);
putdref(b, MKREF(inode_map_free));
return err;
}
+ lafs_iolock_written(&b->b);
+ set_bit(B_PinPending, &b->b.flags);
+ lafs_iounlock_block(&b->b);
retry:
lafs_checkpoint_lock(fs);
err = lafs_pin_dblock(b, ReleaseSpace);
if (err)
return err;
+ /* We don't need iolock_written here as we don't
+ * actually change the inode block yet
+ */
+ lafs_iolock_block(&db->b);
+ set_bit(B_PinPending, &db->b.flags);
+ lafs_iounlock_block(&db->b);
+
/* FIXME quota stuff */
again:
void _lafs_iolock_written(struct block *b)
{
- lafs_iolock_block(b);
+ _lafs_iolock_block(b);
wait_writeback(b);
}
void lafs_checkpoint_lock(struct fs *fs);
void lafs_checkpoint_unlock(struct fs *fs);
void lafs_checkpoint_unlock_wait(struct fs *fs);
-void lafs_phase_wait(struct block *b);
unsigned long long lafs_checkpoint_start(struct fs *fs);
unsigned long lafs_do_checkpoint(struct fs *fs);
struct block *lafs_get_flushable(struct fs *fs, int phase);
return -ENOSPC;
}
-
-/* If a datablock is dirty and pinned to the previous phase,
- * we may not change it in this phase. So we have to wait
- * at least until it is written. We actually wait until the
- * phase passes
- * The same applies to InoIdx blocks.
- * FIXME should I encourage this with a cluster_flush ??
- */
-void lafs_phase_wait(struct block *b)
-{
- struct fs *fs = fs_from_inode(b->inode);
-
- wait_event(fs->phase_wait,
- !test_bit(B_Pinned, &b->flags) ||
- (!!test_bit(B_Phase1, &b->flags)) == fs->phase);
-}
} else
err = -ENOMEM;
mutex_unlock(&fs->orphans->i_mutex);
+ lafs_iolock_written(&b->b);
+ set_bit(B_PinPending, &b->b.flags);
+ lafs_iounlock_block(&b->b);
return err;
}
or[ent].addr = cpu_to_le32(b->b.fileaddr);
unmap_dblock(ob, or);
lafs_dirty_dblock(ob);
- clear_bit(B_PinPending, &ob->b.flags);
}
/* We failed to allocate space to write the update to the orphan
LAFS_BUG(ob1 == NULL, &b->b);
putdref(ob1, MKREF(orphan_release));
+ BUG_ON(!test_bit(B_PinPending, &ob1->b.flags));
+
lafs_checkpoint_lock(fs);
if (lafs_pin_dblock(ob1, ReleaseSpace) < 0)
printk("OUCH 2\n");
goto out_unlock;
}
+ BUG_ON(!test_bit(B_PinPending, &ob2->b.flags));
if (lafs_pin_dblock(ob2, ReleaseSpace) < 0) {
putdref(ob2, MKREF(orphan_move));
goto out_unlock;
putdref(bbl, MKREF(orphan_blk));
lafs_dirty_dblock(ob1);
lafs_dirty_dblock(ob2);
- clear_bit(B_PinPending, &ob1->b.flags);
- clear_bit(B_PinPending, &ob2->b.flags);
/* The orphan reference on ob2 has moved to ob1
* and ob2 is now a 'reservation' reference.
or[ent].type = 0;
unmap_dblock(ob1, or);
lafs_dirty_dblock(ob1);
- clear_bit(B_PinPending, &ob1->b.flags);
getdref(ob1, MKREF(orphan_reserve));
putdref(ob1, MKREF(orphan));
}
* Is this really the best approach?
* Do I need to release some space here?
*/
+ set_bit(B_PinPending, &blk->b.flags); /* Don't need iolock as no io yet */
lafs_pin_dblock(blk, CleanSpace); /* cannot fail during ! ->rolled */
lafs_iolock_block(&blk->b);
continue;
}
+ /* Don't need iolock here as segusage is very special */
+ set_bit(B_PinPending, &ss->ssblk->b.flags);
err = lafs_pin_dblock(ss->ssblk, AccountSpace);
if (err) {
ss_put(ss, fs);
* to the two blocks !! */
LAFS_BUG(1, db ? &db->b : NULL);
lafs_checkpoint_lock(fs);
+ set_bit(B_PinPending, &ssum->ssblk->b.flags);
(void)lafs_pin_dblock(ssum->ssblk, AccountSpace);
- if (ssnum == 0)
+ if (ssnum == 0) {
+ set_bit(B_PinPending, &ssum->youthblk->b.flags);
(void)lafs_pin_dblock(ssum->youthblk, AccountSpace);
+ }
lafs_checkpoint_unlock(fs);
}
if (db) {