]> git.neil.brown.name Git - LaFS.git/commitdiff
Set EmptyIndex where appropriate.
authorNeilBrown <neilb@suse.de>
Tue, 22 Jun 2010 06:08:51 +0000 (16:08 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 23 Jun 2010 01:57:21 +0000 (11:57 +1000)
When an index block becomes empty during incorp, mark it as
Empty.
All that other special handling we had now seems to be over-kill.

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

index c44e4dc71c41133010ac4a0ec0aa3d5639bca434..34712b83ab9676eb661234685855e09ef2a4ba77 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -1553,88 +1553,6 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib,
        return 2;
 }
 
-static u32 update_index(struct indexblock *ib, u32 addr, u64 newphys)
-{
-       /* addr exists in the given internal index block.
-        * We want to replace it's physaddr either with 'newphys'
-        * or with the next entry in which case we remove all 
-        * other trace of the next shuffling down subsequent entries.
-        * Return the next address if one exists, else 0.
-        * If we do find there is no next entry, we must be sure to
-        * fully erase *this* entry, not just set phys to 0.
-        */
-       char *buf = map_iblock(ib);
-       char *p;
-       int len = 1 << ib->b.inode->i_blkbits;
-       u32 rv = 0;
-       u64 phys;
-       u32 a;
-       int found = 0;
-       int type;
-
-       p = buf;
-       if (test_bit(B_InoIdx, &ib->b.flags)) {
-               int offset = LAFSI(ib->b.inode)->metadata_size;
-               len -= offset;
-               p += offset;
-       }
-       type = decode16(p);
-       len -= 2;
-       LAFS_BUG(type != IBLK_INDEX, &ib->b);
-       while (len > 10) {
-               phys = decode48(p);
-               a = decode32(p);
-               len -= 10;
-               if (found) {
-                       p -= 20;
-                       encode48(p, phys);
-                       LAFS_BUG(a && !phys, &ib->b);
-                       if (rv == 0 && a) {
-                               rv = a;
-                               p += 4;
-                       } else
-                               encode32(p, a);
-                       encode48(p, 0ULL);
-                       encode32(p, 0UL);
-               } else if (a == addr) {
-                       found = 1;
-                       if (newphys) {
-                               p -= 10;
-                               encode48(p, newphys);
-                               break;
-                       }
-               } else
-                       LAFS_BUG(a > addr, &ib->b);
-               if (phys == 0)
-                       break;
-       }
-       LAFS_BUG(!found, &ib->b);
-       unmap_iblock(ib, buf);
-       lafs_dirty_iblock(ib);
-       return rv;
-}
-
-static void readdress_index(struct inode *ino, u32 addr, int depth,
-                           u32 newaddr)
-{
-       /* all index blocks of ino at or below depth need to be
-        * relocated to newaddr, including rehashing them.
-        */
-       while (depth) {
-               struct indexblock *ib = lafs_iblock_get(ino, addr, depth,
-                                                       0, MKREF(readdr));
-               if (ib) {
-                       lafs_iolock_block(&ib->b);
-                       ib->b.fileaddr = newaddr;
-                       lafs_unhash_iblock(ib);
-                       lafs_hash_iblock(ib);
-                       lafs_iounlock_block(&ib->b);
-                       putiref(ib, MKREF(readdr));
-               }
-               depth--;
-       }
-}
-
 static void filter_empties(struct block **uninc)
 {
        /* If any block has phys==0 and there is another block
@@ -1670,10 +1588,9 @@ static void filter_empties(struct block **uninc)
 void lafs_incorporate(struct fs *fs, struct indexblock *ib)
 {
        int offset;     /* start of block where indexing is */
-       struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt, *prv;
-       struct block *uninc = NULL, **bp;
+       struct indexblock *new = NULL;
+       struct block *uninc = NULL;
        int rv = 0;
-       u32 next;
        char *buf;
        struct uninc uit;
        int blocksize = fs->prime_sb->s_blocksize;
@@ -1900,16 +1817,10 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
        temp_credits = 0;
        lafs_space_return(fs, uit.credits);
 
-       /* If this index block is now empty, we either
-        * invalidate it and possibly find something else to take
-        * it's place.
-        * If there is nothing to take it's place, and it is the
-        * first block in the parent, we need to recurse up and
-        * resolve the parent in the same way.
+       /* If this index block is now empty and has no
+        * children which are not EmptyIndex, we flag it
+        * as EmptyIndex so index lookups know to avoid it.
         */
-       orig_ib = ib;
-       locked_ib = ib;
- recurse:
        if (test_bit(B_InoIdx, &ib->b.flags)) {
                /* Empty InoIdx blocks are allowed.  However depth must
                 * be 1.  This is where we suddenly collapse a now-empty
@@ -1927,129 +1838,28 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
        }
        if (ib->depth > 1 && ! lafs_index_empty(ib))
                goto out2;
+       if (ib->depth > 1) {
+               int non_empty = 0;
+               struct block *b;
+               spin_lock(&ib->b.inode->i_data.private_lock);
+               list_for_each_entry(b, &ib->children, siblings)
+                       if (!test_bit(B_EmptyIndex, &b->flags)) {
+                               non_empty = 1;
+                               break;
+                       }
+               spin_unlock(&ib->b.inode->i_data.private_lock);
+               if (non_empty)
+                       goto out2;
+       }
        if (ib->depth == 1 &&
            (lafs_leaf_next(ib, 0) != 0xFFFFFFFF ||
             !list_empty(&ib->children)))
                goto out2;
 
-       /* OK, it is empty now.  There are various ways we can handle
-        * this.  All involve modification of the parent in some way,
-        * so we need to get a lock on said parent.
-        * This requires dropping the lock on this block, so we
-        * take i_alloc_sem to stop index looks from getting in our way.
-        */
-       if (test_bit(B_PhysValid, &ib->b.flags))
-               // FIXME this call is improperly locked
-               lafs_allocated_block(fs, &ib->b, 0);
-       else {
-               ib->b.physaddr = 0;
-               set_bit(B_PhysValid, &ib->b.flags);
-       }
-       down_write(&ib->b.inode->i_alloc_sem);
-       /* Any index lookup in ib will notice it is invalid and block
-        * on i_alloc_sem, so it is safe to unlock ib
-        */
-       lafs_iounlock_block(&ib->b);
-       lafs_iolock_block(&ib->b.parent->b);
-       locked_ib = ib->b.parent;
-       /* Now anything looking for an address that could be in ib will
-        * block on the parent first, so we don't need i_alloc_sem
-        * any more.
-        */
-       up_write(&ib->b.inode->i_alloc_sem);
-
-       /* ib is empty and so we are going to remove it from the parent.
-        * So we need to clear any 'dirty' status and remove from the
-        * uninc list
-        */
-       if (test_bit(B_Uninc, &ib->b.flags)) {
-               int doput = 0;
-               spin_lock(&ib->b.inode->i_data.private_lock);
-               for (bp = &ib->b.parent->uninc ; *bp ; ) {
-                       if (*bp == &ib->b) {
-                               *bp = ib->b.chain;
-                               clear_bit(B_Uninc, &ib->b.flags);
-                               doput = 1;
-                               break;
-                       } else
-                               bp = &(*bp)->chain;
-               }
-               spin_unlock(&ib->b.inode->i_data.private_lock);
-               if (doput)
-                       putiref(ib, MKREF(uninc));
-       }
-       if (test_and_clear_bit(B_Dirty, &ib->b.flags))
-               lafs_space_return(fs, 1);
-       if (test_and_clear_bit(B_Realloc, &ib->b.flags))
-               lafs_space_return(fs, 1);
-       /* refile should remove from leaf list */
-       lafs_refile(&ib->b, 0);
-       /* Options for how to handle the fact that ib is now empty.
-        * If this block is not yet incorporated, it can
-        *    be quietly deleted.
-        * If it is, but next isn't re-address that one to take the place.
-        * If next is incorporated and dirty, re-address it likewise,
-        *    deleting the phys from the parent
-        * If next is not dirty, update parent and possibly re-address next
-        * If no next, and parent not empty, just delete
-        * If parent becomes empty, recurse upwards.
-        */
-       nxt = NULL;
-       if (ib->b.siblings.next != &ib->b.parent->children)
-               nxt = list_entry(ib->b.siblings.next, struct indexblock, b.siblings);
-       prv = NULL;
-       if (ib->b.siblings.prev != &ib->b.parent->children)
-               prv = list_entry(ib->b.siblings.prev, struct indexblock, b.siblings);
-       /* we don't need to move to the inode->free_index list as that will
-        * happen when refile drops the ->parent link.
-        * If we completely remove from the list, refile will get confused in
-        * consistency checks.   So just move to the end of the list
-        * to avoid confusing PrimaryRef chains.
-        */
-       list_move_tail(&ib->b.siblings, &ib->b.parent->children);
-       lafs_unhash_iblock(ib);
-       if (test_and_clear_bit(B_PrimaryRef, &ib->b.flags)) {
-               /* This was not incorporated yet, revert the uninc status */
-               if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
-                       /* I was in a PrimaryRef chain */
-                       putiref(ib, MKREF(primary));
-               } else {
-                       LAFS_BUG(!prv, &ib->b);
-                       putiref(prv, MKREF(primary));
-               }
-       } else if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
-               /* Next block is not incorporated yet, so simply re-address
-                * it to replace this block.
-                */
-               clear_bit(B_PrimaryRef, &nxt->b.flags);
-               putiref(ib, MKREF(primary));
-               readdress_index(ib->b.inode, nxt->b.fileaddr, nxt->depth,
-                               ib->b.fileaddr);
-               if (test_bit(B_PhysValid, &nxt->b.flags)) {
-                       LAFS_BUG(nxt->b.physaddr == 0, &nxt->b);
-                       update_index(ib->b.parent, ib->b.fileaddr, nxt->b.physaddr);
-               }
-       } else if ((next = update_index(ib->b.parent, ib->b.fileaddr, 0)) != 0) {
-               /* Found a 'next' block in the parent and have updated the parent.
-                * Need to check for block in cache and re-address
-                */
-               readdress_index(ib->b.inode, next, ib->depth, ib->b.fileaddr);
-       } else if (ib->b.parent->b.fileaddr == ib->b.fileaddr) {
-               /* The parent has just become empty and needs to be 
-                * removed from it's parent.
-                */
-               ib = ib->b.parent;
-               goto recurse;
-       }
-       /* Currently hold iolock on ib->b.parent, and refcnt on orig_ib
-        * which is a descendent.
-        * Need to return with iolock on orig_ib.
-        */
+       /* Block is really really empty */
+       set_bit(B_EmptyIndex, &ib->b.flags);
 out2:
-       if (locked_ib != orig_ib) {
-               lafs_iolock_block(&orig_ib->b);
-               lafs_iounlock_block(&locked_ib->b);
-       }
+       return;
 }
 
 /***************************************************************