]> git.neil.brown.name Git - LaFS.git/commitdiff
lafs_make_orphan_nb - non-blocking version.
authorNeilBrown <neilb@suse.de>
Thu, 27 Aug 2009 01:51:03 +0000 (11:51 +1000)
committerNeilBrown <neilb@suse.de>
Thu, 27 Aug 2009 01:51:03 +0000 (11:51 +1000)
We will need to in the 'dir' orphan handler which itself
needs to be non-blocking.

lafs.h
orphan.c

diff --git a/lafs.h b/lafs.h
index efbf1681c8d5f5b3bb2aadfb859118ad41b38ae6..e943073aa584e9cbd95374673b4e78ec86c3c9e3 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -580,6 +580,7 @@ unsigned long lafs_do_checkpoint(struct fs *fs);
 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);
 
index 21c258564dd3190b028f6aafbf6eb69430e3f4ee..ae4a5e52a43aa0dc2e093b78ba39089b220db74c 100644 (file)
--- a/orphan.c
+++ b/orphan.c
@@ -100,7 +100,7 @@ void lafs_dump_orphans(void)
  * 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;
@@ -117,7 +117,10 @@ static int orphan_prepare(struct fs *fs)
        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
@@ -235,7 +238,7 @@ int lafs_make_orphan(struct fs *fs, struct datablock *db)
        if (test_bit(B_Orphan, &db->b.flags))
                return 0;
 
-       err = orphan_prepare(fs);
+       err = orphan_prepare(fs, 0);
        if (err)
                return err;
  retry:
@@ -257,6 +260,35 @@ int lafs_make_orphan(struct fs *fs, struct datablock *db)
        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)