]> git.neil.brown.name Git - LaFS.git/commitdiff
Be more robust in face of read errors on orphan list.
authorNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 11:15:39 +0000 (21:15 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 10 Oct 2010 23:33:55 +0000 (10:33 +1100)
This isn't *very* robust, but we shouldn't BUG now.  Worst case
is we loose some orphans and some orphan slots.  fsck will have
to deal with that.

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

index 7dbb720fb71c0af6e74fa8d94c99e7e969f3b9fb..50648200c9f2cd3ddbab14734ea546aa6c6015d2 100644 (file)
--- a/orphan.c
+++ b/orphan.c
@@ -354,7 +354,7 @@ void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino)
 
        dprintk("os=%d sh=%d ent=%d nf=%d\n", b->orphan_slot, shift,
                ent, om->nextfree);
-
+again:
        if (b->orphan_slot != om->nextfree-1) {
                /* need to swap in the last entry */
                struct inode *bino;
@@ -382,6 +382,17 @@ void lafs_orphan_release(struct fs *fs, struct datablock *b, struct inode *ino)
                lastor[lastent].type = 0;
                unmap_dblock_2(ob2, lastor);
 
+               if (last.type == 0) {
+                       /* this entry was invalidated during read-in.
+                        * lets just forget it
+                        */
+                       om->nextfree--;
+                       om->reserved++;
+                       orphan_abort(fs);
+                       putdref(ob2, MKREF(orphan_move));
+                       goto again;
+               }
+
                /* The block, being an orphan, must exist */
                bino = lafs_iget_fs(fs,
                                    le32_to_cpu(last.filesys),
@@ -626,7 +637,9 @@ int lafs_count_orphans(struct inode *ino)
        /* Count how many active orphan slots there are
         * in this file (which is the orphan file).
         * We simply iterate all the slots until we
-        * find an empty one
+        * find an empty one.
+        * We keep references to the blocks so lafs_add_orphans
+        * is certain to find them.
         */
        int bnum = -1;
        int slots = 1 << (ino->i_blkbits - 4);
@@ -653,7 +666,8 @@ int lafs_count_orphans(struct inode *ino)
                                break;
 
                unmap_dblock(db, or);
-               putdref(db, MKREF(count_orphans));
+               if (slot == 0)
+                       putdref(db, MKREF(count_orphans));
        } while (slot == slots);
 
        return bnum * slots + slot;
@@ -671,28 +685,26 @@ void lafs_add_orphans(struct fs *fs, struct inode *ino, int count)
                struct orphan *or;
                int slot;
 
-               if (!db)
-                       continue;
-
-               if (lafs_read_block(db) < 0) {
-                       putdref(db, MKREF(add_orphans));
-                       continue;
-               }
+               /* We already own a count_orphans ref on this block */
+               BUG_ON(!db);
+               LAFS_BUG(!test_bit(B_Valid, &db->b.flags), &db->b);
+               putdref(db, MKREF(count_orphans));
 
                or = map_dblock(db);
                for (slot = 0; slot < slots && bslot + slot < count; slot++) {
                        struct inode *oino;
                        struct datablock *ob;
 
-                       if (or[slot].type == 0)
-                               continue;
+                       LAFS_BUG(or[slot].type == 0, &db->b);
                        
                        oino = lafs_iget_fs(fs,
                                            le32_to_cpu(or[slot].filesys),
                                            le32_to_cpu(or[slot].inum),
                                            SYNC);
-                       if (IS_ERR(oino))
+                       if (IS_ERR(oino)) {
+                               or[slot].type = 0;
                                continue;
+                       }
 
                        ob = lafs_get_block(oino, le32_to_cpu(or[slot].addr), NULL,
                                            GFP_KERNEL, MKREF(add_orphan));
@@ -703,7 +715,8 @@ void lafs_add_orphans(struct fs *fs, struct inode *ino, int count)
                                        getdref(db, MKREF(orphan));
                                        ob->orphan_slot = bslot + slot;
                                        lafs_add_orphan(fs, ob);
-                               }
+                               } else
+                                       or[slot].type = 0;
                                putdref(ob, MKREF(add_orphan));
                        }
                        iput(oino);