]> git.neil.brown.name Git - LaFS.git/commitdiff
FORMAT CHANGE - include start address explicitly in indirect blocks.
authorNeilBrown <neilb@suse.de>
Mon, 28 Sep 2009 00:16:17 +0000 (10:16 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 28 Sep 2009 00:16:17 +0000 (10:16 +1000)
By storing the address of the first block in an indirect block,
that block can be relocated in the index tree with no adverse effects.
This makes it easier to handle blocks that have become empty.

So an indirect block now contains:
   u16 0x01   'indirect' indicator
   u32 addr   virtual address of first indexed block
   u48 paddr  physical address of first indexblock block
   u48 paddr2 next block ... etc

index.c
modify.c

diff --git a/index.c b/index.c
index 7d9ec0d3c20aab999a3933dda36e645eb1340f50..b3f244876248353d9181808eb29b005012b5cb66 100644 (file)
--- a/index.c
+++ b/index.c
@@ -1070,7 +1070,7 @@ lafs_make_iblock(struct inode *ino, int adopt, int async, REFARG)
 }
 
 static u64
-leaf_lookup(void *bf, int len, u32 startaddr, u32 target, u32 *nextp)
+leaf_lookup(void *bf, int len, u32 target, u32 *nextp)
 {
        /* buf starts with a 2byte header
         * if 1, then 6byte littleending indirect entries.
@@ -1094,16 +1094,18 @@ leaf_lookup(void *bf, int len, u32 startaddr, u32 target, u32 *nextp)
                break;
 
        case IBLK_INDIRECT: /* indirect */
-               dprintk("indirect lookup for %lu from %lu, len %d\n",
-                       (unsigned long)target, (unsigned long)startaddr, len);
                len -= 2;
                buf += 2;
+               addr = decode32(buf);
+               len -= 4;
+               dprintk("indirect lookup for %lu from %lu, len %d\n",
+                       (unsigned long)target, (unsigned long)addr, len);
 
-               if (target < startaddr)
+               if (target < addr)
                        return 0;
 
                next = target;
-               target -= startaddr;
+               target -= addr;
 
                /* Need both tests as target could be v.large and
                 * multiply by 6 could overflow
@@ -1203,10 +1205,10 @@ u32 lafs_leaf_next(struct indexblock *ib, u32 start)
        if (test_bit(B_InoIdx, &ib->b.flags))
                phys = leaf_lookup(buf + li->metadata_size,
                                   blocksize - li->metadata_size,
-                                  ib->b.fileaddr, start, &next);
+                                  start, &next);
        else
                phys = leaf_lookup(buf, blocksize,
-                                  ib->b.fileaddr, start, &next);
+                                  start, &next);
        unmap_iblock(ib, buf);
        if (phys)
                return start;
@@ -1502,7 +1504,7 @@ static int __lafs_find_next(struct inode *ino, loff_t *addrp)
                        offset = lai->metadata_size;
                buf = map_iblock(leaf);
                p = leaf_lookup(buf+offset, fs->prime_sb->s_blocksize-offset,
-                               leaf->b.fileaddr, (u32)*addrp, &nextd);
+                               (u32)*addrp, &nextd);
                unmap_iblock(leaf, buf);
                if (p) {
                        lafs_iounlock_block(&leaf->b);
@@ -1751,7 +1753,7 @@ find_block(struct datablock *b, int adopt, int async)
                b->b.physaddr = leaf_lookup(buf+offset,
                                            b->b.inode->i_sb->s_blocksize
                                            - offset,
-                                           ib->b.fileaddr, b->b.fileaddr,
+                                           b->b.fileaddr,
                                            NULL);
                set_bit(B_PhysValid, &b->b.flags);
                unmap_iblock(ib, buf);
index 2796c25430cb0c473410799d2222539b85fe9de6..2dfbe20928fc04f74854c101321ff6495be26377 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -165,13 +165,17 @@ static int incorp_index(struct block *b)
        return cr;
 }
 
-static int incorporate_indirect(struct uninc *ui, char *buf, u32 addr, int len)
+static int incorporate_indirect(struct uninc *ui, char *buf, int len)
 {
        /* See if this uninc info can be incorporated directly into
         * this indirect block, and if it can: do it.
         */
        int i;
        int credits = 0;
+       u32 addr;
+
+       addr = decode32(buf);
+       len -= 4;
 
        if ( ui->pending_addr[ui->pending_cnt-1].fileaddr
            +ui->pending_addr[ui->pending_cnt-1].cnt
@@ -481,7 +485,7 @@ static void grow_index_tree(struct indexblock *ib, struct indexblock *new)
        atomic_set(&new->pincnt[!!test_bit(B_Phase1, &ib->b.flags)], 1);
 }
 
-static void print_index(char *buf, u32 start, int len)
+static void print_index(char *buf, int len)
 {
        int type = le16_to_cpu(*(u16 *)(buf));
        char *p = buf+2;
@@ -492,12 +496,13 @@ static void print_index(char *buf, u32 start, int len)
 
        switch (type) {
        case IBLK_INDIRECT:
-               printk(" Indirect:\n");
+               addr = decode32(p);
+               printk(" Indirect %lu:\n", (unsigned long)addr);
                while (len >= 6) {
                        phys = decode48(p);
                        if (phys)
-                               printk(" %u:%lu", start, (unsigned long)phys);
-                       start++;
+                               printk(" %u:%lu", addr, (unsigned long)phys);
+                       addr++;
                        len -= 6;
                }
                printk("\n");
@@ -587,7 +592,7 @@ static int add_indirect(void *data, u32 addr, u64 phys, int len)
 
        if (phys == 0) {
                /* initialise */
-               li->lastaddr = addr;
+               li->lastphys = 0;
                p = li->data;
                encode16(p, IBLK_INDIRECT);
                li->size -= 2;
@@ -597,6 +602,15 @@ static int add_indirect(void *data, u32 addr, u64 phys, int len)
        if (len == 0)
                return 0; /* finalise */
 
+       if (li->lastphys == 0) {
+               /* This is the first address, add the address header */
+               li->lastaddr = addr;
+               li->lastphys = phys;
+               p = li->data;
+               encode32(p, addr);
+               li->data = p;
+               li->size -= 4;
+       }
        p = li->data + (addr - li->lastaddr) * 6;
        lastaddr = li->lastaddr + (li->size/6);
        for (i = 0; i < len && addr < lastaddr ; i++) {
@@ -693,16 +707,17 @@ static int check_leaf(void *data, u32 addr, u64 phys, int len)
        if (phys == 0) {
                /* We are initialising the structure */
                memset(li, 0, sizeof(*li));
-               li->firstaddr = addr;
                li->blksize = len - 2; /* exclude type filed */
                return 0;
        }
        if (len == 0)
                return 0; /* nothing to finalise */
+       if (li->cnt == 0)
+               li->firstaddr = addr;
 
        li->cnt++;
        /* Check for indirect layout */
-       if (((addr + len) - li->firstaddr) * 6 > li->blksize) {
+       if (((addr + len) - li->firstaddr) * 6 > (li->blksize-4)) {
                /* Indirect no longer fits */
                if (!li->choice)
                        li->choice = IBLK_EXTENT;
@@ -744,7 +759,7 @@ static int check_leaf(void *data, u32 addr, u64 phys, int len)
        return origlen;
 }
 
-static u32 walk_index(u32 addr, char **bufp, int len, struct block *uninc,
+static u32 walk_index(char **bufp, int len, struct block *uninc,
                      int (*handle)(void*, u32, u64),
                      void *data)
 {
@@ -758,7 +773,7 @@ static u32 walk_index(u32 addr, char **bufp, int len, struct block *uninc,
         */
        char *buf = *bufp;
 
-       handle(data, addr, 0); /* initialise */
+       handle(data, 0, 0); /* initialise */
 
        while (len >= 10 || uninc != NULL) {
                unsigned long addr = 0;
@@ -795,7 +810,7 @@ static u32 walk_index(u32 addr, char **bufp, int len, struct block *uninc,
        return 0;
 }
 
-static u32 walk_indirect(u32 addr, char **bufp, int len, struct uninc *ui,
+static u32 walk_indirect(char **bufp, int len, struct uninc *ui,
                         int (*handle)(void*, u32, u64, int),
                         void *data)
 {
@@ -808,9 +823,13 @@ static u32 walk_indirect(u32 addr, char **bufp, int len, struct uninc *ui,
        int uinum = 0;
        int uioffset = 0;
        char *buf = *bufp;
+       u32 addr;
+
 
-       handle(data, addr, 0, len); /* initialise */
+       handle(data, 0, 0, len); /* initialise */
 
+       addr = decode32(buf);
+       len -= 4;
        while (len >= 6 || uinum < ui->pending_cnt) {
                u64 phys = 0;
 
@@ -847,9 +866,9 @@ static u32 walk_indirect(u32 addr, char **bufp, int len, struct uninc *ui,
        return 0;
 }
 
-static u32 walk_extent(u32 addr, char **bufp, int len, struct uninc *ui,
-                       int (*handle)(void*, u32, u64, int),
-                       void *data)
+static u32 walk_extent(char **bufp, int len, struct uninc *ui,
+                      int (*handle)(void*, u32, u64, int),
+                      void *data)
 {
        /* pass each extent in buf or ui to handle.  Extents
         * can overlap, so care is needed
@@ -862,7 +881,7 @@ static u32 walk_extent(u32 addr, char **bufp, int len, struct uninc *ui,
        int handled;
        char *buf = *bufp;
 
-       handle(data, addr, 0, len); /* initialise */
+       handle(data, 0, 0, len); /* initialise */
 
        while (len >= 12 || uinum < ui->pending_cnt || elen) {
 
@@ -997,13 +1016,11 @@ void lafs_walk_leaf_index(struct indexblock *ib,
        dprintk("CURRENT=%d\n", current_layout);
        switch (current_layout) {
        case IBLK_INDIRECT:
-               walk_indirect(ib->b.fileaddr,
-                             &buf, len-2, &ui,
+               walk_indirect(&buf, len-2, &ui,
                              handle, data);
                break;
        case IBLK_EXTENT:
-               walk_extent(ib->b.fileaddr,
-                           &buf, len-2, &ui,
+               walk_extent(&buf, len-2, &ui,
                            handle, data);
                break;
        default:
@@ -1178,13 +1195,11 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib,
        buf = ibuf + offset + 2;
        switch (current_layout) {
        case IBLK_INDIRECT:
-               walk_indirect(ib->b.fileaddr,
-                             &buf, len-2, ui,
+               walk_indirect(&buf, len-2, ui,
                              check_leaf, &leafinfo);
                break;
        case IBLK_EXTENT:
-               walk_extent(ib->b.fileaddr,
-                           &buf, len-2, ui,
+               walk_extent(&buf, len-2, ui,
                            check_leaf, &leafinfo);
                break;
        default:
@@ -1215,22 +1230,20 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib,
        buf = ibuf + offset + 2;
        switch (current_layout) {
        case IBLK_INDIRECT:
-               next = walk_indirect(ib->b.fileaddr,
-                                    &buf, len-2, ui,
+               next = walk_indirect(&buf, len-2, ui,
                                     (choice == IBLK_EXTENT)
                                     ? add_extent : add_indirect,
                                     &layout);
                break;
        case IBLK_EXTENT:
-               next = walk_extent(ib->b.fileaddr,
-                                  &buf, len-2, ui,
+               next = walk_extent(&buf, len-2, ui,
                                   (choice == IBLK_EXTENT)
                                   ? add_extent : add_indirect,
                                   &layout);
                break;
        }
        dprintk("walk_leaf only got as far as %d\n", (int)next);
-       // print_index(ibuf+offset, ib->b.fileaddr, len);
+       // print_index(ibuf+offset, len);
        if (next == 0) {
                /* it all fit perfectly.
                 * Copy from 'new' into 'ib' and zero the uninc list
@@ -1352,7 +1365,7 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib,
        }
        layout.data = ibuf;
        layout.size = len;
-       next2 = walk_extent(next, &sbuf, slen, ui, add_extent, &layout);
+       next2 = walk_extent(&sbuf, slen, ui, add_extent, &layout);
        LAFS_BUG(next2 != 0, &ib->b);
        if (slen && layout.data > sbuf) {
                printk("slen=%d ld-sb=%d layout.data=%p sbuf=%p "
@@ -1441,8 +1454,7 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib,
 
        buf = ibuf + offset + 2;
 
-       next = walk_index(ib->b.fileaddr,
-                         &buf, len-2, uninc,
+       next = walk_index(&buf, len-2, uninc,
                          add_index,
                          &layout);
 
@@ -1617,7 +1629,6 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
                /* Maybe a direct update of an indirect block */
                if (*(u16 *)(buf) == cpu_to_le16(IBLK_INDIRECT) &&
                    incorporate_indirect(&uit, buf+2,
-                                        ib->b.fileaddr,
                                         blocksize-(offset+2))) {
                        unmap_iblock(ib, buf-offset);
                        goto out;
@@ -1633,7 +1644,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
 
                dprintk("Index contains:\n");
                if (lafs_trace)
-                       print_index(buf, ib->b.fileaddr, blocksize - offset);
+                       print_index(buf, blocksize - offset);
                dprintk("uninc contains:\n");
                if (lafs_trace)
                        lafs_print_uninc(&uit);
@@ -1672,7 +1683,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
                if (lafs_trace) {
                        struct block *b;
 
-                       print_index(buf, ib->b.fileaddr, blocksize - offset);
+                       print_index(buf, blocksize - offset);
                        printk("uninc list:\n");
                        for (b = uninc; b ; b=b->chain)
                                printk("  %lu: %llu\n",