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;
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 */
addr++;
phys++;
}
+ if (i < len)
+ li->nextaddr = addr;
return i;
}
if (li->size < 12) {
/* No room */
dprintk("Extent says 'no room'\n");
+ li->nextaddr = li->lastaddr;
return 0;
}
p = li->data;
* 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.
*/
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 */
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,
/* 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;
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,
*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) {
handled = handle(data, eaddr, ephys, elen2);
if (handled < elen2) {
*bufp = buf - 12;
- return eaddr + handled;
+ return 0;
}
eaddr += elen2;
ephys += elen2;
handled = handle(data, eaddr, ephys, elen);
if (handled < elen) {
*bufp = buf - 12;
- return eaddr + handled;
+ return 0;
}
elen = 0;
}
*bufp = buf;
handle(data, 0, ~(u64)0, 0); /* finalise */
- return 0;
+ return 1;
}
void lafs_walk_leaf_index(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;
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);
}
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
*/
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
}
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",
int current_layout;
struct layoutinfo layout;
u32 next = 0;
+ int ok;
int cr;
ibuf = map_iblock(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
*/
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.