ia64/xen-unstable

changeset 5390:1c2fe32ca700

bitkeeper revision 1.1695 (42a80eb0iCQq47kS2MSpOLTFyng5Cg)

Parallax fixes/updates:
- all data access now through the async lookup code.
- added synchronous wrappers for tools to use.
- added end-to-end crc32 on all image blocks
- various other fixes/cleanups/test stubs.

Signed-off-by: andrew.warfield@cl.cam.ac.uk
author akw27@arcadians.cl.cam.ac.uk
date Thu Jun 09 09:41:04 2005 +0000 (2005-06-09)
parents 949970efef98
children 11dce3390a66
files .rootkeys linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_userdev.c tools/blktap/Makefile tools/blktap/blockstore.c tools/blktap/parallax-threaded.c tools/blktap/parallax-threaded.h tools/blktap/parallax.c tools/blktap/requests-async.c tools/blktap/requests-async.h tools/blktap/snaplog.c tools/blktap/vdi_fill.c tools/blktap/vdi_unittest.c tools/blktap/vdi_validate.c
line diff
     1.1 --- a/.rootkeys	Thu Jun 09 09:20:02 2005 +0000
     1.2 +++ b/.rootkeys	Thu Jun 09 09:41:04 2005 +0000
     1.3 @@ -489,8 +489,6 @@ 42277b02WrfP1meTDPv1M5swFq8oHQ tools/blk
     1.4  42277b02P1C0FYj3gqwTZUD8sxKCug tools/blktap/blockstore.h
     1.5  42371b8aL1JsxAXOd4bBhmZKDyjiJg tools/blktap/blockstored.c
     1.6  42371b8aD_x3L9MKsXciMNqkuk58eQ tools/blktap/bstest.c
     1.7 -423f270cbEKiTMapKnCyqkuwGvgOMA tools/blktap/parallax-threaded.c
     1.8 -423f270cFdXryIcD7HTPUl_Dbk4DAQ tools/blktap/parallax-threaded.h
     1.9  42277b03930x2TJT3PZlw6o0GERXpw tools/blktap/parallax.c
    1.10  42277b03XQYq8bujXSz7JAZ8N7j_pA tools/blktap/radix.c
    1.11  42277b03vZ4-jno_mgKmAcCW3ycRAg tools/blktap/radix.h
    1.12 @@ -507,6 +505,7 @@ 42277b043ZKx0NJSbcgptQctQ5rerg tools/blk
    1.13  423f270c_QDjGLQ_YdaOtyBM5n9BDg tools/blktap/vdi_snap_delete.c
    1.14  42277b043Fjy5-H7LyBtUPyDlZFo6A tools/blktap/vdi_snap_list.c
    1.15  42277b04vhqD6Lq3WmGbaESoAAKdhw tools/blktap/vdi_tree.c
    1.16 +42277b04RnFo07c1LcdmLn-FtRJEmw tools/blktap/vdi_unittest.c
    1.17  42277b047H8fTVyUf75BWAjh6Zpsqg tools/blktap/vdi_validate.c
    1.18  4124b307nRyK3dhn1hAsvrY76NuV3g tools/check/Makefile
    1.19  4124b307vHLUWbfpemVefmaWDcdfag tools/check/README
     2.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Thu Jun 09 09:20:02 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Thu Jun 09 09:41:04 2005 +0000
     2.3 @@ -34,7 +34,7 @@ unsigned long blktap_ring_ok; /* make th
     2.4  static wait_queue_head_t blktap_wait;
     2.5  
     2.6  /* Where things are inside the device mapping. */
     2.7 -struct vm_area_struct *blktap_vma;
     2.8 +struct vm_area_struct *blktap_vma = NULL;
     2.9  unsigned long mmap_vstart;
    2.10  unsigned long rings_vstart;
    2.11  
    2.12 @@ -139,7 +139,14 @@ static int blktap_release(struct inode *
    2.13  
    2.14      ClearPageReserved(virt_to_page(blktap_ube_ring.sring));
    2.15      free_page((unsigned long) blktap_ube_ring.sring);
    2.16 -    
    2.17 +
    2.18 +    /* Clear any active mappings. */
    2.19 +    if (blktap_vma != NULL) {
    2.20 +        zap_page_range(blktap_vma, blktap_vma->vm_start, 
    2.21 +                       blktap_vma->vm_end - blktap_vma->vm_start, NULL);
    2.22 +        blktap_vma = NULL;
    2.23 +    }
    2.24 +
    2.25      return 0;
    2.26  }
    2.27  
     3.1 --- a/tools/blktap/Makefile	Thu Jun 09 09:20:02 2005 +0000
     3.2 +++ b/tools/blktap/Makefile	Thu Jun 09 09:41:04 2005 +0000
     3.3 @@ -15,6 +15,8 @@ INSTALL_DIR     = $(INSTALL) -d -m0755
     3.4  
     3.5  INCLUDES += 
     3.6  
     3.7 +LIBS     := -lpthread -lz
     3.8 +
     3.9  SRCS     :=
    3.10  SRCS     += blktaplib.c
    3.11  
    3.12 @@ -24,10 +26,8 @@ PLX_SRCS += radix.c
    3.13  PLX_SRCS += snaplog.c
    3.14  PLX_SRCS += blockstore.c 
    3.15  PLX_SRCS += block-async.c
    3.16 -PLXT_SRCS := $(PLX_SRCS)
    3.17 -PLXT_SRCS += parallax-threaded.c
    3.18 +PLX_SRCS += requests-async.c
    3.19  VDI_SRCS := $(PLX_SRCS)
    3.20 -PLX_SRCS += requests-async.c
    3.21  PLX_SRCS += parallax.c
    3.22  
    3.23  VDI_TOOLS :=
    3.24 @@ -58,7 +58,7 @@ IBINS    = blkdump parallax $(VDI_TOOLS)
    3.25  
    3.26  LIB      = libblktap.so libblktap.so.$(MAJOR) libblktap.so.$(MAJOR).$(MINOR)
    3.27  
    3.28 -all: mk-symlinks blkdump $(VDI_TOOLS) parallax parallax-threaded blockstored
    3.29 +all: mk-symlinks blkdump $(VDI_TOOLS) parallax blockstored
    3.30  	$(MAKE) $(LIB)
    3.31  
    3.32  LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
    3.33 @@ -80,7 +80,7 @@ install: all
    3.34  	$(INSTALL_PROG) $(IBINS) $(DESTDIR)/$(BLKTAP_INSTALL_DIR)
    3.35  
    3.36  clean:
    3.37 -	rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS blkdump $(VDI_TOOLS) parallax parallax-threaded
    3.38 +	rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS blkdump $(VDI_TOOLS) parallax
    3.39  
    3.40  rpm: all
    3.41  	rm -rf staging
    3.42 @@ -96,45 +96,45 @@ libblktap.so:
    3.43  libblktap.so.$(MAJOR):
    3.44  	ln -sf libblktap.so.$(MAJOR).$(MINOR) $@
    3.45  libblktap.so.$(MAJOR).$(MINOR): $(OBJS)
    3.46 -	$(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ -lpthread -lz
    3.47 +	$(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ $(LIBS)
    3.48  
    3.49  blkdump: $(LIB)
    3.50  	$(CC) $(CFLAGS) -o blkdump -L$(XEN_LIBXC) -L. -l blktap blkdump.c
    3.51  
    3.52  parallax: $(LIB) $(PLX_SRCS)
    3.53 -	$(CC) $(CFLAGS) -o parallax -L$(XEN_LIBXC) -L. -lblktap -lpthread $(PLX_SRCS) 
    3.54 -
    3.55 -parallax-threaded: $(LIB) $(PLXT_SRCS)
    3.56 -	$(CC) $(CFLAGS) -o parallax-threaded -L$(XEN_LIBXC) -L. -lpthread -lblktap $(PLXT_SRCS)
    3.57 +	$(CC) $(CFLAGS) -o parallax -L$(XEN_LIBXC) -L. -lblktap $(LIBS) $(PLX_SRCS) 
    3.58  
    3.59  vdi_list: $(LIB) vdi_list.c $(VDI_SRCS)
    3.60 -	$(CC) $(CFLAGS) -g3 -o vdi_list vdi_list.c -lpthread $(VDI_SRCS)
    3.61 +	$(CC) $(CFLAGS) -g3 -o vdi_list vdi_list.c $(LIBS) $(VDI_SRCS)
    3.62  
    3.63  vdi_create: $(LIB) vdi_create.c $(VDI_SRCS)
    3.64 -	$(CC) $(CFLAGS) -g3 -o vdi_create vdi_create.c -lpthread $(VDI_SRCS)
    3.65 +	$(CC) $(CFLAGS) -g3 -o vdi_create vdi_create.c $(LIBS) $(VDI_SRCS)
    3.66  
    3.67  vdi_snap: $(LIB) vdi_snap.c $(VDI_SRCS)
    3.68 -	$(CC) $(CFLAGS) -g3 -o vdi_snap vdi_snap.c -lpthread $(VDI_SRCS)
    3.69 +	$(CC) $(CFLAGS) -g3 -o vdi_snap vdi_snap.c $(LIBS) $(VDI_SRCS)
    3.70  
    3.71  vdi_snap_list: $(LIB) vdi_snap_list.c $(VDI_SRCS)
    3.72 -	$(CC) $(CFLAGS) -g3 -o vdi_snap_list vdi_snap_list.c -lpthread $(VDI_SRCS)
    3.73 +	$(CC) $(CFLAGS) -g3 -o vdi_snap_list vdi_snap_list.c $(LIBS) $(VDI_SRCS)
    3.74  
    3.75  vdi_snap_delete: $(LIB) vdi_snap_delete.c $(VDI_SRCS)
    3.76 -	$(CC) $(CFLAGS) -g3 -o vdi_snap_delete vdi_snap_delete.c -lpthread $(VDI_SRCS)
    3.77 +	$(CC) $(CFLAGS) -g3 -o vdi_snap_delete vdi_snap_delete.c $(LIBS) $(VDI_SRCS)
    3.78  
    3.79  vdi_tree: $(LIB) vdi_tree.c $(VDI_SRCS)
    3.80 -	$(CC) $(CFLAGS) -g3 -o vdi_tree vdi_tree.c -lpthread $(VDI_SRCS)
    3.81 +	$(CC) $(CFLAGS) -g3 -o vdi_tree vdi_tree.c $(LIBS) $(VDI_SRCS)
    3.82  
    3.83  vdi_fill: $(LIB) vdi_fill.c $(VDI_SRCS)
    3.84 -	$(CC) $(CFLAGS) -g3 -o vdi_fill vdi_fill.c -lpthread $(VDI_SRCS)
    3.85 +	$(CC) $(CFLAGS) -g3 -o vdi_fill vdi_fill.c $(LIBS) $(VDI_SRCS)
    3.86  
    3.87  vdi_validate: $(LIB) vdi_validate.c $(VDI_SRCS)
    3.88 -	$(CC) $(CFLAGS) -g3 -o vdi_validate vdi_validate.c -lpthread $(VDI_SRCS)
    3.89 +	$(CC) $(CFLAGS) -g3 -o vdi_validate vdi_validate.c $(LIBS) $(VDI_SRCS)
    3.90 +
    3.91 +vdi_unittest: $(LIB) vdi_unittest.c $(VDI_SRCS)
    3.92 +	$(CC) $(CFLAGS) -g3 -o vdi_unittest vdi_unittest.c $(LIBS) $(VDI_SRCS)
    3.93  
    3.94  blockstored: blockstored.c
    3.95 -	$(CC) $(CFLAGS) -g3 -o blockstored -lpthread blockstored.c
    3.96 +	$(CC) $(CFLAGS) -g3 -o blockstored $(LIBS) blockstored.c
    3.97  bstest: bstest.c blockstore.c
    3.98 -	$(CC) $(CFLAGS) -g3 -o bstest bstest.c -lpthread blockstore.c
    3.99 +	$(CC) $(CFLAGS) -g3 -o bstest bstest.c $(LIBS) blockstore.c
   3.100  
   3.101  .PHONY: TAGS clean install mk-symlinks rpm
   3.102  TAGS:
     4.1 --- a/tools/blktap/blockstore.c	Thu Jun 09 09:20:02 2005 +0000
     4.2 +++ b/tools/blktap/blockstore.c	Thu Jun 09 09:41:04 2005 +0000
     4.3 @@ -17,7 +17,6 @@
     4.4  #include <stdarg.h>
     4.5  #include "blockstore.h"
     4.6  #include <pthread.h>
     4.7 -#include "parallax-threaded.h"
     4.8  
     4.9  //#define BLOCKSTORE_REMOTE
    4.10  //#define BSDEBUG
     5.1 --- a/tools/blktap/parallax-threaded.c	Thu Jun 09 09:20:02 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,654 +0,0 @@
     5.4 -/**************************************************************************
     5.5 - * 
     5.6 - * parallax.c
     5.7 - *
     5.8 - * The Parallax Storage Server
     5.9 - *
    5.10 - */
    5.11 - 
    5.12 -
    5.13 -#include <stdio.h>
    5.14 -#include <stdlib.h>
    5.15 -#include <string.h>
    5.16 -#include <pthread.h>
    5.17 -#include "blktaplib.h"
    5.18 -#include "blockstore.h"
    5.19 -#include "vdi.h"
    5.20 -#include "parallax-threaded.h"
    5.21 -
    5.22 -#define PARALLAX_DEV     61440
    5.23 -
    5.24 -
    5.25 -#if 0
    5.26 -#define DPRINTF(_f, _a...) printf ( _f , ## _a )
    5.27 -#else
    5.28 -#define DPRINTF(_f, _a...) ((void)0)
    5.29 -#endif
    5.30 -
    5.31 -/* ------[ session records ]----------------------------------------------- */
    5.32 -
    5.33 -#define BLKIF_HASHSZ 1024
    5.34 -#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
    5.35 -
    5.36 -#define VDI_HASHSZ 16
    5.37 -#define VDI_HASH(_vd) ((((_vd)>>8)^(_vd))&(VDI_HASHSZ-1))
    5.38 -
    5.39 -typedef struct blkif {
    5.40 -    domid_t       domid;
    5.41 -    unsigned int  handle;
    5.42 -    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
    5.43 -    vdi_t        *vdi_hash[VDI_HASHSZ];
    5.44 -    struct blkif *hash_next;
    5.45 -} blkif_t;
    5.46 -
    5.47 -static blkif_t      *blkif_hash[BLKIF_HASHSZ];
    5.48 -
    5.49 -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
    5.50 -{
    5.51 -    if ( handle != 0 )
    5.52 -        printf("blktap/parallax don't currently support non-0 dev handles!\n");
    5.53 -    
    5.54 -    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
    5.55 -    while ( (blkif != NULL) && 
    5.56 -            ((blkif->domid != domid) || (blkif->handle != handle)) )
    5.57 -        blkif = blkif->hash_next;
    5.58 -    return blkif;
    5.59 -}
    5.60 -
    5.61 -vdi_t *blkif_get_vdi(blkif_t *blkif, blkif_vdev_t device)
    5.62 -{
    5.63 -    vdi_t *vdi = blkif->vdi_hash[VDI_HASH(device)];
    5.64 -    
    5.65 -    while ((vdi != NULL) && (vdi->vdevice != device))
    5.66 -        vdi = vdi->next;
    5.67 -    
    5.68 -    return vdi;
    5.69 -}
    5.70 -
    5.71 -/* ------[ control message handling ]-------------------------------------- */
    5.72 -
    5.73 -void blkif_create(blkif_be_create_t *create)
    5.74 -{
    5.75 -    domid_t       domid  = create->domid;
    5.76 -    unsigned int  handle = create->blkif_handle;
    5.77 -    blkif_t     **pblkif, *blkif;
    5.78 -
    5.79 -    DPRINTF("parallax (blkif_create): create is %p\n", create); 
    5.80 -    
    5.81 -    if ( (blkif = (blkif_t *)malloc(sizeof(blkif_t))) == NULL )
    5.82 -    {
    5.83 -        DPRINTF("Could not create blkif: out of memory\n");
    5.84 -        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
    5.85 -        return;
    5.86 -    }
    5.87 -
    5.88 -    memset(blkif, 0, sizeof(*blkif));
    5.89 -    blkif->domid  = domid;
    5.90 -    blkif->handle = handle;
    5.91 -    blkif->status = DISCONNECTED;
    5.92 -/*
    5.93 -    spin_lock_init(&blkif->vbd_lock);
    5.94 -    spin_lock_init(&blkif->blk_ring_lock);
    5.95 -    atomic_set(&blkif->refcnt, 0);
    5.96 -*/
    5.97 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
    5.98 -    while ( *pblkif != NULL )
    5.99 -    {
   5.100 -        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
   5.101 -        {
   5.102 -            DPRINTF("Could not create blkif: already exists\n");
   5.103 -            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
   5.104 -            free(blkif);
   5.105 -            return;
   5.106 -        }
   5.107 -        pblkif = &(*pblkif)->hash_next;
   5.108 -    }
   5.109 -
   5.110 -    blkif->hash_next = *pblkif;
   5.111 -    *pblkif = blkif;
   5.112 -
   5.113 -    DPRINTF("Successfully created blkif\n");
   5.114 -    create->status = BLKIF_BE_STATUS_OKAY;
   5.115 -}
   5.116 -
   5.117 -void blkif_destroy(blkif_be_destroy_t *destroy)
   5.118 -{
   5.119 -    domid_t       domid  = destroy->domid;
   5.120 -    unsigned int  handle = destroy->blkif_handle;
   5.121 -    blkif_t     **pblkif, *blkif;
   5.122 -
   5.123 -    DPRINTF("parallax (blkif_destroy): destroy is %p\n", destroy); 
   5.124 -    
   5.125 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
   5.126 -    while ( (blkif = *pblkif) != NULL )
   5.127 -    {
   5.128 -        if ( (blkif->domid == domid) && (blkif->handle == handle) )
   5.129 -        {
   5.130 -            if ( blkif->status != DISCONNECTED )
   5.131 -                goto still_connected;
   5.132 -            goto destroy;
   5.133 -        }
   5.134 -        pblkif = &blkif->hash_next;
   5.135 -    }
   5.136 -
   5.137 -    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   5.138 -    return;
   5.139 -
   5.140 - still_connected:
   5.141 -    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
   5.142 -    return;
   5.143 -
   5.144 - destroy:
   5.145 -    *pblkif = blkif->hash_next;
   5.146 -    /* destroy_all_vbds(blkif); */
   5.147 -    free(blkif);
   5.148 -    destroy->status = BLKIF_BE_STATUS_OKAY;
   5.149 -}
   5.150 -
   5.151 -void vbd_create(blkif_be_vbd_create_t *create)
   5.152 -{
   5.153 -    blkif_t            *blkif;
   5.154 -    vdi_t              *vdi, **vdip;
   5.155 -    blkif_vdev_t        vdevice = create->vdevice;
   5.156 -
   5.157 -    DPRINTF("parallax (vbd_create): create=%p\n", create); 
   5.158 -    
   5.159 -    blkif = blkif_find_by_handle(create->domid, create->blkif_handle);
   5.160 -    if ( blkif == NULL )
   5.161 -    {
   5.162 -        DPRINTF("vbd_create attempted for non-existent blkif (%u,%u)\n", 
   5.163 -                create->domid, create->blkif_handle); 
   5.164 -        create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   5.165 -        return;
   5.166 -    }
   5.167 -
   5.168 -    /* VDI identifier is in grow->extent.sector_start */
   5.169 -    DPRINTF("vbd_create: create->dev_handle (id) is %lx\n", 
   5.170 -            (unsigned long)create->dev_handle);
   5.171 -
   5.172 -    vdi = vdi_get(create->dev_handle);
   5.173 -    if (vdi == NULL)
   5.174 -    {
   5.175 -        printf("parallax (vbd_create): VDI %lx not found.\n",
   5.176 -               (unsigned long)create->dev_handle);
   5.177 -        create->status = BLKIF_BE_STATUS_VBD_NOT_FOUND;
   5.178 -        return;
   5.179 -    }
   5.180 -    
   5.181 -    vdi->next = NULL;
   5.182 -    vdi->vdevice = vdevice;
   5.183 -    vdip = &blkif->vdi_hash[VDI_HASH(vdevice)];
   5.184 -    while (*vdip != NULL)
   5.185 -        vdip = &(*vdip)->next;
   5.186 -    *vdip = vdi;
   5.187 -    
   5.188 -    DPRINTF("vbd_grow: happy return!\n"); 
   5.189 -    create->status = BLKIF_BE_STATUS_OKAY;
   5.190 -}
   5.191 -
   5.192 -int parallax_control(control_msg_t *msg)
   5.193 -{
   5.194 -    domid_t  domid;
   5.195 -    int      ret;
   5.196 -
   5.197 -    DPRINTF("parallax_control: msg is %p\n", msg); 
   5.198 -    
   5.199 -    if (msg->type != CMSG_BLKIF_BE) 
   5.200 -    {
   5.201 -        printf("Unexpected control message (%d)\n", msg->type);
   5.202 -        return 0;
   5.203 -    }
   5.204 -    
   5.205 -    switch(msg->subtype)
   5.206 -    {
   5.207 -    case CMSG_BLKIF_BE_CREATE:
   5.208 -        if ( msg->length != sizeof(blkif_be_create_t) )
   5.209 -            goto parse_error;
   5.210 -        blkif_create((blkif_be_create_t *)msg->msg);
   5.211 -        break;   
   5.212 -        
   5.213 -    case CMSG_BLKIF_BE_DESTROY:
   5.214 -        if ( msg->length != sizeof(blkif_be_destroy_t) )
   5.215 -            goto parse_error;
   5.216 -        blkif_destroy((blkif_be_destroy_t *)msg->msg);
   5.217 -        break;  
   5.218 -        
   5.219 -    case CMSG_BLKIF_BE_VBD_CREATE:
   5.220 -        if ( msg->length != sizeof(blkif_be_vbd_create_t) )
   5.221 -            goto parse_error;
   5.222 -        vbd_create((blkif_be_vbd_create_t *)msg->msg);
   5.223 -        break;
   5.224 -    }
   5.225 -    return 0;
   5.226 -parse_error:
   5.227 -    printf("Bad control message!\n");
   5.228 -    return 0;
   5.229 -    
   5.230 -}    
   5.231 -
   5.232 -int parallax_probe(blkif_request_t *req, blkif_t *blkif)
   5.233 -{
   5.234 -    blkif_response_t *rsp;
   5.235 -    vdisk_t *img_info;
   5.236 -    vdi_t *vdi;
   5.237 -    int i, nr_vdis = 0; 
   5.238 -
   5.239 -    DPRINTF("parallax_probe: req=%p, blkif=%p\n", req, blkif); 
   5.240 -
   5.241 -    /* We expect one buffer only. */
   5.242 -    if ( req->nr_segments != 1 )
   5.243 -      goto err;
   5.244 -
   5.245 -    /* Make sure the buffer is page-sized. */
   5.246 -    if ( (blkif_first_sect(req->frame_and_sects[0]) != 0) ||
   5.247 -       (blkif_last_sect (req->frame_and_sects[0]) != 7) )
   5.248 -      goto err;
   5.249 -
   5.250 -    /* fill the list of devices */
   5.251 -    for (i=0; i<VDI_HASHSZ; i++) {
   5.252 -        vdi = blkif->vdi_hash[i];
   5.253 -        while (vdi) {
   5.254 -            img_info = (vdisk_t *)MMAP_VADDR(ID_TO_IDX(req->id), 0);
   5.255 -            img_info[nr_vdis].device   = vdi->vdevice;
   5.256 -            img_info[nr_vdis].info     = 0;
   5.257 -            /* The -2 here accounts for the LSB in the radix tree */
   5.258 -            img_info[nr_vdis].capacity = 
   5.259 -                    ((1LL << (VDI_HEIGHT-2)) >> SECTOR_SHIFT);
   5.260 -            nr_vdis++;
   5.261 -            vdi = vdi->next;
   5.262 -        }
   5.263 -    }
   5.264 -
   5.265 -    
   5.266 -    rsp = (blkif_response_t *)req;
   5.267 -    rsp->id = req->id;
   5.268 -    rsp->operation = BLKIF_OP_PROBE;
   5.269 -    rsp->status = nr_vdis; /* number of disks */
   5.270 -
   5.271 -    DPRINTF("parallax_probe: send positive response (nr_vdis=%d)\n", nr_vdis);
   5.272 -    return  BLKTAP_RESPOND;
   5.273 -err:
   5.274 -    rsp = (blkif_response_t *)req;
   5.275 -    rsp->id = req->id;
   5.276 -    rsp->operation = BLKIF_OP_PROBE;
   5.277 -    rsp->status = BLKIF_RSP_ERROR;
   5.278 -    
   5.279 -    DPRINTF("parallax_probe: send error response\n"); 
   5.280 -    return BLKTAP_RESPOND;  
   5.281 -}
   5.282 -
   5.283 -typedef struct {
   5.284 -    blkif_request_t *req;
   5.285 -    int              count;
   5.286 -    pthread_mutex_t  mutex;
   5.287 -} pending_t;
   5.288 -
   5.289 -#define MAX_REQUESTS 64
   5.290 -pending_t pending_list[MAX_REQUESTS];
   5.291 -
   5.292 -typedef struct  {
   5.293 -    vdi_t           *vdi;
   5.294 -    blkif_request_t *req;
   5.295 -    int              segment;
   5.296 -    pending_t       *pent;
   5.297 -} readseg_params_t;
   5.298 -
   5.299 -#define DISPATCH_SIZE 1024UL
   5.300 -#define DISPATCH_MASK (DISPATCH_SIZE-1)
   5.301 -readseg_params_t dispatch_list[DISPATCH_SIZE];
   5.302 -unsigned long dprod = 0, dcons = 0;
   5.303 -pthread_mutex_t dispatch_mutex;
   5.304 -pthread_cond_t  dispatch_cond;
   5.305 -
   5.306 -void *read_segment(void *param)
   5.307 -{
   5.308 -    readseg_params_t *p;
   5.309 -    u64 vblock, gblock, sector;
   5.310 -    char *dpage, *spage;
   5.311 -    unsigned long size, start, offset;
   5.312 -    blkif_response_t *rsp;
   5.313 -    int tid;
   5.314 -    
   5.315 -unsigned long dc, dp;
   5.316 -  
   5.317 -#ifdef NOTHREADS
   5.318 -#else
   5.319 -    /* Set this thread's tid. */
   5.320 -    tid = *(int *)param;
   5.321 -    free(param);
   5.322 -
   5.323 -    pthread_setspecific(tid_key, (void *)tid);
   5.324 -
   5.325 -    printf("My tid is %d.\n", (int)pthread_getspecific(tid_key));
   5.326 -start:
   5.327 -    pthread_mutex_lock(&dispatch_mutex);
   5.328 -    while (dprod == dcons)
   5.329 -        pthread_cond_wait(&dispatch_cond, &dispatch_mutex);
   5.330 -    
   5.331 -    if (dprod == dcons) {
   5.332 -        /* unnecessary wakeup. */
   5.333 -        pthread_mutex_unlock(&dispatch_mutex);
   5.334 -        goto start;
   5.335 -    }
   5.336 -#endif
   5.337 -dc = dcons;
   5.338 -dp = dprod;
   5.339 -
   5.340 -    p = &dispatch_list[dcons & DISPATCH_MASK];
   5.341 -    dcons++;
   5.342 -#ifdef NOTHREADS
   5.343 -#else
   5.344 -    pthread_mutex_unlock(&dispatch_mutex);
   5.345 -#endif    
   5.346 -    dpage  = (char *)MMAP_VADDR(ID_TO_IDX(p->req->id), p->segment);
   5.347 -
   5.348 -    /* Round the requested segment to a block address. */
   5.349 -
   5.350 -    sector  = p->req->sector_number + (8*p->segment);
   5.351 -    vblock = (sector << SECTOR_SHIFT) >> BLOCK_SHIFT;
   5.352 -
   5.353 -    /* Get that block from the store. */
   5.354 -
   5.355 -    gblock = vdi_lookup_block(p->vdi, vblock, NULL);
   5.356 -
   5.357 -    /* Calculate read size and offset within the read block. */
   5.358 -
   5.359 -    offset = (sector << SECTOR_SHIFT) % BLOCK_SIZE;
   5.360 -    size = ( blkif_last_sect (p->req->frame_and_sects[p->segment]) -
   5.361 -             blkif_first_sect(p->req->frame_and_sects[p->segment]) + 1
   5.362 -           ) << SECTOR_SHIFT;
   5.363 -    start = blkif_first_sect(p->req->frame_and_sects[p->segment]) 
   5.364 -            << SECTOR_SHIFT;
   5.365 -
   5.366 -    /* If the block does not exist in the store, return zeros. */
   5.367 -    /* Otherwise, copy that region to the guest page.          */
   5.368 -
   5.369 -//    printf("      : (%p, %d, %d) (%d) [c:%lu,p:%lu]\n", 
   5.370 -//            p->req, ID_TO_IDX(p->req->id), p->segment,
   5.371 -//            p->pent->count, dc, dp);
   5.372 -    
   5.373 -    DPRINTF("ParallaxRead: sect: %lld (%ld,%ld),  "
   5.374 -            "vblock %llx, gblock %llx, "
   5.375 -            "size %lx\n", 
   5.376 -            sector, blkif_first_sect(p->req->frame_and_sects[p->segment]),
   5.377 -            blkif_last_sect (p->req->frame_and_sects[p->segment]),
   5.378 -            vblock, gblock, size); 
   5.379 -
   5.380 -    if ( gblock == 0 ) {
   5.381 -
   5.382 -        memset(dpage + start, '\0', size);
   5.383 -
   5.384 -    } else {
   5.385 -
   5.386 -        spage = readblock(gblock);
   5.387 -
   5.388 -        if (spage == NULL) {
   5.389 -            printf("Error reading gblock from store: %Ld\n", gblock);
   5.390 -            goto err;
   5.391 -        }
   5.392 -
   5.393 -        memcpy(dpage + start, spage + offset, size);
   5.394 -
   5.395 -        freeblock(spage);
   5.396 -    }
   5.397 -    
   5.398 -    
   5.399 -    /* Done the read.  Now update the pending record. */
   5.400 -    
   5.401 -    pthread_mutex_lock(&p->pent->mutex);
   5.402 -    p->pent->count--;
   5.403 -    
   5.404 -    if (p->pent->count == 0) {
   5.405 -        
   5.406 -//    printf("FINISH: (%d, %d)\n", ID_TO_IDX(p->req->id), p->segment);
   5.407 -        rsp = (blkif_response_t *)p->req;
   5.408 -        rsp->id = p->req->id;
   5.409 -        rsp->operation = BLKIF_OP_READ;
   5.410 -        rsp->status = BLKIF_RSP_OKAY;
   5.411 -
   5.412 -        blktap_inject_response(rsp);       
   5.413 -    }
   5.414 -    
   5.415 -    pthread_mutex_unlock(&p->pent->mutex);
   5.416 -    
   5.417 -#ifdef NOTHREADS
   5.418 -    return NULL;
   5.419 -#else
   5.420 -    goto start;
   5.421 -#endif
   5.422 -                
   5.423 -err:
   5.424 -    printf("I am screwed!\n");
   5.425 -#ifdef NOTHREADS
   5.426 -    return NULL;
   5.427 -#else
   5.428 -    goto start;
   5.429 -#endif
   5.430 -}
   5.431 -
   5.432 -
   5.433 -int parallax_read(blkif_request_t *req, blkif_t *blkif)
   5.434 -{
   5.435 -    blkif_response_t *rsp;
   5.436 -    unsigned long size, offset, start;
   5.437 -    u64 sector;
   5.438 -    u64 vblock, gblock;
   5.439 -    vdi_t *vdi;
   5.440 -    int i;
   5.441 -    char *dpage, *spage;
   5.442 -    pending_t *pent;
   5.443 -    readseg_params_t *params;
   5.444 -
   5.445 -    vdi = blkif_get_vdi(blkif, req->device);
   5.446 -    
   5.447 -    if ( vdi == NULL )
   5.448 -        goto err;
   5.449 -
   5.450 -//    printf("START : (%p, %d, %d)\n", req, ID_TO_IDX(req->id), req->nr_segments);
   5.451 -    
   5.452 -    pent = &pending_list[ID_TO_IDX(req->id)];
   5.453 -    pent->count = req->nr_segments;
   5.454 -    pent->req = req;
   5.455 -    pthread_mutex_init(&pent->mutex, NULL);
   5.456 -       
   5.457 -    
   5.458 -    for (i = 0; i < req->nr_segments; i++) {
   5.459 -        pthread_t tid;
   5.460 -        int ret;
   5.461 -
   5.462 -        params = &dispatch_list[dprod & DISPATCH_MASK];
   5.463 -        params->pent = pent;
   5.464 -        params->vdi  = vdi;
   5.465 -        params->req  = req;         
   5.466 -        params->segment = i;
   5.467 -        wmb();
   5.468 -        dprod++;
   5.469 -        
   5.470 -        pthread_mutex_lock(&dispatch_mutex);
   5.471 -        pthread_cond_signal(&dispatch_cond);
   5.472 -        pthread_mutex_unlock(&dispatch_mutex);
   5.473 -#ifdef NOTHREADS        
   5.474 -        read_segment(NULL);
   5.475 -#endif        
   5.476 -        
   5.477 -    }
   5.478 -    
   5.479 -    
   5.480 -    
   5.481 -
   5.482 -    return BLKTAP_STOLEN;
   5.483 -
   5.484 -err:
   5.485 -    rsp = (blkif_response_t *)req;
   5.486 -    rsp->id = req->id;
   5.487 -    rsp->operation = BLKIF_OP_READ;
   5.488 -    rsp->status = BLKIF_RSP_ERROR;
   5.489 -    
   5.490 -    return BLKTAP_RESPOND;  
   5.491 -}
   5.492 -
   5.493 -int parallax_write(blkif_request_t *req, blkif_t *blkif)
   5.494 -{
   5.495 -    blkif_response_t *rsp;
   5.496 -    u64 sector;
   5.497 -    int i, writable = 0;
   5.498 -    u64 vblock, gblock;
   5.499 -    char *spage;
   5.500 -    unsigned long size, offset, start;
   5.501 -    vdi_t *vdi;
   5.502 -
   5.503 -    vdi = blkif_get_vdi(blkif, req->device);
   5.504 -    
   5.505 -    if ( vdi == NULL )
   5.506 -        goto err;
   5.507 -    
   5.508 -    for (i = 0; i < req->nr_segments; i++) {
   5.509 -            
   5.510 -        spage  = (char *)MMAP_VADDR(ID_TO_IDX(req->id), i);
   5.511 -        
   5.512 -        /* Round the requested segment to a block address. */
   5.513 -        
   5.514 -        sector  = req->sector_number + (8*i);
   5.515 -        vblock = (sector << SECTOR_SHIFT) >> BLOCK_SHIFT;
   5.516 -        
   5.517 -        /* Get that block from the store. */
   5.518 -        
   5.519 -        gblock   = vdi_lookup_block(vdi, vblock, &writable);
   5.520 -        
   5.521 -        /* Calculate read size and offset within the read block. */
   5.522 -        
   5.523 -        offset = (sector << SECTOR_SHIFT) % BLOCK_SIZE;
   5.524 -        size = ( blkif_last_sect (req->frame_and_sects[i]) -
   5.525 -                 blkif_first_sect(req->frame_and_sects[i]) + 1
   5.526 -               ) << SECTOR_SHIFT;
   5.527 -        start = blkif_first_sect(req->frame_and_sects[i]) << SECTOR_SHIFT;
   5.528 -
   5.529 -        DPRINTF("ParallaxWrite: sect: %lld (%ld,%ld),  "
   5.530 -                "vblock %llx, gblock %llx, "
   5.531 -                "size %lx\n", 
   5.532 -                sector, blkif_first_sect(req->frame_and_sects[i]),
   5.533 -                blkif_last_sect (req->frame_and_sects[i]),
   5.534 -                vblock, gblock, size); 
   5.535 -        
   5.536 -        /* XXX: For now we just freak out if they try to write a   */
   5.537 -        /* non block-sized, block-aligned page.                    */
   5.538 -        
   5.539 -        if ((offset != 0) || (size != BLOCK_SIZE) || (start != 0)) {
   5.540 -            printf("]\n] STRANGE WRITE!\n]\n");
   5.541 -            goto err;
   5.542 -        }
   5.543 -
   5.544 -        if (( gblock == 0 ) || ( writable == 0 )) {
   5.545 -         
   5.546 -            gblock = allocblock(spage);
   5.547 -            vdi_update_block(vdi, vblock, gblock);
   5.548 -            
   5.549 -        } else {
   5.550 -            
   5.551 -            /* write-in-place, no need to change mappings. */
   5.552 -            writeblock(gblock, spage);
   5.553 -            
   5.554 -        }
   5.555 -
   5.556 -    }
   5.557 -
   5.558 -    rsp = (blkif_response_t *)req;
   5.559 -    rsp->id = req->id;
   5.560 -    rsp->operation = BLKIF_OP_WRITE;
   5.561 -    rsp->status = BLKIF_RSP_OKAY;
   5.562 -
   5.563 -    return BLKTAP_RESPOND;
   5.564 -err:
   5.565 -    rsp = (blkif_response_t *)req;
   5.566 -    rsp->id = req->id;
   5.567 -    rsp->operation = BLKIF_OP_WRITE;
   5.568 -    rsp->status = BLKIF_RSP_ERROR;
   5.569 -    
   5.570 -    return BLKTAP_RESPOND;  
   5.571 -}
   5.572 -
   5.573 -int parallax_request(blkif_request_t *req)
   5.574 -{
   5.575 -    blkif_response_t *rsp;
   5.576 -    domid_t  dom   = ID_TO_DOM(req->id);
   5.577 -    blkif_t *blkif = blkif_find_by_handle(dom, 0);
   5.578 -
   5.579 -    //DPRINTF("parallax_request: req=%p, dom=%d, blkif=%p\n", req, dom, blkif); 
   5.580 -    
   5.581 -    if (blkif == NULL)
   5.582 -        goto err;
   5.583 -    
   5.584 -    if ( req->operation == BLKIF_OP_PROBE ) {
   5.585 -        
   5.586 -        return parallax_probe(req, blkif);
   5.587 -        
   5.588 -    } else if ( req->operation == BLKIF_OP_READ ) {
   5.589 -        
   5.590 -        return parallax_read(req, blkif);
   5.591 -        
   5.592 -    } else if ( req->operation == BLKIF_OP_WRITE ) {
   5.593 -        
   5.594 -        return parallax_write(req, blkif);
   5.595 -        
   5.596 -    } else {
   5.597 -        /* Unknown operation */
   5.598 -        goto err;
   5.599 -    }
   5.600 -    
   5.601 -err:
   5.602 -    rsp = (blkif_response_t *)req;
   5.603 -    rsp->id = req->id;
   5.604 -    rsp->operation = req->operation;
   5.605 -    rsp->status = BLKIF_RSP_ERROR;
   5.606 -    return BLKTAP_RESPOND;  
   5.607 -}
   5.608 -
   5.609 -void __init_parallax(void) 
   5.610 -{
   5.611 -    memset(blkif_hash, 0, sizeof(blkif_hash));
   5.612 -}
   5.613 -
   5.614 -
   5.615 -
   5.616 -int main(int argc, char *argv[])
   5.617 -{
   5.618 -    pthread_t read_pool[READ_POOL_SIZE];
   5.619 -    int i, tid=0;
   5.620 -    
   5.621 -    DPRINTF("parallax: starting.\n"); 
   5.622 -    __init_blockstore();
   5.623 -    DPRINTF("parallax: initialized blockstore...\n"); 
   5.624 -    __init_vdi();
   5.625 -    DPRINTF("parallax: initialized vdi registry etc...\n"); 
   5.626 -    __init_parallax();
   5.627 -    DPRINTF("parallax: initialized local stuff..\n"); 
   5.628 -
   5.629 -    
   5.630 -    pthread_mutex_init(&dispatch_mutex, NULL);
   5.631 -    pthread_cond_init(&dispatch_cond, NULL);
   5.632 -    
   5.633 -    pthread_key_create(&tid_key, NULL);
   5.634 -    tid = 0;
   5.635 -    
   5.636 -#ifdef NOTHREADS
   5.637 -#else
   5.638 -    for (i=0; i < READ_POOL_SIZE; i++) {
   5.639 -        int ret, *t;
   5.640 -        t = (int *)malloc(sizeof(int));
   5.641 -        *t = tid++;
   5.642 -        ret = pthread_create(&read_pool[i], NULL, read_segment, t);
   5.643 -        if (ret != 0) printf("Error starting thread %d\n", i);
   5.644 -    }
   5.645 -#endif
   5.646 -    
   5.647 -    pthread_setspecific(tid_key, (void *)tid);
   5.648 -    
   5.649 -    printf("*My tid is %d.\n", (int)pthread_getspecific(tid_key));
   5.650 -    
   5.651 -    blktap_register_ctrl_hook("parallax_control", parallax_control);
   5.652 -    blktap_register_request_hook("parallax_request", parallax_request);
   5.653 -    DPRINTF("parallax: added ctrl + request hooks, starting listen...\n"); 
   5.654 -    blktap_listen();
   5.655 -    
   5.656 -    return 0;
   5.657 -}
     6.1 --- a/tools/blktap/parallax-threaded.h	Thu Jun 09 09:20:02 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,24 +0,0 @@
     6.4 -/**************************************************************************
     6.5 - * 
     6.6 - * parallax-threaded.h
     6.7 - *
     6.8 - * a few thread-specific defines
     6.9 - *
    6.10 - */
    6.11 - 
    6.12 -#ifndef __PARALLAX_THREADED_H__
    6.13 -#define __PARALLAX_THREADED_H__
    6.14 - 
    6.15 -#if 0
    6.16 -/* Turn off threading. */
    6.17 -#define NOTHREADS
    6.18 -#endif
    6.19 -
    6.20 -//#define READ_POOL_SIZE 128
    6.21 -#define READ_POOL_SIZE 8
    6.22 -
    6.23 -/* per-thread identifier */
    6.24 -pthread_key_t tid_key;
    6.25 -
    6.26 -#endif /* __PARALLAX_THREADED_H__ */
    6.27 -
     7.1 --- a/tools/blktap/parallax.c	Thu Jun 09 09:20:02 2005 +0000
     7.2 +++ b/tools/blktap/parallax.c	Thu Jun 09 09:41:04 2005 +0000
     7.3 @@ -427,7 +427,7 @@ int parallax_read(blkif_request_t *req, 
     7.4          p->vblock = vblock; /* dbg */
     7.5          
     7.6          /* Get that block from the store. */
     7.7 -        async_read(vdi, vblock, read_cb, (void *)p);    
     7.8 +        vdi_read(vdi, vblock, read_cb, (void *)p);    
     7.9      }
    7.10      
    7.11      return BLKTAP_STOLEN;
    7.12 @@ -534,7 +534,7 @@ int parallax_write(blkif_request_t *req,
    7.13          p->vblock = vblock; /* dbg */
    7.14          
    7.15          /* Issue the write to the store. */
    7.16 -        async_write(vdi, vblock, spage, write_cb, (void *)p);
    7.17 +        vdi_write(vdi, vblock, spage, write_cb, (void *)p);
    7.18      }
    7.19  
    7.20      return BLKTAP_STOLEN;
    7.21 @@ -595,7 +595,7 @@ int main(int argc, char *argv[])
    7.22      DPRINTF("parallax: starting.\n"); 
    7.23      __init_blockstore();
    7.24      DPRINTF("parallax: initialized blockstore...\n"); 
    7.25 -	init_block_async();
    7.26 +    init_block_async();
    7.27      DPRINTF("parallax: initialized async blocks...\n"); 
    7.28      __init_vdi();
    7.29      DPRINTF("parallax: initialized vdi registry etc...\n"); 
     8.1 --- a/tools/blktap/requests-async.c	Thu Jun 09 09:20:02 2005 +0000
     8.2 +++ b/tools/blktap/requests-async.c	Thu Jun 09 09:41:04 2005 +0000
     8.3 @@ -6,8 +6,11 @@
     8.4  #include <stdio.h>
     8.5  #include <stdlib.h>
     8.6  #include <string.h>
     8.7 +#include <ctype.h>
     8.8  #include <assert.h>
     8.9  #include <pthread.h>
    8.10 +#include <err.h>
    8.11 +#include <zlib.h> /* for crc32() */
    8.12  #include "requests-async.h"
    8.13  #include "vdi.h"
    8.14  #include "radix.h"
    8.15 @@ -23,6 +26,10 @@
    8.16  #define DPRINTF(_f, _a...) ((void)0)
    8.17  #endif
    8.18  
    8.19 +struct block_info {
    8.20 +    u32        crc;
    8.21 +    u32        unused;
    8.22 +};
    8.23  
    8.24  struct io_req {
    8.25      enum { IO_OP_READ, IO_OP_WRITE } op;
    8.26 @@ -34,16 +41,17 @@ struct io_req {
    8.27      struct radix_lock *lock;
    8.28  
    8.29      /* internal stuff: */
    8.30 -    struct io_ret    retval;/* holds the return while we unlock. */
    8.31 -    char            *block; /* the block to write */
    8.32 -    radix_tree_node  radix[3];
    8.33 -    u64              radix_addr[3];
    8.34 +    struct io_ret     retval;/* holds the return while we unlock. */
    8.35 +    char             *block; /* the block to write */
    8.36 +    radix_tree_node   radix[3];
    8.37 +    u64               radix_addr[3];
    8.38 +    struct block_info bi;
    8.39  };
    8.40  
    8.41  void clear_w_bits(radix_tree_node node) 
    8.42  {
    8.43      int i;
    8.44 -    for (i=0; i<RADIX_TREE_MAP_ENTRIES; i++)
    8.45 +    for (i=0; i<RADIX_TREE_MAP_ENTRIES; i+=2)
    8.46          node[i] = node[i] & ONEMASK;
    8.47      return;
    8.48  }
    8.49 @@ -63,6 +71,7 @@ enum states {
    8.50      /* write */
    8.51      WRITE_LOCKED,
    8.52      WRITE_DATA,
    8.53 +    WRITE_L3,
    8.54      WRITE_UNLOCKED,
    8.55      
    8.56      /* L3 Zero Path */
    8.57 @@ -112,18 +121,19 @@ enum radix_offsets {
    8.58  static void read_cb(struct io_ret ret, void *param);
    8.59  static void write_cb(struct io_ret ret, void *param);
    8.60  
    8.61 -
    8.62 -int async_read(vdi_t *vdi, u64 vaddr, io_cb_t cb, void *param)
    8.63 +int vdi_read(vdi_t *vdi, u64 vaddr, io_cb_t cb, void *param)
    8.64  {
    8.65      struct io_req *req;
    8.66  
    8.67 -    DPRINTF("async_read\n");
    8.68 +    if (!VALID_VADDR(vaddr)) return ERR_BAD_VADDR;
    8.69 +    /* Every second line in the bottom-level radix tree is used to      */
    8.70 +    /* store crc32 values etc. We shift the vadder here to achied this. */
    8.71 +    vaddr <<= 1;
    8.72  
    8.73      req = (struct io_req *)malloc(sizeof (struct io_req));
    8.74 -    req->radix[0] = req->radix[1] = req->radix[2] = NULL;
    8.75 +    if (req == NULL) return ERR_NOMEM;
    8.76  
    8.77 -    if (req == NULL) {perror("req was NULL in async_read"); return(-1); }
    8.78 -	
    8.79 +    req->radix[0] = req->radix[1] = req->radix[2] = NULL;	
    8.80      req->op    = IO_OP_READ;
    8.81      req->root  = vdi->radix_root;
    8.82      req->lock  = vdi->radix_lock; 
    8.83 @@ -138,26 +148,35 @@ int async_read(vdi_t *vdi, u64 vaddr, io
    8.84  }
    8.85  
    8.86  
    8.87 -int   async_write(vdi_t *vdi, u64 vaddr, char *block, 
    8.88 -                  io_cb_t cb, void *param)
    8.89 +int   vdi_write(vdi_t *vdi, u64 vaddr, char *block, 
    8.90 +                io_cb_t cb, void *param)
    8.91  {
    8.92      struct io_req *req;
    8.93  
    8.94 +    if (!VALID_VADDR(vaddr)) return ERR_BAD_VADDR;
    8.95 +    /* Every second line in the bottom-level radix tree is used to      */
    8.96 +    /* store crc32 values etc. We shift the vadder here to achied this. */
    8.97 +    vaddr <<= 1;
    8.98  
    8.99      req = (struct io_req *)malloc(sizeof (struct io_req));
   8.100 +    if (req == NULL) return ERR_NOMEM; 
   8.101 +
   8.102      req->radix[0] = req->radix[1] = req->radix[2] = NULL;
   8.103 -    
   8.104 -    if (req == NULL) {perror("req was NULL in async_write"); return(-1); }
   8.105 +    req->op     = IO_OP_WRITE;
   8.106 +    req->root   = vdi->radix_root;
   8.107 +    req->lock   = vdi->radix_lock; 
   8.108 +    req->vaddr  = vaddr;
   8.109 +    req->block  = block;
   8.110 +    /* Todo: add a pseodoheader to the block to include some location   */
   8.111 +    /* information in the CRC as well.                                  */
   8.112 +    req->bi.crc = (u32) crc32(0L, Z_NULL, 0); 
   8.113 +    req->bi.crc = (u32) crc32(req->bi.crc, block, BLOCK_SIZE); 
   8.114 +    req->bi.unused = 0xdeadbeef;
   8.115  
   8.116 -    req->op    = IO_OP_WRITE;
   8.117 -    req->root  = vdi->radix_root;
   8.118 -    req->lock  = vdi->radix_lock; 
   8.119 -    req->vaddr = vaddr;
   8.120 -    req->block = block;
   8.121 -    req->cb    = cb;
   8.122 -    req->param = param;
   8.123 +    req->cb     = cb;
   8.124 +    req->param  = param;
   8.125      req->radix_addr[L1] = getid(req->root); /* for consistency */
   8.126 -    req->state = WRITE_LOCKED;
   8.127 +    req->state  = WRITE_LOCKED;
   8.128  
   8.129      block_wlock(req->lock, L1_IDX(vaddr), write_cb, req);
   8.130  
   8.131 @@ -165,7 +184,7 @@ int   async_write(vdi_t *vdi, u64 vaddr,
   8.132      return 0;
   8.133  }
   8.134  
   8.135 -void read_cb(struct io_ret ret, void *param)
   8.136 +static void read_cb(struct io_ret ret, void *param)
   8.137  {
   8.138      struct io_req *req = (struct io_req *)param;
   8.139      radix_tree_node node;
   8.140 @@ -219,12 +238,16 @@ void read_cb(struct io_ret ret, void *pa
   8.141          break;
   8.142  
   8.143      case READ_L3:
   8.144 -    
   8.145 +    {
   8.146 +        struct block_info *bi;
   8.147 +
   8.148          DPRINTF("READ_L3\n");
   8.149          block = IO_BLOCK(ret);
   8.150          if (block == NULL) goto fail;
   8.151          node = (radix_tree_node) block;
   8.152          idx  = getid( node[L3_IDX(req->vaddr)] );
   8.153 +        bi = (struct block_info *) &node[L3_IDX(req->vaddr) + 1];
   8.154 +        req->bi = *bi;
   8.155          free(block);
   8.156          if ( idx == ZERO )  {
   8.157              req->state = RETURN_ZERO;
   8.158 @@ -234,16 +257,47 @@ void read_cb(struct io_ret ret, void *pa
   8.159              block_read(idx, read_cb, req);
   8.160          }
   8.161          break;
   8.162 -
   8.163 +    }
   8.164      case READ_DATA:
   8.165 -    
   8.166 +    {
   8.167 +        u32 crc;
   8.168 +
   8.169          DPRINTF("READ_DATA\n");
   8.170 -        if (IO_BLOCK(ret) == NULL) goto fail;
   8.171 +        block = IO_BLOCK(ret);
   8.172 +        if (block == NULL) goto fail;
   8.173 +
   8.174 +        /* crc check */
   8.175 +        crc = (u32) crc32(0L, Z_NULL, 0); 
   8.176 +        crc = (u32) crc32(crc, block, BLOCK_SIZE); 
   8.177 +        if (crc != req->bi.crc) {
   8.178 +            /* TODO: add a retry loop here.                          */
   8.179 +            /* Do this after the cache is added -- make sure to      */
   8.180 +            /* invalidate the bad page before reissuing the read.    */
   8.181 +
   8.182 +            warn("Bad CRC on vaddr (%Lu:%d)\n", req->vaddr, req->bi.unused);
   8.183 +#ifdef PRINT_BADCRC_PAGES
   8.184 +            {
   8.185 +                int j;
   8.186 +                for (j=0; j<BLOCK_SIZE; j++) {
   8.187 +                    if isprint(block[j]) {
   8.188 +                        printf("%c", block[j]);
   8.189 +                    } else {
   8.190 +                        printf(".");
   8.191 +                    }
   8.192 +                    if ((j % 64) == 0) printf("\n");
   8.193 +                }
   8.194 +            }
   8.195 +#endif /* PRINT_BADCRC_PAGES */
   8.196 +
   8.197 +            /* fast and loose for the moment. */
   8.198 +            /* goto fail;                     */
   8.199 +        }
   8.200 +
   8.201          req->retval = ret;
   8.202          req->state = READ_UNLOCKED;
   8.203          block_runlock(req->lock, L1_IDX(req->vaddr), read_cb, req);
   8.204          break;
   8.205 -        
   8.206 +    }
   8.207      case READ_UNLOCKED:
   8.208      {
   8.209          struct io_ret r;
   8.210 @@ -293,12 +347,13 @@ void read_cb(struct io_ret ret, void *pa
   8.211  
   8.212  }
   8.213  
   8.214 -void write_cb(struct io_ret r, void *param)
   8.215 +static void write_cb(struct io_ret r, void *param)
   8.216  {
   8.217      struct io_req *req = (struct io_req *)param;
   8.218      radix_tree_node node;
   8.219      u64 a, addr;
   8.220      void *req_param;
   8.221 +    struct block_info *bi;
   8.222  
   8.223      switch(req->state) {
   8.224      	
   8.225 @@ -383,6 +438,19 @@ void write_cb(struct io_ret r, void *par
   8.226          }
   8.227          break;
   8.228      
   8.229 +    case WRITE_DATA:
   8.230 +
   8.231 +        DPRINTF("WRITE_DATA\n");
   8.232 +        /* The L3 radix points to the correct block, we just need to  */
   8.233 +        /* update the crc.                                            */
   8.234 +        if (IO_INT(r) < 0) goto fail;
   8.235 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.236 +        req->bi.unused = 101;
   8.237 +        *bi = req->bi;
   8.238 +        req->state = WRITE_L3;
   8.239 +        block_write(req->radix_addr[L3], (char*)req->radix[L3], write_cb, req);
   8.240 +        break;
   8.241 +    
   8.242      /* L3 Zero Path: */
   8.243  
   8.244      case ALLOC_DATA_L3z:
   8.245 @@ -391,6 +459,9 @@ void write_cb(struct io_ret r, void *par
   8.246          addr = IO_ADDR(r);
   8.247          a = writable(addr);
   8.248          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.249 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.250 +        req->bi.unused = 102;
   8.251 +        *bi = req->bi;
   8.252          req->state = WRITE_L3_L3z;
   8.253          block_write(req->radix_addr[L3], (char*)req->radix[L3], write_cb, req);
   8.254          break;
   8.255 @@ -398,11 +469,14 @@ void write_cb(struct io_ret r, void *par
   8.256      /* L3 Fault Path: */
   8.257  
   8.258      case ALLOC_DATA_L3f:
   8.259 -
   8.260 +    
   8.261          DPRINTF("ALLOC_DATA_L3f\n");
   8.262          addr = IO_ADDR(r);
   8.263          a = writable(addr);
   8.264          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.265 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.266 +        req->bi.unused = 103;
   8.267 +        *bi = req->bi;
   8.268          req->state = WRITE_L3_L3f;
   8.269          block_write(req->radix_addr[L3], (char*)req->radix[L3], write_cb, req);
   8.270          break;
   8.271 @@ -416,6 +490,9 @@ void write_cb(struct io_ret r, void *par
   8.272          a = writable(addr);
   8.273          req->radix[L3] = newblock();
   8.274          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.275 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.276 +        req->bi.unused = 104;
   8.277 +        *bi = req->bi;
   8.278          req->state = ALLOC_L3_L2z;
   8.279          block_alloc( (char*)req->radix[L3], write_cb, req );
   8.280          break;
   8.281 @@ -452,6 +529,9 @@ void write_cb(struct io_ret r, void *par
   8.282          addr = IO_ADDR(r);
   8.283          a = writable(addr);
   8.284          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.285 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.286 +        req->bi.unused = 105;
   8.287 +        *bi = req->bi;
   8.288          req->state = ALLOC_L3_L2f;
   8.289          block_alloc( (char*)req->radix[L3], write_cb, req );
   8.290          break;
   8.291 @@ -475,10 +555,13 @@ void write_cb(struct io_ret r, void *par
   8.292          a = writable(addr);
   8.293          req->radix[L3] = newblock();
   8.294          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.295 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.296 +        req->bi.unused = 106;
   8.297 +        *bi = req->bi;
   8.298          req->state = ALLOC_L3_L1z;
   8.299          block_alloc( (char*)req->radix[L3], write_cb, req );
   8.300          break;
   8.301 -
   8.302 +        
   8.303      case ALLOC_L3_L1z:
   8.304  
   8.305          DPRINTF("ALLOC_L3_L1z\n");
   8.306 @@ -546,6 +629,9 @@ void write_cb(struct io_ret r, void *par
   8.307          addr = IO_ADDR(r);
   8.308          a = writable(addr);
   8.309          req->radix[L3][L3_IDX(req->vaddr)] = a;
   8.310 +        bi  = (struct block_info *) &req->radix[L3][L3_IDX(req->vaddr)+1];
   8.311 +        req->bi.unused = 107;
   8.312 +        *bi = req->bi;
   8.313          req->state = ALLOC_L3_L1f;
   8.314          block_alloc( (char*)req->radix[L3], write_cb, req );
   8.315          break;
   8.316 @@ -570,7 +656,7 @@ void write_cb(struct io_ret r, void *par
   8.317          block_write(req->radix_addr[L1], (char*)req->radix[L1], write_cb, req);
   8.318          break;
   8.319  
   8.320 -    case WRITE_DATA:
   8.321 +    case WRITE_L3:
   8.322      case WRITE_L3_L3z:
   8.323      case WRITE_L3_L3f:
   8.324      case WRITE_L2_L2z:
   8.325 @@ -590,8 +676,8 @@ void write_cb(struct io_ret r, void *par
   8.326      }
   8.327      case WRITE_UNLOCKED:
   8.328      {
   8.329 -		struct io_ret r;
   8.330 -		io_cb_t cb;
   8.331 +        struct io_ret r;
   8.332 +        io_cb_t cb;
   8.333          DPRINTF("WRITE_UNLOCKED!\n");
   8.334          req_param = req->param;
   8.335          r         = req->retval;
   8.336 @@ -612,13 +698,57 @@ void write_cb(struct io_ret r, void *par
   8.337      {
   8.338          struct io_ret r;
   8.339          io_cb_t cb;
   8.340 +        int i;
   8.341 +
   8.342          DPRINTF("asyn_write had a read error mid-way.\n");
   8.343          req_param = req->param;
   8.344          cb        = req->cb;
   8.345          r.type = IO_INT_T;
   8.346          r.u.i  = -1;
   8.347 +        /* free any saved node vals. */
   8.348 +        for (i=0; i<3; i++)
   8.349 +            if (req->radix[i] != 0) free(req->radix[i]);
   8.350          free(req);
   8.351          cb(r, req_param);
   8.352      }
   8.353  }
   8.354  
   8.355 +char *vdi_read_s(vdi_t *vdi, u64 vaddr)
   8.356 +{
   8.357 +    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
   8.358 +    char *block = NULL;
   8.359 +    int ret;
   8.360 +
   8.361 +    void reads_cb(struct io_ret r, void *param) 
   8.362 +    {
   8.363 +        block = IO_BLOCK(r);
   8.364 +        pthread_mutex_unlock((pthread_mutex_t *)param);
   8.365 +    }
   8.366 +
   8.367 +    pthread_mutex_lock(&m);
   8.368 +    ret = vdi_read(vdi, vaddr, reads_cb, &m);
   8.369 +
   8.370 +    if (ret == 0) pthread_mutex_lock(&m);
   8.371 +    
   8.372 +    return block;
   8.373 +}
   8.374 +
   8.375 +
   8.376 +int vdi_write_s(vdi_t *vdi, u64 vaddr, char *block)
   8.377 +{
   8.378 +    pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
   8.379 +    int ret, result;
   8.380 +
   8.381 +    void writes_cb(struct io_ret r, void *param) 
   8.382 +    {
   8.383 +        result = IO_INT(r);
   8.384 +        pthread_mutex_unlock((pthread_mutex_t *)param);
   8.385 +    }
   8.386 +
   8.387 +    pthread_mutex_lock(&m);
   8.388 +    ret = vdi_write(vdi, vaddr, block, writes_cb, &m);
   8.389 +
   8.390 +    if (ret == 0) pthread_mutex_lock(&m);
   8.391 +    
   8.392 +    return result;
   8.393 +}
     9.1 --- a/tools/blktap/requests-async.h	Thu Jun 09 09:20:02 2005 +0000
     9.2 +++ b/tools/blktap/requests-async.h	Thu Jun 09 09:41:04 2005 +0000
     9.3 @@ -13,7 +13,17 @@
     9.4  #define readonly(x) ((u64)((x) << 1))
     9.5  */
     9.6  
     9.7 -int async_read (vdi_t *vdi, u64 vaddr, io_cb_t cb, void *param);
     9.8 -int async_write(vdi_t *vdi, u64 vaddr, char *block, io_cb_t cb, void *param);
     9.9 +#define VADDR_MASK 0x0000000003ffffffLLU /* 26-bits = 256Gig */
    9.10 +#define VALID_VADDR(x) (((x) & VADDR_MASK) == (x))
    9.11 +
    9.12 +int vdi_read (vdi_t *vdi, u64 vaddr, io_cb_t cb, void *param);
    9.13 +int vdi_write(vdi_t *vdi, u64 vaddr, char *block, io_cb_t cb, void *param);
    9.14               
    9.15 +/* synchronous versions: */
    9.16 +char *vdi_read_s (vdi_t *vdi, u64 vaddr);
    9.17 +int   vdi_write_s(vdi_t *vdi, u64 vaddr, char *block);
    9.18 +
    9.19 +#define ERR_BAD_VADDR  -1
    9.20 +#define ERR_NOMEM      -2
    9.21 +
    9.22  #endif //_REQUESTSASYNC_H_
    10.1 --- a/tools/blktap/snaplog.c	Thu Jun 09 09:20:02 2005 +0000
    10.2 +++ b/tools/blktap/snaplog.c	Thu Jun 09 09:41:04 2005 +0000
    10.3 @@ -97,6 +97,7 @@ int __snap_block_create(snap_id_t *paren
    10.4      
    10.5      new_id->index = 0;
    10.6      new_id->block = allocblock(blk);
    10.7 +    freeblock(blk);
    10.8      if (new_id->block == 0)
    10.9          return -1;
   10.10      
    11.1 --- a/tools/blktap/vdi_fill.c	Thu Jun 09 09:20:02 2005 +0000
    11.2 +++ b/tools/blktap/vdi_fill.c	Thu Jun 09 09:41:04 2005 +0000
    11.3 @@ -16,6 +16,7 @@
    11.4  #include <unistd.h>
    11.5  #include "blockstore.h"
    11.6  #include "radix.h"
    11.7 +#include "requests-async.h"
    11.8  #include "vdi.h"
    11.9  
   11.10  int main(int argc, char *argv[])
   11.11 @@ -30,6 +31,7 @@ int main(int argc, char *argv[])
   11.12      u64          vblock = 0, count=0;
   11.13      
   11.14      __init_blockstore();
   11.15 +    init_block_async();
   11.16      __init_vdi();
   11.17      
   11.18      if ( argc < 3 ) {
   11.19 @@ -64,10 +66,7 @@ int main(int argc, char *argv[])
   11.20      printf("%011Ld blocks total\n", tot_size / BLOCK_SIZE);    
   11.21      printf("           ");
   11.22      while ( ( count = read(fd, spage, BLOCK_SIZE) ) > 0 ) {
   11.23 -        u64 gblock = 0;
   11.24 -        
   11.25 -        gblock = allocblock(spage);
   11.26 -        vdi_update_block(vdi, vblock, gblock);
   11.27 +        vdi_write_s(vdi, vblock, spage);
   11.28          
   11.29          vblock++;
   11.30          if ((vblock % 512) == 0)
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/blktap/vdi_unittest.c	Thu Jun 09 09:41:04 2005 +0000
    12.3 @@ -0,0 +1,184 @@
    12.4 +/**************************************************************************
    12.5 + * 
    12.6 + * vdi_unittest.c
    12.7 + *
    12.8 + * Run a small test workload to ensure that data access through a vdi
    12.9 + * is (at least superficially) correct.
   12.10 + *
   12.11 + */
   12.12 + 
   12.13 +#include <stdio.h>
   12.14 +#include <stdlib.h>
   12.15 +#include <string.h>
   12.16 +#include <sys/types.h>
   12.17 +#include <sys/stat.h>
   12.18 +#include <fcntl.h>
   12.19 +#include <unistd.h>
   12.20 +#include "requests-async.h"
   12.21 +#include "blockstore.h"
   12.22 +#include "radix.h"
   12.23 +#include "vdi.h"
   12.24 +
   12.25 +#define TEST_PAGES  32
   12.26 +static char *zero_page;
   12.27 +static char pages[TEST_PAGES][BLOCK_SIZE];
   12.28 +static int next_page = 0;
   12.29 +
   12.30 +void fill_test_pages(void)
   12.31 +{
   12.32 +    int i, j;
   12.33 +    long *page;
   12.34 +
   12.35 +    for (i=0; i< TEST_PAGES; i++) {
   12.36 +        page = (unsigned long *)pages[i];
   12.37 +        for (j=0; j<(BLOCK_SIZE/4); j++) {
   12.38 +            page[j] = random();
   12.39 +        }
   12.40 +    }
   12.41 +
   12.42 +    zero_page = newblock();
   12.43 +}
   12.44 +
   12.45 +inline u64 make_vaddr(u64 L1, u64 L2, u64 L3)
   12.46 +{
   12.47 +    u64 ret = L1;
   12.48 +
   12.49 +    ret = (ret << 9) | L2;
   12.50 +    ret = (ret << 9) | L3;
   12.51 +
   12.52 +    return ret;
   12.53 +}
   12.54 +
   12.55 +void touch_block(vdi_t *vdi, u64 L1, u64 L2, u64 L3)
   12.56 +{
   12.57 +    u64 vaddr;
   12.58 +    char *page = pages[next_page++];
   12.59 +    char *rpage = NULL;
   12.60 +
   12.61 +    printf("TOUCH (%3Lu, %3Lu, %3Lu)\n", L1, L2, L3);
   12.62 +
   12.63 +    vaddr = make_vaddr(L1, L2, L3);
   12.64 +    vdi_write_s(vdi, vaddr, page);
   12.65 +    rpage = vdi_read_s(vdi, vaddr);
   12.66 +
   12.67 +    if (rpage == NULL) 
   12.68 +    {
   12.69 +        printf( "read %Lu returned NULL\n", vaddr); 
   12.70 +        return; 
   12.71 +    }
   12.72 +
   12.73 +    if (memcmp(page, rpage, BLOCK_SIZE) != 0)
   12.74 +    {
   12.75 +        printf( "read %Lu returned a different page\n", vaddr);
   12.76 +        return;
   12.77 +    }
   12.78 +
   12.79 +    freeblock(rpage);
   12.80 +}
   12.81 +
   12.82 +void test_block(vdi_t *vdi, u64 L1, u64 L2, u64 L3, char *page)
   12.83 +{
   12.84 +    u64 vaddr;
   12.85 +    char *rpage = NULL;
   12.86 +
   12.87 +    printf("TEST  (%3Lu, %3Lu, %3Lu)\n", L1, L2, L3);
   12.88 +
   12.89 +    vaddr = make_vaddr(L1, L2, L3);
   12.90 +    rpage = vdi_read_s(vdi, vaddr);
   12.91 +
   12.92 +    if (rpage == NULL) 
   12.93 +    {
   12.94 +        printf( "read %Lu returned NULL\n", vaddr); 
   12.95 +        return; 
   12.96 +    }
   12.97 +
   12.98 +    if (memcmp(page, rpage, BLOCK_SIZE) != 0)
   12.99 +    {
  12.100 +        printf( "read %Lu returned a different page\n", vaddr);
  12.101 +        return;
  12.102 +    }
  12.103 +
  12.104 +    freeblock(rpage);
  12.105 +}
  12.106 +
  12.107 +void coverage_test(vdi_t *vdi)
  12.108 +{
  12.109 +    u64 vaddr;
  12.110 +    int i, j, k;
  12.111 +
  12.112 +    /* Do a series of writes and reads to test all paths through the 
  12.113 +     * async radix code.  The radix request code will dump CRC warnings
  12.114 +     * if there are data problems here as well.
  12.115 +     */
  12.116 +
  12.117 +    /* L1 Zero */
  12.118 +    touch_block(vdi, 0, 0, 0);
  12.119 +
  12.120 +    /* L2 Zero */
  12.121 +    i = next_page;
  12.122 +    touch_block(vdi, 0, 1, 0);
  12.123 +
  12.124 +    /* L3 Zero */
  12.125 +    j = next_page;
  12.126 +    touch_block(vdi, 0, 0, 1);
  12.127 +    k = next_page;
  12.128 +    touch_block(vdi, 0, 1, 1);
  12.129 +
  12.130 +    /* Direct write */
  12.131 +    touch_block(vdi, 0, 0, 0);
  12.132 +
  12.133 +    vdi_snapshot(vdi);
  12.134 +
  12.135 +    /* L1 fault */
  12.136 +    touch_block(vdi, 0, 0, 0);
  12.137 +    /* test the read-only branches that should have been copied over. */
  12.138 +    test_block(vdi, 0, 1, 0, pages[i]);
  12.139 +    test_block(vdi, 0, 0, 1, pages[j]);
  12.140 +
  12.141 +    /* L2 fault */
  12.142 +    touch_block(vdi, 0, 1, 0);
  12.143 +    test_block(vdi, 0, 1, 1, pages[k]);
  12.144 +
  12.145 +    /* L3 fault */
  12.146 +    touch_block(vdi, 0, 0, 1);
  12.147 +    
  12.148 +    /* read - L1 zero */
  12.149 +    test_block(vdi, 1, 0, 0, zero_page);
  12.150 +    
  12.151 +    /* read - L2 zero */
  12.152 +    test_block(vdi, 0, 2, 0, zero_page);
  12.153 +
  12.154 +    /* read - L3 zero */
  12.155 +    test_block(vdi, 0, 0, 2, zero_page);
  12.156 +}
  12.157 +
  12.158 +int main(int argc, char *argv[])
  12.159 +{
  12.160 +    vdi_t       *vdi;
  12.161 +    u64          id;
  12.162 +    int          fd;
  12.163 +    struct stat  st;
  12.164 +    u64          tot_size;
  12.165 +    char         spage[BLOCK_SIZE];
  12.166 +    char        *dpage;
  12.167 +    u64          vblock = 0, count=0;
  12.168 +    
  12.169 +    __init_blockstore();
  12.170 +    init_block_async();
  12.171 +    __init_vdi();
  12.172 +        
  12.173 +    vdi = vdi_create( NULL, "UNIT TEST VDI");
  12.174 +    
  12.175 +    if ( vdi == NULL ) {
  12.176 +        printf("Failed to create VDI!\n");
  12.177 +        freeblock(vdi);
  12.178 +        exit(-1);
  12.179 +    }
  12.180 +
  12.181 +    fill_test_pages();
  12.182 +    coverage_test(vdi);
  12.183 +    
  12.184 +    freeblock(vdi);
  12.185 +    
  12.186 +    return (0);
  12.187 +}
    13.1 --- a/tools/blktap/vdi_validate.c	Thu Jun 09 09:20:02 2005 +0000
    13.2 +++ b/tools/blktap/vdi_validate.c	Thu Jun 09 09:41:04 2005 +0000
    13.3 @@ -18,6 +18,7 @@
    13.4  #include "blockstore.h"
    13.5  #include "radix.h"
    13.6  #include "vdi.h"
    13.7 +#include "requests-async.h"
    13.8  
    13.9  int main(int argc, char *argv[])
   13.10  {
   13.11 @@ -31,6 +32,7 @@ int main(int argc, char *argv[])
   13.12      u64          vblock = 0, count=0;
   13.13      
   13.14      __init_blockstore();
   13.15 +    init_block_async();
   13.16      __init_vdi();
   13.17      
   13.18      if ( argc < 3 ) {
   13.19 @@ -64,17 +66,14 @@ int main(int argc, char *argv[])
   13.20      
   13.21      printf("           ");
   13.22      while ( ( count = read(fd, spage, BLOCK_SIZE) ) > 0 ) {
   13.23 -        u64 gblock = 0;
   13.24 -        
   13.25 -        gblock = vdi_lookup_block(vdi, vblock, NULL);
   13.26 -        
   13.27 -        if (gblock == 0) {
   13.28 +
   13.29 +        dpage = vdi_read_s(vdi, vblock);
   13.30 +
   13.31 +        if (dpage == NULL) {
   13.32              printf("\n\nfound an unmapped VDI block (%Ld)\n", vblock);
   13.33              exit(0);
   13.34          }
   13.35 -        
   13.36 -        dpage = readblock(gblock);
   13.37 -        
   13.38 +
   13.39          if (memcmp(spage, dpage, BLOCK_SIZE) != 0) {
   13.40              printf("\n\nblocks don't match! (%Ld)\n", vblock);
   13.41              exit(0);
   13.42 @@ -83,8 +82,10 @@ int main(int argc, char *argv[])
   13.43          freeblock(dpage);
   13.44          
   13.45          vblock++;
   13.46 -        printf("\b\b\b\b\b\b\b\b\b\b\b%011Ld", vblock);
   13.47 -        fflush(stdout);
   13.48 +        if ((vblock % 1024) == 0) {
   13.49 +            printf("\b\b\b\b\b\b\b\b\b\b\b%011Ld", vblock);
   13.50 +            fflush(stdout);
   13.51 +        }
   13.52      }
   13.53      printf("\n");
   13.54