From 790a63ff9dd9ab7a0944d22798ecc57e8a41ee46 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 18 Jun 2010 21:47:27 +1000 Subject: [PATCH] Incorp: improve setting of address after split. When we split a block, the address of the second half should be the first address that won't fit in the original block. Currently it is the first address that didn't fit. If we end up adding blocks in reverse address order, this could cause each new block to require a split. Signed-off-by: NeilBrown --- modify.c | 62 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/modify.c b/modify.c index 71d6c3f..23e6437 100644 --- a/modify.c +++ b/modify.c @@ -517,7 +517,8 @@ void lafs_print_uninc(struct uninc *ui) struct layoutinfo { char *data; int size; - u32 forcestart; + u32 forcestart; /* set, indirect block must be address from here */ + u32 nextaddr; /* on failure, set to the first address that doesn't fit */ u64 lastphys; u32 lastaddr; @@ -540,8 +541,10 @@ static int add_index(void *data, u32 addr, u64 phys) if (phys == ~0LL) return 0; - if (li->size < 10) + if (li->size < 10) { + li->nextaddr = addr; return 0; + } cp = li->data; /* Each entry is 10 bytes: 6byte dev, 4byte file */ @@ -591,6 +594,8 @@ static int add_indirect(void *data, u32 addr, u64 phys, int len) addr++; phys++; } + if (i < len) + li->nextaddr = addr; return i; } @@ -636,6 +641,7 @@ static int add_extent(void *data, u32 addr, u64 phys, int len) if (li->size < 12) { /* No room */ dprintk("Extent says 'no room'\n"); + li->nextaddr = li->lastaddr; return 0; } p = li->data; @@ -741,7 +747,7 @@ static u32 walk_index(char **bufp, int len, struct block *uninc, * always add_index). * Must pass addresses in order. * 'handle' returns 1 if the address was added. - * We return the first address not handled, or 0 if all are handled. + * We return 1 if all addressed handled, else 0. * * Entries are 10 bytes: 6 byte dev address, 4 byte file address. */ @@ -769,7 +775,7 @@ static u32 walk_index(char **bufp, int len, struct block *uninc, if (addr > uninc->fileaddr) buf -= 10; *bufp = buf; - return uninc->fileaddr; + return 0; } if (uninc->fileaddr == addr) /* Don't record the old value from the index */ @@ -779,13 +785,13 @@ static u32 walk_index(char **bufp, int len, struct block *uninc, if (phys && !handle(data, addr, phys)) { *bufp = buf - 10; - return addr; + return 0; } if (phys == 0 && uninc == NULL) break; } handle(data, 0, ~(u64)0); /* finalise */ - return 0; + return 1; } static u32 walk_indirect(char **bufp, int len, struct uninc *ui, @@ -795,8 +801,8 @@ static u32 walk_indirect(char **bufp, int len, struct uninc *ui, /* Pass each entry in buf or ui to "handle". * Must pass addresses in order. * 'handle' returns number of addresses handled. - * If this isn't all, we stop and return the first address - * not handled - or 0 if all are handled. + * If this isn't all, we stop and return 0 + * else 1 if all are handled. */ int uinum = 0; int uioffset = 0; @@ -834,14 +840,14 @@ static u32 walk_indirect(char **bufp, int len, struct uninc *ui, if (phys) { if (!handle(data, addr, phys, 1)) { *bufp = buf - 6; - return addr; + return 0; } } addr++; } handle(data, 0, ~(u64)0, 0); /* finalise */ - return 0; + return 1; } static u32 walk_extent(char **bufp, int len, struct uninc *ui, @@ -926,8 +932,7 @@ static u32 walk_extent(char **bufp, int len, struct uninc *ui, *bufp = buf - 12; else *bufp = buf; - return ui->pending_addr[uinum].fileaddr - + uioffset + handled; + return 0; } uioffset += hlen; if (uioffset >= ui->pending_addr[uinum].cnt) { @@ -945,7 +950,7 @@ static u32 walk_extent(char **bufp, int len, struct uninc *ui, handled = handle(data, eaddr, ephys, elen2); if (handled < elen2) { *bufp = buf - 12; - return eaddr + handled; + return 0; } eaddr += elen2; ephys += elen2; @@ -955,7 +960,7 @@ static u32 walk_extent(char **bufp, int len, struct uninc *ui, handled = handle(data, eaddr, ephys, elen); if (handled < elen) { *bufp = buf - 12; - return eaddr + handled; + return 0; } elen = 0; @@ -963,7 +968,7 @@ static u32 walk_extent(char **bufp, int len, struct uninc *ui, } *bufp = buf; handle(data, 0, ~(u64)0, 0); /* finalise */ - return 0; + return 1; } void lafs_walk_leaf_index(struct indexblock *ib, @@ -1157,9 +1162,9 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib, int current_layout; int choice; struct layoutinfo layout; - u32 next = 0; - u32 next2; + u32 next; int uinxt, uinum; + int ok; u32 eaddr; u64 ephys; @@ -1216,13 +1221,13 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib, buf = ibuf + offset + 2; switch (current_layout) { case IBLK_INDIRECT: - next = walk_indirect(&buf, len-2, ui, + ok = walk_indirect(&buf, len-2, ui, (choice == IBLK_EXTENT) ? add_extent : add_indirect, &layout); break; case IBLK_EXTENT: - next = walk_extent(&buf, len-2, ui, + ok = walk_extent(&buf, len-2, ui, (choice == IBLK_EXTENT) ? add_extent : add_indirect, &layout); @@ -1230,7 +1235,7 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib, } dprintk("walk_leaf only got as far as %d\n", (int)next); // print_index(ibuf+offset, len); - if (next == 0) { + if (ok) { /* it all fit perfectly. * Copy from 'new' into 'ib' and zero the uninc list */ @@ -1240,6 +1245,7 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib, unmap_iblock(ib, ibuf); return 1; } + next = layout.nextaddr; LAFS_BUG(offset, &ib->b); /* It didn't fit, and this is a regular index block, so @@ -1368,8 +1374,8 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib, } layout.data = ibuf; layout.size = len; - next2 = walk_extent(&sbuf, slen, ui, add_extent, &layout); - LAFS_BUG(next2 != 0, &ib->b); + ok = walk_extent(&sbuf, slen, ui, add_extent, &layout); + LAFS_BUG(!ok, &ib->b); if (slen && layout.data > sbuf) { printk("slen=%d ld-sb=%d layout.data=%p sbuf=%p " "buf=%p ibuf=%p len=%d\n", @@ -1442,6 +1448,7 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib, int current_layout; struct layoutinfo layout; u32 next = 0; + int ok; int cr; ibuf = map_iblock(ib); @@ -1463,14 +1470,14 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib, buf = ibuf + offset + 2; - next = walk_index(&buf, len-2, uninc, - ib->b.fileaddr, - add_index, - &layout); + ok = walk_index(&buf, len-2, uninc, + ib->b.fileaddr, + add_index, + &layout); dprintk("walk_index only got as far as %d\n", (int)next); - if (next == 0) { + if (ok) { /* it all fit perfectly. * Copy from 'new' into 'ib' and free all uninc blocks */ @@ -1494,6 +1501,7 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib, grow_index_tree(ib, new); return 3; } + next = layout.nextaddr; /* It didn't fit, and this is a regular index block, so * we need to do a horizontal split. * 'new' already has the early addresses. -- 2.39.5