]> git.neil.brown.name Git - LaFS.git/commitdiff
SegRef fixes.
authorNeilBrown <neilb@suse.de>
Sun, 20 Jun 2010 23:41:51 +0000 (09:41 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 21 Jun 2010 00:29:32 +0000 (10:29 +1000)
We mustn't hold a SegRef for blocks which aren't going to be accounted
in any segment usage counts.

This means we should never hold SegRef on the Root block, and if we
decide not to account certain block during unmount - as roll-forward
will account them - we should drop SegRef promptly.

Signed-off-by: NeilBrown <neilb@suse.de>
block.c
index.c
segments.c

diff --git a/block.c b/block.c
index b4fcf3405a94fbade2e342b43ac86eb3a6d37577..646174793adcd497f03c2c46ffdb87194fa9a8ad 100644 (file)
--- a/block.c
+++ b/block.c
@@ -401,9 +401,12 @@ lafs_reserve_block(struct block *b, int alloc_type)
 
        /* Having reserved the block, we need to get a segref,
         * which will involve reserving those blocks too.
+        * However we never get a segref for Root.
         */
 
-       while (err == 0 && !test_bit(B_SegRef, &b->flags))
+       while (err == 0
+              && !test_bit(B_Root, &b->flags)
+              && !test_bit(B_SegRef, &b->flags))
                err = lafs_seg_ref_block(b, 0);
 
        return err;
diff --git a/index.c b/index.c
index c6cf20a2b6c6d50ee38b1b23c471abbff6f91189..f8e50a3dfe21943fd5e307c764056f029f429375 100644 (file)
--- a/index.c
+++ b/index.c
@@ -1951,6 +1951,7 @@ int lafs_allocated_block(struct fs *fs, struct block *blk, u64 phys)
                LAFS_BUG(i == fs->maxsnapshot, blk);
                blk->physaddr = phys; /* superblock doesn't get
                                         counted in summaries */
+               LAFS_BUG(test_bit(B_SegRef, &blk->flags), blk);
                set_bit(B_PhysValid, &blk->flags);
                fs->ss[i].root_addr = phys;
                lai = LAFSI(blk->inode);
@@ -1975,6 +1976,8 @@ int lafs_allocated_block(struct fs *fs, struct block *blk, u64 phys)
                 * dirty after the checkpoint.
                 * So just return
                 */
+               if (test_and_clear_bit(B_SegRef, &blk->flags))
+                       lafs_seg_deref(fs, blk->physaddr, 0);
                blk->physaddr = phys;
                set_bit(B_PhysValid, &blk->flags);
                return 0;
index a941d690be30db89448e9400987664d0235c4b39..4f393e98b634ce2ad535cdcb40bdf083761ae2f5 100644 (file)
@@ -245,6 +245,8 @@ void lafs_seg_put_all(struct fs *fs)
  * find the matching segsum block.  If it already
  * has SegRef, we add the reference and retry from the start.
  * If it doesn't have SegRef, we prealloc and then tail recurse.
+ * Note: we never set SegRef on B_Root blocks as their usage
+ * isn't recorded.
  */
 int lafs_seg_ref_block(struct block *b, int ssnum)
 {
@@ -257,6 +259,9 @@ int lafs_seg_ref_block(struct block *b, int ssnum)
        getref(b, MKREF(segref));
 
        while (!test_bit(B_SegRef, &b->flags)) {
+
+               BUG_ON(test_bit(B_Root, &b->flags));
+
                if (b->physaddr == 0) {
                        set_bit(B_SegRef, &b->flags);
                        break;