struct block *lafs_get_flushable(struct fs *fs, int phase);
int lafs_make_orphan(struct fs *fs, struct datablock *db);
+int lafs_make_orphan_nb(struct fs *fs, struct datablock *db);
void lafs_orphan_release(struct fs *fs, struct datablock *b);
unsigned long lafs_run_orphans(struct fs *fs);
* store the orphan record, and make sure we hold a reference
* to the block.
*/
-static int orphan_prepare(struct fs *fs)
+static int orphan_prepare(struct fs *fs, int async)
{
struct orphan_md *om = &LAFSI(fs->orphans)->md.orphan;
u32 bnum;
b = lafs_get_block(fs->orphans, bnum, NULL, GFP_KERNEL,
MKREF(orphan_reserve));
if (b) {
- err = lafs_read_block(b);
+ if (async)
+ err = lafs_read_block_async(b);
+ else
+ err = lafs_read_block(b);
if (err)
putdref(b, MKREF(orphan_reserve));
else
if (test_bit(B_Orphan, &db->b.flags))
return 0;
- err = orphan_prepare(fs);
+ err = orphan_prepare(fs, 0);
if (err)
return err;
retry:
return err;
}
+/* non-blocking version of make_orphan */
+int lafs_make_orphan_nb(struct fs *fs, struct datablock *db)
+{
+ int err;
+ struct datablock *ob;
+
+ if (test_bit(B_Orphan, &db->b.flags))
+ return 0;
+
+ err = orphan_prepare(fs, 1);
+ if (err)
+ return err;
+
+ lafs_checkpoint_lock(fs);
+ if (!mutex_trylock(&fs->orphans->i_mutex)) {
+ lafs_checkpoint_unlock(fs);
+ return -EAGAIN;
+ }
+ ob = orphan_pin(fs, db);
+ if (IS_ERR(ob)) {
+ orphan_abort(fs);
+ err = PTR_ERR(ob);
+ } else
+ orphan_commit(fs, db, ob);
+ mutex_unlock(&fs->orphans->i_mutex);
+ lafs_checkpoint_unlock(fs);
+ return err;
+}
+
/*
* When any processing of an orphan makes it not an orphan any more
* (e.g. link is created for a file, directory block is cleaned)