]> git.neil.brown.name Git - LaFS.git/commitdiff
roll: make sure unlinked inodes before orphans.
authorNeilBrown <neilb@suse.de>
Mon, 28 Mar 2011 10:20:32 +0000 (21:20 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 28 Mar 2011 10:20:32 +0000 (21:20 +1100)
If we find an unlinked inode during roll-forward it should end up
being an orphan.
But we don't look at the orphan file soon enough, and if it isn't in
the orphan file then we can BUG, which is bad.
So if we do find one, make it an orphan.  If it turns out to be in the
orphan file that entry will just be discarded.

Signed-off-by: NeilBrown <neilb@suse.de>
roll.c

diff --git a/roll.c b/roll.c
index b1079b4bd5932b5ce54fd7ec18935194c31b2c87..b6d8e3300cdc2c9154d54ceccc212dea5f801c4d 100644 (file)
--- a/roll.c
+++ b/roll.c
@@ -676,6 +676,7 @@ static int roll_forward(struct fs *fs)
        u32 seg;
        u32 offset;
        int order = 0;
+       struct list_head pending;
 
        fs->phase = 1;
        fs->qphase = 0;
@@ -764,11 +765,15 @@ static int roll_forward(struct fs *fs)
 
 
        /* Now we release all the nlink==0 inodes that we found */
-       while (!list_empty(&fs->pending_orphans)) {
-               struct datablock *db = list_entry(fs->pending_orphans.next,
-                                                 struct datablock,
-                                                 orphans);
+       INIT_LIST_HEAD(&pending);
+       list_splice_init(&fs->pending_orphans, &pending);
+       while (!list_empty(&pending)) {
+               struct datablock *db = list_first_entry(&pending,
+                                                       struct datablock,
+                                                       orphans);
                list_del_init(&db->orphans);
+               if (db->my_inode->i_nlink == 0)
+                       lafs_make_orphan(fs, db);
                lafs_iput_fs(db->my_inode);
                putdref(db, MKREF(roll_orphan));
        }