]> git.neil.brown.name Git - LaFS.git/commitdiff
Pin SegmentMap block when they might need to be dirtied.
authorNeilBrown <neilb@suse.de>
Sat, 26 Jun 2010 03:26:37 +0000 (13:26 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 27 Jun 2010 23:15:02 +0000 (09:15 +1000)
This is more in-keeping with other practices and not that SegmentMap
blocks are handles carefully by the cleaner and checkpoint, it is
safe to do this.
They stay pinned until they are no-longer referenced.  This may keep
some Credits unavailable but that is not a big cost.

When we pin these we don't hold or need a phase lock, so don't
require it.

Now that we alway pin segments when first used (free_get) we don't
need to prealloc in lafs_seg_move.

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

diff --git a/block.c b/block.c
index 7ea8f3aadf2d3f1f476b25670b51ea63c964ddc7..22a6613e3d017b368756cc7441a0938e37eccb3e 100644 (file)
--- a/block.c
+++ b/block.c
@@ -462,9 +462,15 @@ lafs_pin_dblock(struct datablock *b, int alloc_type)
        } else
                blk = getref(&b->b, MKREF(pindb));
 
-       LAFS_BUG(!test_phase_locked(fs), &b->b);
 
-       lafs_phase_wait(blk);
+       if (LAFSI(b->b.inode)->type != TypeSegmentMap) {
+               /* FIXME test is a hack until we get a better
+                * phase wait.  TypeSegmentMap does it's own
+                * dirty management so doesn't need this.
+                */
+               LAFS_BUG(!test_phase_locked(fs), &b->b);
+               lafs_phase_wait(blk);
+       }
 
        set_bit(B_PinPending, &b->b.flags);
        err = lafs_reserve_block(blk, alloc_type);
diff --git a/index.c b/index.c
index 5884e799f0d6003997cfd92d25d943514c4280be..283291e6d2a699c13a2e9348a4429fd1de33be4b 100644 (file)
--- a/index.c
+++ b/index.c
@@ -399,7 +399,8 @@ void lafs_pin_block_ph(struct block *b, int ph)
        struct inode *ino;
 
        LAFS_BUG(b->parent == NULL && !test_bit(B_Root, &b->flags), b);
-       if (!test_bit(B_Realloc, &b->flags))
+       if (!test_bit(B_Realloc, &b->flags) &&
+           LAFSI(b->inode)->type != TypeSegmentMap)
                LAFS_BUG(!test_phase_locked(fs), b);
 
        ino = b->inode;
@@ -818,6 +819,12 @@ void lafs_refile(struct block *b, int dec)
                         */
                        onlru = 1;
 
+               /* PinPending disappears with the last non-lru reference,
+                * (or possibly at other times).
+                */
+               if (atomic_read(&b->refcnt) == dec + onlru)
+                       clear_bit(B_PinPending, &b->flags);
+
                ph = !!test_bit(B_Phase1, &b->flags);
                /* See if we still need to be pinned */
                /* FIXME need some locking here ... */
index 66d9faad0b3f72393580e355c7c0ad6d1775867f..c8f219486f7771eedb08a5ce167408d36311747e 100644 (file)
@@ -313,7 +313,7 @@ int lafs_seg_ref_block(struct block *b, int ssnum)
                        continue;
                }
 
-               err = lafs_prealloc(&ss->ssblk->b, AccountSpace);
+               err = lafs_pin_dblock(ss->ssblk, AccountSpace);
                if (err) {
                        ss_put(ss, fs);
                        putref(b, MKREF(segref));
@@ -376,10 +376,6 @@ void lafs_seg_move(struct fs *fs, u64 oldaddr, u64 newaddr,
                ss = segsum_byaddr(fs, newaddr, ssnum);
                seg_inc(fs, ss, 1, fs->qphase == phase);
 
-               /* FIXME this doesn't belong here, does it ?*/
-               lafs_checkpoint_lock(fs);
-               (void)lafs_reserve_block(&ss->ssblk->b, AccountSpace);
-               lafs_checkpoint_unlock(fs);
                if (!moveref)
                        ss_put(ss, fs);
        }
@@ -1108,9 +1104,9 @@ again:
                                 * to the two blocks !! */
                                LAFS_BUG(1, &db->b);
                        lafs_checkpoint_lock(fs);
-                       (void)lafs_reserve_block(&ssum->ssblk->b, AccountSpace);
+                       (void)lafs_pin_dblock(ssum->ssblk, AccountSpace);
                        if (ssnum == 0)
-                               (void)lafs_reserve_block(&ssum->youthblk->b, AccountSpace);
+                               (void)lafs_pin_dblock(ssum->youthblk, AccountSpace);
                        lafs_checkpoint_unlock(fs);
                        /* These aren't in the table any more - the segsum holds
                         * the necessary reference */
@@ -1133,8 +1129,10 @@ again:
                                               - 1),
                                    NULL, GFP_KERNEL,
                                    MKREF(youth));
-               // FIXME we need to hold a ref on all youth blocks for
-               // known free segments....
+               /* As we hold a ref on youth block for anything in the
+                * table, and that block was loaded at the time, it must
+                * still be valid.
+                */
                BUG_ON(!test_bit(B_Valid, &db->b.flags));
                goto again;
        }