]> git.neil.brown.name Git - LaFS.git/commitdiff
Properly track segrefs held by active segments.
authorNeilBrown <neilb@suse.de>
Tue, 29 Jun 2010 11:57:33 +0000 (21:57 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 2 Jul 2010 23:31:19 +0000 (09:31 +1000)
Each active segment holds a segref.  This is currently in a
slightly haphazard way.

If .dev is >= 0 a segref is held, so new_segment drops it,
then devs .dev to -1, unless a new segment is found.

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

index 04f593086a83a8084c98e084707bc59e634087d0..330738a5d67387662d045021e97e5c3048f99531 100644 (file)
--- a/cluster.c
+++ b/cluster.c
@@ -263,8 +263,9 @@ static int seg_remainder(struct fs *fs, struct segpos *seg)
         * this segment
         */
        struct fs_dev *dv = &fs->devs[seg->dev];
-
        int rows = dv->rows_per_table - seg->st_row;
+
+       BUG_ON(seg->dev < 0);
        rows += dv->rows_per_table * (dv->tables_per_seg - seg->st_table - 1);
        return rows * dv->width;
 }
@@ -290,6 +291,7 @@ static u32 seg_setsize(struct fs *fs, struct segpos *seg, u32 size)
         */
        struct fs_dev *dv = &fs->devs[seg->dev];
        u32 rv;
+       BUG_ON(seg->dev < 0);
        size = (size + dv->width - 1) / dv->width;
        rv = size * dv->width;
        size += seg->st_row;
@@ -385,8 +387,13 @@ static int new_segment(struct fs *fs, int cnum)
         */
        if (wc->seg.dev >= 0) {
                p = segtovirt(fs, wc->seg.dev, wc->seg.num);
-               lafs_seg_deref(fs, p, 0);
+               /* If this is the first segment, p would be 0,
+                * so add one to ensure we drop the reference.
+                */
+               lafs_seg_deref(fs, p + 1, 0);
+               wc->seg.dev = -1;
        }
+       wc->remaining = 0;
 
        if (cnum &&
            fs->clean_reserved < fs->max_segment)
@@ -395,7 +402,7 @@ static int new_segment(struct fs *fs, int cnum)
        lafs_free_get(fs, &dev, &seg, 0);
        wc->seg.dev = dev;
        wc->seg.num = seg;
-       seg_setpos(fs, &wc->seg, (p = segtovirt(fs, dev, seg)));
+       seg_setpos(fs, &wc->seg, segtovirt(fs, dev, seg));
 
        wc->remaining = seg_remainder(fs, &wc->seg);
        return 0;
diff --git a/super.c b/super.c
index 80699b4cf7209cfb9006b82c85637218c440b94d..71f50980a611ca0b40a8fb692a97b95c4d0c4eea 100644 (file)
--- a/super.c
+++ b/super.c
@@ -549,6 +549,7 @@ lafs_load(struct options *op, int newest)
                        INIT_LIST_HEAD(&fs->wc[i].pending_blocks[j]);
                }
                init_waitqueue_head(&fs->wc[i].pending_wait);
+               fs->wc[i].seg.dev = -1;
        }
 
        fs->max_newblocks = 1000; /* FIXME this should be configurable, and