From: NeilBrown Date: Sat, 2 Oct 2010 11:15:39 +0000 (+1000) Subject: Be more robust in face of read errors on orphan list. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=6f1426b4a5dcc40dd960f2eac2b4558d80203633;p=LaFS.git Be more robust in face of read errors on orphan list. 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 --- diff --git a/orphan.c b/orphan.c index 7dbb720..5064820 100644 --- 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);