From: NeilBrown Date: Sun, 19 Sep 2010 11:46:46 +0000 (+1000) Subject: Process orphan file during mount. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=83088c000fd6b41e5f4a926b62fa0013bb6717be;p=LaFS.git Process orphan file during mount. We need to read the orphan file to set nextfree, and then to add all the blocks to the orphan list. Signed-off-by: NeilBrown --- diff --git a/inode.c b/inode.c index 489560c..0ad0488 100644 --- a/inode.c +++ b/inode.c @@ -336,8 +336,8 @@ lafs_import_inode(struct inode *ino, struct datablock *b) case TypeOrphanList: { struct orphan_md *m = &li->md.orphan; - m->nextfree = 0; /* FIXME should I could size of file - * or something? */ + /* This will be set via lafs_count_orphans */ + m->nextfree = 0; m->reserved = 0; break; } @@ -374,7 +374,7 @@ lafs_import_inode(struct inode *ino, struct datablock *b) * Either the orphan file is wrong, or the * linkcount is wrong. * It is safest to assume the later - either - * was an FS check would be needed to fix it. + * way an FS check would be needed to fix it. */ /* FIXME set a superblock flag requesting * directory linkage checking diff --git a/lafs.h b/lafs.h index 5426ee2..66a58d8 100644 --- a/lafs.h +++ b/lafs.h @@ -700,6 +700,8 @@ long lafs_run_orphans(struct fs *fs); void lafs_add_orphan(struct fs *fs, struct datablock *db); void lafs_orphan_forget(struct fs *fs, struct datablock *db); struct datablock *lafs_find_orphan(struct inode *ino); +int lafs_count_orphans(struct inode *ino); +void lafs_add_orphans(struct fs *fs, struct inode *ino, int count); /* Segment.c */ int lafs_prealloc(struct block *b, int type); diff --git a/orphan.c b/orphan.c index ac538f7..c9dd687 100644 --- a/orphan.c +++ b/orphan.c @@ -628,3 +628,96 @@ struct datablock *lafs_find_orphan(struct inode *ino) spin_unlock(&fs->lock); return NULL; } + +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 + */ + int bnum = -1; + int slots = 1 << (ino->i_blkbits - 4); + int slot; + + do { + struct datablock *db; + struct orphan *or; + + bnum++; + slot = 0; + + db = lafs_get_block(ino, bnum, NULL, GFP_KERNEL, MKREF(count_orphans)); + if (!db) + break; + if (lafs_read_block(db) < 0) { + putdref(db, MKREF(count_orphans)); + break; + } + + or = map_dblock(db); + for (slot = 0; slot < slots ; slot++) + if (or[slot].type == 0) + break; + + unmap_dblock(db, or); + putdref(db, MKREF(count_orphans)); + } while (slot == slots); + + return bnum * slots + slot; +} + +void lafs_add_orphans(struct fs *fs, struct inode *ino, int count) +{ + int slots = 1 << (ino->i_blkbits - 4); + int last_block = (count + slots - 1) >> (ino->i_blkbits - 4); + int bnum; + + for (bnum = 0; bnum < last_block; bnum++) { + struct datablock *db = lafs_get_block(ino, bnum, NULL, GFP_KERNEL, MKREF(add_orphans)); + int bslot = bnum * slots; + struct orphan *or; + int slot; + + if (!db) + continue; + + if (lafs_read_block(db) < 0) { + putdref(db, MKREF(add_orphans)); + continue; + } + + 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; + + oino = lafs_iget_fs(fs, + le32_to_cpu(or[slot].filesys), + le32_to_cpu(or[slot].inum), + SYNC); + if (IS_ERR(oino)) + continue; + + ob = lafs_get_block(oino, le32_to_cpu(or[slot].addr), NULL, + GFP_KERNEL, MKREF(add_orphan)); + + if (!IS_ERR(ob)) { + if (!test_and_set_bit(B_Orphan, &ob->b.flags)) { + getdref(ob, MKREF(orphan_flag)); + ob->orphan_slot = bslot + slot; + lafs_add_orphan(fs, ob); + } + putdref(ob, MKREF(add_orphan)); + } + iput(oino); + } + unmap_dblock(db, or); + } +} + + + diff --git a/roll.c b/roll.c index 400f966..befba49 100644 --- a/roll.c +++ b/roll.c @@ -220,7 +220,7 @@ roll_mini(struct fs *fs, int fsnum, int inum, int trunc, int flg, memcpy(buf+offset, data, len); unmap_dblock(db, buf); err = lafs_import_inode(inode, db); - /* WE borrow the orphan list to keep a reference on + /* We borrow the orphan list to keep a reference on * this inode until all processing is finished * to make sure inodes that are about to get linked * to get deleted early @@ -552,7 +552,7 @@ static int roll_forward(struct fs *fs) lafs_add_active(fs, next); - /* Now we release all the nlink==0 inode that we found */ + /* 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, @@ -575,6 +575,7 @@ lafs_mount(struct fs *fs) int err; int d; struct sb_key *k = fs->prime_sb->s_fs_info; + int orphan_count; fs->rolled = 0; fs->ss[0].root = root = iget_locked(fs->prime_sb, 0); @@ -621,9 +622,15 @@ lafs_mount(struct fs *fs) SYNC); /* FIXME check this is a segusage file */ } + orphan_count = lafs_count_orphans(fs->orphans); + LAFSI(fs->orphans)->md.orphan.nextfree = orphan_count; + lafs_checkpoint_lock(fs); err = roll_forward(fs); lafs_checkpoint_unlock(fs); + + lafs_add_orphans(fs, fs->orphans, orphan_count); + for (d = 0; d < 4; d++) { fs->cleaner.seg[d].chead = alloc_page(GFP_KERNEL); INIT_LIST_HEAD(&fs->cleaner.seg[d].cleaning);