]> git.neil.brown.name Git - LaFS.git/commitdiff
Process orphan file during mount.
authorNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 11:46:46 +0000 (21:46 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 19 Sep 2010 11:46:46 +0000 (21:46 +1000)
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 <neilb@suse.de>
inode.c
lafs.h
orphan.c
roll.c

diff --git a/inode.c b/inode.c
index 489560cca916c3bd3a61ed8e73fc4f8d2b6b7de5..0ad0488a6233e29d2fdee82d4bfb4db9208585c7 100644 (file)
--- 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 5426ee2e77f64ce1516a8339003aa7c2e54dec28..66a58d8290c2e033ee7fe1e34dd1a37006363e20 100644 (file)
--- 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);
index ac538f7bcb28aef2bfedb3326a9b42209aede497..c9dd687306cd5308fc07b8d18a47121df62b046f 100644 (file)
--- 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 400f96604f0bc8686192f3342fa8f3424fc155bc..befba49a4906ab5a4fa178c3bec9da6475a28770 100644 (file)
--- 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);