ia64/xen-unstable

changeset 3421:70b803ca7d24

bitkeeper revision 1.1159.219.1 (41e4eca6eauLGi5osqpDb_OmwLgatA)

Some fixes and cleanups to the blktap code.
author akw27@labyrinth.cl.cam.ac.uk
date Wed Jan 12 09:23:50 2005 +0000 (2005-01-12)
parents eceb1ecd0973
children 671aaec9d333
files linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c
line diff
     1.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c	Sat Jan 08 17:38:59 2005 +0000
     1.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c	Wed Jan 12 09:23:50 2005 +0000
     1.3 @@ -41,9 +41,9 @@ int __init xlblk_init(void)
     1.4      DPRINTK("   tap - Frontend connection init:\n");
     1.5      
     1.6      active_reqs_init();
     1.7 +    blkif_interface_init();
     1.8 +    blkdev_schedule_init();
     1.9      
    1.10 -    ptfe_blkif.status = DISCONNECTED;
    1.11 -
    1.12      (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
    1.13                                      CALLBACK_IN_BLOCKING_CONTEXT);
    1.14  
     2.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h	Sat Jan 08 17:38:59 2005 +0000
     2.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h	Wed Jan 12 09:23:50 2005 +0000
     2.3 @@ -23,23 +23,32 @@
     2.4  #include <asm/pgalloc.h>
     2.5  #include <asm-xen/hypervisor.h>
     2.6  #include <asm-xen/xen-public/io/blkif.h>
     2.7 +#include <asm-xen/xen-public/io/ring.h>
     2.8 +
     2.9 +/* Used to signal to the backend that this is a tap domain. */
    2.10 +#define BLKTAP_COOKIE 0xbeadfeed
    2.11  
    2.12  /* -------[ debug / pretty printing ]--------------------------------- */
    2.13  
    2.14  #if 0
    2.15 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
    2.16 +                           __FILE__ , __LINE__ , ## _a )
    2.17 +#else
    2.18 +#define DPRINTK(_f, _a...) ((void)0)
    2.19 +#endif
    2.20 +
    2.21 +#if 1
    2.22  #define ASSERT(_p) \
    2.23      if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
    2.24      __LINE__, __FILE__); *(int*)0=0; }
    2.25 -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
    2.26 -                           __FILE__ , __LINE__ , ## _a )
    2.27  #else
    2.28  #define ASSERT(_p) ((void)0)
    2.29 -#define DPRINTK(_f, _a...) ((void)0)
    2.30  #endif
    2.31  
    2.32  #define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
    2.33  
    2.34 -/* -------[ connection / request tracking ]--------------------------- */
    2.35 +
    2.36 +/* -------[ connection tracking ]------------------------------------- */
    2.37  
    2.38  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    2.39  #define VMALLOC_VMADDR(x) ((unsigned long)(x))
    2.40 @@ -49,30 +58,40 @@ extern spinlock_t blkif_io_lock;
    2.41  
    2.42  typedef struct blkif_st {
    2.43      /* Unique identifier for this interface. */
    2.44 -    domid_t          domid;
    2.45 -    unsigned int     handle;
    2.46 +    domid_t             domid;
    2.47 +    unsigned int        handle;
    2.48      /* Physical parameters of the comms window. */
    2.49 -    unsigned long    shmem_frame;
    2.50 -    unsigned int     evtchn;
    2.51 -    int              irq;
    2.52 +    unsigned long       shmem_frame;
    2.53 +    unsigned int        evtchn;
    2.54 +    int                 irq;
    2.55      /* Comms information. */
    2.56 -    blkif_ring_t    *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */
    2.57 -    BLKIF_RING_IDX     blk_req_cons;  /* Request consumer. */
    2.58 -    BLKIF_RING_IDX     blk_resp_prod; /* Private version of resp. producer. */
    2.59 +    blkif_back_ring_t   blk_ring;
    2.60      
    2.61      enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
    2.62      /*
    2.63       * DISCONNECT response is deferred until pending requests are ack'ed.
    2.64       * We therefore need to store the id from the original request.
    2.65 -     */    u8               disconnect_rspid;
    2.66 -    struct blkif_st *hash_next;
    2.67 -    struct list_head blkdev_list;
    2.68 -    spinlock_t       blk_ring_lock;
    2.69 -    atomic_t         refcnt;
    2.70 -    
    2.71 +     */    
    2.72 +    u8                  disconnect_rspid;
    2.73 +    struct blkif_st    *hash_next;
    2.74 +    struct list_head    blkdev_list;
    2.75 +    spinlock_t          blk_ring_lock;
    2.76 +    atomic_t            refcnt;
    2.77      struct work_struct work;
    2.78  } blkif_t;
    2.79  
    2.80 +blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
    2.81 +void blkif_disconnect_complete(blkif_t *blkif);
    2.82 +#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
    2.83 +#define blkif_put(_b)                             \
    2.84 +    do {                                          \
    2.85 +        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
    2.86 +            blkif_disconnect_complete(_b);        \
    2.87 +    } while (0)
    2.88 +
    2.89 +
    2.90 +/* -------[ active request tracking ]--------------------------------- */
    2.91 +
    2.92  typedef struct {
    2.93      blkif_t       *blkif;
    2.94      unsigned long  id;
    2.95 @@ -80,48 +99,16 @@ typedef struct {
    2.96      unsigned long  mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    2.97      unsigned long  virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
    2.98      int            next_free;
    2.99 +    int inuse; /* debugging */
   2.100  } active_req_t;
   2.101  
   2.102 -
   2.103 -/* -------[ block ring structs ]-------------------------------------- */
   2.104 -
   2.105 -/* Types of ring. */
   2.106 -#define BLKIF_REQ_RING_TYPE 1
   2.107 -#define BLKIF_RSP_RING_TYPE 2
   2.108 -
   2.109 -/* generic ring struct. */
   2.110 -typedef struct blkif_generic_ring_struct {
   2.111 -    int type;
   2.112 -} blkif_generic_ring_t;
   2.113 -
   2.114 -/* A requestor's view of a ring. */
   2.115 -typedef struct blkif_req_ring_struct {
   2.116 -
   2.117 -    int type;                    /* Will be BLKIF_REQ_RING_TYPE        */
   2.118 -    BLKIF_RING_IDX req_prod;     /* PRIVATE req_prod index             */
   2.119 -    BLKIF_RING_IDX rsp_cons;     /* Response consumer index            */
   2.120 -    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
   2.121 +typedef unsigned int ACTIVE_RING_IDX;
   2.122  
   2.123 -} blkif_req_ring_t;
   2.124 -
   2.125 -#define BLKIF_REQ_RING_INIT { BLKIF_REQ_RING_TYPE, 0, 0, 0 }
   2.126 -
   2.127 -/* A responder's view of a ring. */
   2.128 -typedef struct blkif_rsp_ring_struct {
   2.129 +active_req_t *lookup_active_req(ACTIVE_RING_IDX idx);
   2.130 +inline unsigned int ID_TO_IDX(unsigned long id);
   2.131 +inline domid_t ID_TO_DOM(unsigned long id);
   2.132  
   2.133 -    int type;       
   2.134 -    BLKIF_RING_IDX rsp_prod;     /* PRIVATE rsp_prod index             */
   2.135 -    BLKIF_RING_IDX req_cons;     /* Request consumer index             */
   2.136 -    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
   2.137 -
   2.138 -} blkif_rsp_ring_t;
   2.139 -
   2.140 -#define BLKIF_RSP_RING_INIT = { BLKIF_RSP_RING_TYPE, 0, 0, 0 }
   2.141 -
   2.142 -#define RING(a) (blkif_generic_ring_t *)(a)
   2.143 -
   2.144 -inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring);
   2.145 -
   2.146 +inline void active_reqs_init(void);
   2.147  
   2.148  /* -------[ interposition -> character device interface ]------------- */
   2.149  
   2.150 @@ -135,6 +122,7 @@ inline int BLKTAP_RING_FULL(blkif_generi
   2.151  #define BLKTAP_IOCTL_KICK_FE         1
   2.152  #define BLKTAP_IOCTL_KICK_BE         2
   2.153  #define BLKTAP_IOCTL_SETMODE         3
   2.154 +#define BLKTAP_IOCTL_PRINT_IDXS      100  
   2.155  
   2.156  /* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
   2.157  #define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
   2.158 @@ -196,22 +184,12 @@ extern unsigned long mmap_vstart;
   2.159  #define RING_PAGES 128 
   2.160  extern unsigned long rings_vstart;
   2.161  
   2.162 +
   2.163  /* -------[ Here be globals ]----------------------------------------- */
   2.164 -
   2.165  extern unsigned long blktap_mode;
   2.166  
   2.167 -
   2.168 -/* blkif struct, containing ring to FE domain */
   2.169 -extern blkif_t ptfe_blkif; 
   2.170 -
   2.171  /* Connection to a single backend domain. */
   2.172 -extern blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
   2.173 -extern BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
   2.174 -extern BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
   2.175 -
   2.176 -/* Rings up to user space. */ 
   2.177 -extern blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
   2.178 -extern blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
   2.179 +extern blkif_front_ring_t blktap_be_ring;
   2.180  
   2.181  /* Event channel to backend domain. */
   2.182  extern unsigned int blkif_ptbe_evtchn;
   2.183 @@ -224,10 +202,13 @@ extern unsigned long blktap_ring_ok;
   2.184  /* init function for character device interface.                       */
   2.185  int blktap_init(void);
   2.186  
   2.187 +/* init function for the blkif cache. */
   2.188 +void __init blkif_interface_init(void);
   2.189 +void __init blkdev_schedule_init(void);
   2.190 +void blkif_deschedule(blkif_t *blkif);
   2.191 +
   2.192  /* interfaces to the char driver, passing messages to and from apps.   */
   2.193  void blktap_kick_user(void);
   2.194 -int blktap_write_to_ring(blkif_request_t *req);
   2.195 -
   2.196  
   2.197  /* user ring access functions: */
   2.198  int blktap_write_fe_ring(blkif_request_t *req);
   2.199 @@ -235,11 +216,12 @@ int blktap_write_be_ring(blkif_response_
   2.200  int blktap_read_fe_ring(void);
   2.201  int blktap_read_be_ring(void);
   2.202  
   2.203 -/* and the helpers they call: */
   2.204 -inline int write_resp_to_fe_ring(blkif_response_t *rsp);
   2.205 -inline void kick_fe_domain(void);
   2.206 +/* fe/be ring access functions: */
   2.207 +int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp);
   2.208 +int write_req_to_be_ring(blkif_request_t *req);
   2.209  
   2.210 -inline int write_req_to_be_ring(blkif_request_t *req);
   2.211 +/* event notification functions */
   2.212 +inline void kick_fe_domain(blkif_t *blkif);
   2.213  inline void kick_be_domain(void);
   2.214  
   2.215  /* Interrupt handlers. */
   2.216 @@ -250,5 +232,8 @@ irqreturn_t blkif_ptfe_int(int irq, void
   2.217  /* Control message receiver. */
   2.218  extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
   2.219  
   2.220 +/* debug */
   2.221 +void print_vm_ring_idxs(void);
   2.222 +        
   2.223  #define __BLKINT_H__
   2.224  #endif
     3.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c	Sat Jan 08 17:38:59 2005 +0000
     3.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c	Wed Jan 12 09:23:50 2005 +0000
     3.3 @@ -32,10 +32,71 @@ unsigned int blkif_ptbe_evtchn;
     3.4  
     3.5  /*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
     3.6  
     3.7 +#define BLKIF_HASHSZ 1024
     3.8 +#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
     3.9 +
    3.10 +static kmem_cache_t *blkif_cachep;
    3.11 +static blkif_t      *blkif_hash[BLKIF_HASHSZ];
    3.12 +
    3.13 +blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
    3.14 +{
    3.15 +    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
    3.16 +    while ( (blkif != NULL) && 
    3.17 +            ((blkif->domid != domid) || (blkif->handle != handle)) )
    3.18 +        blkif = blkif->hash_next;
    3.19 +    return blkif;
    3.20 +}
    3.21 +
    3.22 +static void __blkif_disconnect_complete(void *arg)
    3.23 +{
    3.24 +    blkif_t              *blkif = (blkif_t *)arg;
    3.25 +    ctrl_msg_t            cmsg;
    3.26 +    blkif_be_disconnect_t disc;
    3.27 +
    3.28 +    /*
    3.29 +     * These can't be done in blkif_disconnect() because at that point there
    3.30 +     * may be outstanding requests at the disc whose asynchronous responses
    3.31 +     * must still be notified to the remote driver.
    3.32 +     */
    3.33 +    unbind_evtchn_from_irq(blkif->evtchn);
    3.34 +    vfree(blkif->blk_ring.sring);
    3.35 +
    3.36 +    /* Construct the deferred response message. */
    3.37 +    cmsg.type         = CMSG_BLKIF_BE;
    3.38 +    cmsg.subtype      = CMSG_BLKIF_BE_DISCONNECT;
    3.39 +    cmsg.id           = blkif->disconnect_rspid;
    3.40 +    cmsg.length       = sizeof(blkif_be_disconnect_t);
    3.41 +    disc.domid        = blkif->domid;
    3.42 +    disc.blkif_handle = blkif->handle;
    3.43 +    disc.status       = BLKIF_BE_STATUS_OKAY;
    3.44 +    memcpy(cmsg.msg, &disc, sizeof(disc));
    3.45 +
    3.46 +    /*
    3.47 +     * Make sure message is constructed /before/ status change, because
    3.48 +     * after the status change the 'blkif' structure could be deallocated at
    3.49 +     * any time. Also make sure we send the response /after/ status change,
    3.50 +     * as otherwise a subsequent CONNECT request could spuriously fail if
    3.51 +     * another CPU doesn't see the status change yet.
    3.52 +     */
    3.53 +    mb();
    3.54 +    if ( blkif->status != DISCONNECTING )
    3.55 +        BUG();
    3.56 +    blkif->status = DISCONNECTED;
    3.57 +    mb();
    3.58 +
    3.59 +    /* Send the successful response. */
    3.60 +    ctrl_if_send_response(&cmsg);
    3.61 +}
    3.62 +
    3.63 +void blkif_disconnect_complete(blkif_t *blkif)
    3.64 +{
    3.65 +    INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
    3.66 +    schedule_work(&blkif->work);
    3.67 +}
    3.68  
    3.69  void blkif_ptfe_create(blkif_be_create_t *create)
    3.70  {
    3.71 -    blkif_t      *blkif;
    3.72 +    blkif_t      *blkif, **pblkif;
    3.73      domid_t       domid  = create->domid;
    3.74      unsigned int  handle = create->blkif_handle;
    3.75  
    3.76 @@ -43,16 +104,38 @@ void blkif_ptfe_create(blkif_be_create_t
    3.77      /* May want to store info on the connecting domain here. */
    3.78  
    3.79      DPRINTK("PT got BE_CREATE\n");
    3.80 -    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
    3.81 +
    3.82 +    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
    3.83 +    {
    3.84 +        DPRINTK("Could not create blkif: out of memory\n");
    3.85 +        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
    3.86 +        return;
    3.87 +    }
    3.88  
    3.89      /* blkif struct init code from blkback.c */
    3.90      memset(blkif, 0, sizeof(*blkif));
    3.91      blkif->domid  = domid;
    3.92      blkif->handle = handle;
    3.93 -    blkif->status = DISCONNECTED;    
    3.94 +    blkif->status = DISCONNECTED;  
    3.95      spin_lock_init(&blkif->blk_ring_lock);
    3.96      atomic_set(&blkif->refcnt, 0);
    3.97  
    3.98 +    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
    3.99 +    while ( *pblkif != NULL )
   3.100 +    {
   3.101 +        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
   3.102 +        {
   3.103 +            DPRINTK("Could not create blkif: already exists\n");
   3.104 +            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
   3.105 +            kmem_cache_free(blkif_cachep, blkif);
   3.106 +            return;
   3.107 +        }
   3.108 +        pblkif = &(*pblkif)->hash_next;
   3.109 +    }
   3.110 +
   3.111 +    blkif->hash_next = *pblkif;
   3.112 +    *pblkif = blkif;
   3.113 +
   3.114      create->status = BLKIF_BE_STATUS_OKAY;
   3.115  }
   3.116  
   3.117 @@ -61,24 +144,59 @@ void blkif_ptfe_destroy(blkif_be_destroy
   3.118  {
   3.119      /* Clear anything that we initialized above. */
   3.120  
   3.121 +    domid_t       domid  = destroy->domid;
   3.122 +    unsigned int  handle = destroy->blkif_handle;
   3.123 +    blkif_t     **pblkif, *blkif;
   3.124 +
   3.125      DPRINTK("PT got BE_DESTROY\n");
   3.126 +    
   3.127 +    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
   3.128 +    while ( (blkif = *pblkif) != NULL )
   3.129 +    {
   3.130 +        if ( (blkif->domid == domid) && (blkif->handle == handle) )
   3.131 +        {
   3.132 +            if ( blkif->status != DISCONNECTED )
   3.133 +                goto still_connected;
   3.134 +            goto destroy;
   3.135 +        }
   3.136 +        pblkif = &blkif->hash_next;
   3.137 +    }
   3.138 +
   3.139 +    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   3.140 +    return;
   3.141 +
   3.142 + still_connected:
   3.143 +    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
   3.144 +    return;
   3.145 +
   3.146 + destroy:
   3.147 +    *pblkif = blkif->hash_next;
   3.148 +    kmem_cache_free(blkif_cachep, blkif);
   3.149      destroy->status = BLKIF_BE_STATUS_OKAY;
   3.150  }
   3.151  
   3.152  void blkif_ptfe_connect(blkif_be_connect_t *connect)
   3.153  {
   3.154 -    domid_t       domid  = connect->domid;
   3.155 -    /*unsigned int  handle = connect->blkif_handle;*/
   3.156 -    unsigned int  evtchn = connect->evtchn;
   3.157 -    unsigned long shmem_frame = connect->shmem_frame;
   3.158 +    domid_t        domid  = connect->domid;
   3.159 +    unsigned int   handle = connect->blkif_handle;
   3.160 +    unsigned int   evtchn = connect->evtchn;
   3.161 +    unsigned long  shmem_frame = connect->shmem_frame;
   3.162      struct vm_struct *vma;
   3.163 -    pgprot_t      prot;
   3.164 -    int           error;
   3.165 -    blkif_t      *blkif;
   3.166 +    pgprot_t       prot;
   3.167 +    int            error;
   3.168 +    blkif_t       *blkif;
   3.169 +    blkif_sring_t *sring;
   3.170  
   3.171      DPRINTK("PT got BE_CONNECT\n");
   3.172  
   3.173 -    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
   3.174 +    blkif = blkif_find_by_handle(domid, handle);
   3.175 +    if ( unlikely(blkif == NULL) )
   3.176 +    {
   3.177 +        DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", 
   3.178 +                connect->domid, connect->blkif_handle); 
   3.179 +        connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   3.180 +        return;
   3.181 +    }
   3.182  
   3.183      if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   3.184      {
   3.185 @@ -112,30 +230,51 @@ void blkif_ptfe_connect(blkif_be_connect
   3.186          return;
   3.187      }
   3.188  
   3.189 +    sring = (blkif_sring_t *)vma->addr;
   3.190 +    SHARED_RING_INIT(BLKIF_RING, sring);
   3.191 +    BACK_RING_INIT(BLKIF_RING, &blkif->blk_ring, sring);
   3.192 +    
   3.193      blkif->evtchn        = evtchn;
   3.194      blkif->irq           = bind_evtchn_to_irq(evtchn);
   3.195      blkif->shmem_frame   = shmem_frame;
   3.196 -    blkif->blk_ring_base = (blkif_ring_t *)vma->addr;
   3.197      blkif->status        = CONNECTED;
   3.198 -    /*blkif_get(blkif);*/
   3.199 +    blkif_get(blkif);
   3.200  
   3.201      request_irq(blkif->irq, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
   3.202  
   3.203      connect->status = BLKIF_BE_STATUS_OKAY;
   3.204  }
   3.205  
   3.206 -void blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect)
   3.207 +int blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
   3.208  {
   3.209 -    /*
   3.210 -     * don't actually set the passthrough to disconnected.
   3.211 -     * We just act as a pipe, and defer to the real ends to handle things like
   3.212 -     * recovery.
   3.213 -     */
   3.214 +    domid_t       domid  = disconnect->domid;
   3.215 +    unsigned int  handle = disconnect->blkif_handle;
   3.216 +    blkif_t      *blkif;
   3.217  
   3.218      DPRINTK("PT got BE_DISCONNECT\n");
   3.219 +    
   3.220 +    blkif = blkif_find_by_handle(domid, handle);
   3.221 +    if ( unlikely(blkif == NULL) )
   3.222 +    {
   3.223 +        DPRINTK("blkif_disconnect attempted for non-existent blkif"
   3.224 +                " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); 
   3.225 +        disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   3.226 +        return 1; /* Caller will send response error message. */
   3.227 +    }
   3.228 +
   3.229 +    if ( blkif->status == CONNECTED )
   3.230 +    {
   3.231 +        blkif->status = DISCONNECTING;
   3.232 +        blkif->disconnect_rspid = rsp_id;
   3.233 +        wmb(); /* Let other CPUs see the status change. */
   3.234 +        free_irq(blkif->irq, blkif);
   3.235 +        blkif_deschedule(blkif);
   3.236 +        blkif_put(blkif);
   3.237 +        return 0; /* Caller should not send response message. */
   3.238 +    }
   3.239  
   3.240      disconnect->status = BLKIF_BE_STATUS_OKAY;
   3.241 -    return;
   3.242 +    return 1;
   3.243  }
   3.244  
   3.245  /*-----[ Control Messages to/from Backend VM ]----------------------------*/
   3.246 @@ -150,7 +289,7 @@ static void blkif_ptbe_send_interface_co
   3.247      };
   3.248      blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
   3.249      msg->handle      = 0;
   3.250 -    msg->shmem_frame = virt_to_machine(blk_ptbe_ring) >> PAGE_SHIFT;
   3.251 +    msg->shmem_frame = virt_to_machine(blktap_be_ring.sring) >> PAGE_SHIFT;
   3.252      
   3.253      ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   3.254  }
   3.255 @@ -162,9 +301,11 @@ static void blkif_ptbe_close(void)
   3.256  /* Move from CLOSED to DISCONNECTED state. */
   3.257  static void blkif_ptbe_disconnect(void)
   3.258  {
   3.259 -    blk_ptbe_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
   3.260 -    blk_ptbe_ring->req_prod = blk_ptbe_ring->resp_prod 
   3.261 -                            = ptbe_resp_cons = ptbe_req_prod = 0;
   3.262 +    blkif_sring_t *sring;
   3.263 +    
   3.264 +    sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
   3.265 +    SHARED_RING_INIT(BLKIF_RING, sring);
   3.266 +    FRONT_RING_INIT(BLKIF_RING, &blktap_be_ring, sring);
   3.267      blkif_pt_state  = BLKIF_STATE_DISCONNECTED;
   3.268      DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
   3.269      blkif_ptbe_send_interface_connect();
   3.270 @@ -319,7 +460,9 @@ void blkif_ctrlif_rx(ctrl_msg_t *msg, un
   3.271          case CMSG_BLKIF_BE_DISCONNECT:
   3.272              if ( msg->length != sizeof(blkif_be_disconnect_t) )
   3.273                  goto parse_error;
   3.274 -            blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0]);
   3.275 +            if ( !blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0],
   3.276 +                    msg->id) )
   3.277 +                return;
   3.278              break;        
   3.279  
   3.280          /* We just ignore anything to do with vbds for now. */
   3.281 @@ -356,3 +499,12 @@ void blkif_ctrlif_rx(ctrl_msg_t *msg, un
   3.282      msg->length = 0;
   3.283      ctrl_if_send_response(msg);
   3.284  }
   3.285 +
   3.286 +/*-----[ All control messages enter here: ]-------------------------------*/
   3.287 +
   3.288 +void __init blkif_interface_init(void)
   3.289 +{
   3.290 +    blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
   3.291 +                                     0, 0, NULL, NULL);
   3.292 +    memset(blkif_hash, 0, sizeof(blkif_hash));
   3.293 +}
     4.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c	Sat Jan 08 17:38:59 2005 +0000
     4.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c	Wed Jan 12 09:23:50 2005 +0000
     4.3 @@ -5,55 +5,46 @@
     4.4   * Block request routing data path.
     4.5   * 
     4.6   * Copyright (c) 2004, Andrew Warfield
     4.7 - *
     4.8 + * -- see full header in blktap.c
     4.9   */
    4.10   
    4.11  #include "blktap.h"
    4.12 +#include <asm-xen/evtchn.h>
    4.13  
    4.14  /*-----[ The data paths ]-------------------------------------------------*/
    4.15 - 
    4.16 -/* Connections to the frontend domains.*/
    4.17 -blkif_t   ptfe_blkif; 
    4.18 - 
    4.19 +
    4.20  /* Connection to a single backend domain. */
    4.21 -blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
    4.22 -BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
    4.23 -BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
    4.24 -
    4.25 -/* Rings up to user space. */ 
    4.26 -blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
    4.27 -blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
    4.28 -
    4.29 -/*-----[ Ring helpers ]---------------------------------------------------*/
    4.30 -
    4.31 -inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring)
    4.32 -{
    4.33 -    if (ring->type == BLKIF_REQ_RING_TYPE) {
    4.34 -        blkif_req_ring_t *r = (blkif_req_ring_t *)ring;
    4.35 -        return ( ( r->req_prod - r->rsp_cons ) == BLKIF_RING_SIZE );
    4.36 -    }
    4.37 -    
    4.38 -    /* for now assume that there is always room in the response path. */
    4.39 -    return 0;
    4.40 -}
    4.41 +blkif_front_ring_t blktap_be_ring;
    4.42  
    4.43  /*-----[ Tracking active requests ]---------------------------------------*/
    4.44  
    4.45  /* this must be the same as MAX_PENDING_REQS in blkback.c */
    4.46 -#define MAX_ACTIVE_REQS 64
    4.47 +#define MAX_ACTIVE_REQS ((ACTIVE_RING_IDX)64U)
    4.48  
    4.49 -active_req_t  active_reqs[MAX_ACTIVE_REQS];
    4.50 -unsigned char active_req_ring[MAX_ACTIVE_REQS];
    4.51 -spinlock_t    active_req_lock = SPIN_LOCK_UNLOCKED;
    4.52 -typedef unsigned int ACTIVE_RING_IDX;
    4.53 -ACTIVE_RING_IDX active_prod, active_cons;
    4.54 +active_req_t     active_reqs[MAX_ACTIVE_REQS];
    4.55 +ACTIVE_RING_IDX  active_req_ring[MAX_ACTIVE_REQS];
    4.56 +spinlock_t       active_req_lock = SPIN_LOCK_UNLOCKED;
    4.57 +ACTIVE_RING_IDX  active_prod, active_cons;
    4.58  #define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
    4.59  #define ACTIVE_IDX(_ar) (_ar - active_reqs)
    4.60 +#define NR_ACTIVE_REQS (MAX_ACTIVE_REQS - active_prod + active_cons)
    4.61  
    4.62  inline active_req_t *get_active_req(void) 
    4.63  {
    4.64 -    ASSERT(active_cons != active_prod);    
    4.65 -    return &active_reqs[MASK_ACTIVE_IDX(active_cons++)];
    4.66 +    ACTIVE_RING_IDX idx;
    4.67 +    active_req_t *ar;
    4.68 +    unsigned long flags;
    4.69 +        
    4.70 +    ASSERT(active_cons != active_prod);   
    4.71 +    
    4.72 +    spin_lock_irqsave(&active_req_lock, flags);
    4.73 +    idx =  active_req_ring[MASK_ACTIVE_IDX(active_cons++)];
    4.74 +    ar = &active_reqs[idx];
    4.75 +if (ar->inuse) WPRINTK("AR INUSE! (%lu)\n", ar->id);
    4.76 +ar->inuse = 1;
    4.77 +    spin_unlock_irqrestore(&active_req_lock, flags);
    4.78 +    
    4.79 +    return ar;
    4.80  }
    4.81  
    4.82  inline void free_active_req(active_req_t *ar) 
    4.83 @@ -61,10 +52,16 @@ inline void free_active_req(active_req_t
    4.84      unsigned long flags;
    4.85          
    4.86      spin_lock_irqsave(&active_req_lock, flags);
    4.87 +ar->inuse = 0;
    4.88      active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
    4.89      spin_unlock_irqrestore(&active_req_lock, flags);
    4.90  }
    4.91  
    4.92 +active_req_t *lookup_active_req(ACTIVE_RING_IDX idx)
    4.93 +{
    4.94 +    return &active_reqs[idx];   
    4.95 +}
    4.96 +
    4.97  inline void active_reqs_init(void)
    4.98  {
    4.99      ACTIVE_RING_IDX i;
   4.100 @@ -76,55 +73,256 @@ inline void active_reqs_init(void)
   4.101          active_req_ring[i] = i;
   4.102  }
   4.103  
   4.104 +/* Requests passing through the tap to the backend hijack the id field
   4.105 + * in the request message.  In it we put the AR index _AND_ the fe domid.
   4.106 + * the domid is used by the backend to map the pages properly.
   4.107 + */
   4.108 +
   4.109 +static inline unsigned long MAKE_ID(domid_t fe_dom, ACTIVE_RING_IDX idx)
   4.110 +{
   4.111 +    return ( (fe_dom << 16) | idx );
   4.112 +}
   4.113 +
   4.114 +inline unsigned int ID_TO_IDX(unsigned long id) 
   4.115 +{ 
   4.116 +        return ( id & 0x0000ffff );
   4.117 +}
   4.118 +
   4.119 +inline domid_t ID_TO_DOM(unsigned long id) { return (id >> 16); }
   4.120 +
   4.121 +/*-----[ Ring helpers ]---------------------------------------------------*/
   4.122 +
   4.123 +inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
   4.124 +{
   4.125 +    blkif_response_t *resp_d;
   4.126 +    active_req_t *ar;
   4.127 +    
   4.128 +    /* remap id, and free the active req. blkif lookup goes here too.*/
   4.129 +    ar = &active_reqs[ID_TO_IDX(rsp->id)];
   4.130 +    /* WPRINTK("%3u > %3lu\n", ID_TO_IDX(rsp->id), ar->id); */
   4.131 +    rsp->id = ar->id;
   4.132 +    free_active_req(ar);
   4.133 +            
   4.134 +    resp_d = RING_GET_RESPONSE(BLKIF_RING, &blkif->blk_ring,
   4.135 +            blkif->blk_ring.rsp_prod_pvt);
   4.136 +    memcpy(resp_d, rsp, sizeof(blkif_response_t));
   4.137 +    wmb();
   4.138 +    blkif->blk_ring.rsp_prod_pvt++;
   4.139 +            
   4.140 +    return 0;
   4.141 +}
   4.142 +
   4.143 +inline int write_req_to_be_ring(blkif_request_t *req)
   4.144 +{
   4.145 +    blkif_request_t *req_d;
   4.146 +
   4.147 +    req_d = RING_GET_REQUEST(BLKIF_RING, &blktap_be_ring,
   4.148 +            blktap_be_ring.req_prod_pvt);
   4.149 +    memcpy(req_d, req, sizeof(blkif_request_t));
   4.150 +    wmb();
   4.151 +    blktap_be_ring.req_prod_pvt++;
   4.152 +            
   4.153 +    return 0;
   4.154 +}
   4.155 +
   4.156 +inline void kick_fe_domain(blkif_t *blkif) 
   4.157 +{
   4.158 +    RING_PUSH_RESPONSES(BLKIF_RING, &blkif->blk_ring);
   4.159 +    notify_via_evtchn(blkif->evtchn);
   4.160 +    DPRINTK("notified FE(dom %u)\n", blkif->domid);
   4.161 +    
   4.162 +}
   4.163 +
   4.164 +inline void kick_be_domain(void)
   4.165 +{
   4.166 +    wmb(); /* Ensure that the frontend can see the requests. */
   4.167 +    RING_PUSH_REQUESTS(BLKIF_RING, &blktap_be_ring);
   4.168 +    notify_via_evtchn(blkif_ptbe_evtchn);
   4.169 +    DPRINTK("notified BE\n");
   4.170 +}
   4.171 +
   4.172  /*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
   4.173  
   4.174 +/*-----[ Scheduler list maint -from blkback ]--- */
   4.175 +
   4.176 +static struct list_head blkio_schedule_list;
   4.177 +static spinlock_t blkio_schedule_list_lock;
   4.178 +
   4.179 +static int __on_blkdev_list(blkif_t *blkif)
   4.180 +{
   4.181 +    return blkif->blkdev_list.next != NULL;
   4.182 +}
   4.183 +
   4.184 +static void remove_from_blkdev_list(blkif_t *blkif)
   4.185 +{
   4.186 +    unsigned long flags;
   4.187 +    if ( !__on_blkdev_list(blkif) ) return;
   4.188 +    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
   4.189 +    if ( __on_blkdev_list(blkif) )
   4.190 +    {
   4.191 +        list_del(&blkif->blkdev_list);
   4.192 +        blkif->blkdev_list.next = NULL;
   4.193 +        blkif_put(blkif);
   4.194 +    }
   4.195 +    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
   4.196 +}
   4.197 +
   4.198 +static void add_to_blkdev_list_tail(blkif_t *blkif)
   4.199 +{
   4.200 +    unsigned long flags;
   4.201 +    if ( __on_blkdev_list(blkif) ) return;
   4.202 +    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
   4.203 +    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
   4.204 +    {
   4.205 +        list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
   4.206 +        blkif_get(blkif);
   4.207 +    }
   4.208 +    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
   4.209 +}
   4.210 +
   4.211 +
   4.212 +/*-----[ Scheduler functions - from blkback ]--- */
   4.213 +
   4.214 +static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
   4.215 +
   4.216 +static int do_block_io_op(blkif_t *blkif, int max_to_do);
   4.217 +
   4.218 +static int blkio_schedule(void *arg)
   4.219 +{
   4.220 +    DECLARE_WAITQUEUE(wq, current);
   4.221 +
   4.222 +    blkif_t          *blkif;
   4.223 +    struct list_head *ent;
   4.224 +
   4.225 +    daemonize(
   4.226 +        "xentapd"
   4.227 +        );
   4.228 +
   4.229 +    for ( ; ; )
   4.230 +    {
   4.231 +        /* Wait for work to do. */
   4.232 +        add_wait_queue(&blkio_schedule_wait, &wq);
   4.233 +        set_current_state(TASK_INTERRUPTIBLE);
   4.234 +        if ( (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) || 
   4.235 +             list_empty(&blkio_schedule_list) )
   4.236 +            schedule();
   4.237 +        __set_current_state(TASK_RUNNING);
   4.238 +        remove_wait_queue(&blkio_schedule_wait, &wq);
   4.239 +
   4.240 +        /* Queue up a batch of requests. */
   4.241 +        while ( (NR_ACTIVE_REQS < MAX_ACTIVE_REQS) &&
   4.242 +                !list_empty(&blkio_schedule_list) )
   4.243 +        {
   4.244 +            ent = blkio_schedule_list.next;
   4.245 +            blkif = list_entry(ent, blkif_t, blkdev_list);
   4.246 +            blkif_get(blkif);
   4.247 +            remove_from_blkdev_list(blkif);
   4.248 +            if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
   4.249 +                add_to_blkdev_list_tail(blkif);
   4.250 +            blkif_put(blkif);
   4.251 +        }
   4.252 +
   4.253 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
   4.254 +        /* Push the batch through to disc. */
   4.255 +        run_task_queue(&tq_disk);
   4.256 +#endif
   4.257 +    }
   4.258 +}
   4.259 +
   4.260 +static void maybe_trigger_blkio_schedule(void)
   4.261 +{
   4.262 +    /*
   4.263 +     * Needed so that two processes, who together make the following predicate
   4.264 +     * true, don't both read stale values and evaluate the predicate
   4.265 +     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
   4.266 +     */
   4.267 +    smp_mb();
   4.268 +
   4.269 +    if ( (NR_ACTIVE_REQS < (MAX_ACTIVE_REQS)) && /* XXX!!! was M_A_R/2*/
   4.270 +         !list_empty(&blkio_schedule_list) ) 
   4.271 +        wake_up(&blkio_schedule_wait);
   4.272 +}
   4.273 +
   4.274 +void blkif_deschedule(blkif_t *blkif)
   4.275 +{
   4.276 +    remove_from_blkdev_list(blkif);
   4.277 +}
   4.278 +
   4.279 +void __init blkdev_schedule_init(void)
   4.280 +{
   4.281 +    spin_lock_init(&blkio_schedule_list_lock);
   4.282 +    INIT_LIST_HEAD(&blkio_schedule_list);
   4.283 +
   4.284 +    if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
   4.285 +        BUG();
   4.286 +}
   4.287 +    
   4.288 +/*-----[ Interrupt entry from a frontend ]------ */
   4.289 +
   4.290  irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
   4.291  {
   4.292 +    blkif_t *blkif = dev_id;
   4.293 +
   4.294 +    add_to_blkdev_list_tail(blkif);
   4.295 +    maybe_trigger_blkio_schedule();
   4.296 +    return IRQ_HANDLED;
   4.297 +}
   4.298 +
   4.299 +/*-----[ Other Frontend Ring functions ]-------- */
   4.300 +
   4.301 +/* irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)*/
   4.302 +static int do_block_io_op(blkif_t *blkif, int max_to_do)
   4.303 +{
   4.304      /* we have pending messages from the real frontend. */
   4.305  
   4.306 -    blkif_request_t *req_s, *req_d;
   4.307 -    BLKIF_RING_IDX fe_rp;
   4.308 +    blkif_request_t *req_s;
   4.309 +    RING_IDX i, rp;
   4.310      unsigned long flags;
   4.311 -    int notify;
   4.312 -    unsigned long i;
   4.313      active_req_t *ar;
   4.314 +    int more_to_do = 0;
   4.315 +    int notify_be = 0, notify_user = 0;
   4.316      
   4.317      DPRINTK("PT got FE interrupt.\n");
   4.318 +
   4.319 +    if (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) return 1;
   4.320      
   4.321      /* lock both rings */
   4.322      spin_lock_irqsave(&blkif_io_lock, flags);
   4.323  
   4.324 -    /* While there are REQUESTS on FERing: */
   4.325 -    fe_rp = ptfe_blkif.blk_ring_base->req_prod;
   4.326 +    rp = blkif->blk_ring.sring->req_prod;
   4.327      rmb();
   4.328 -    notify = (ptfe_blkif.blk_req_cons != fe_rp);
   4.329 -
   4.330 -    for (i = ptfe_blkif.blk_req_cons; i != fe_rp; i++) {
   4.331 -
   4.332 -        /* Get the next request */
   4.333 -        req_s = &ptfe_blkif.blk_ring_base->ring[MASK_BLKIF_IDX(i)].req;
   4.334 +    
   4.335 +    for ( i = blkif->blk_ring.req_cons; 
   4.336 +         (i != rp) && 
   4.337 +            !RING_REQUEST_CONS_OVERFLOW(BLKIF_RING, &blkif->blk_ring, i);
   4.338 +          i++ )
   4.339 +    {
   4.340          
   4.341 +        if ((--max_to_do == 0) || (NR_ACTIVE_REQS == MAX_ACTIVE_REQS)) 
   4.342 +        {
   4.343 +            more_to_do = 1;
   4.344 +            break;
   4.345 +        }
   4.346 +        
   4.347 +        req_s = RING_GET_REQUEST(BLKIF_RING, &blkif->blk_ring, i);
   4.348          /* This is a new request:  
   4.349           * Assign an active request record, and remap the id. 
   4.350           */
   4.351          ar = get_active_req();
   4.352          ar->id = req_s->id;
   4.353 -        req_s->id = ACTIVE_IDX(ar);
   4.354 -        DPRINTK("%3lu < %3lu\n", req_s->id, ar->id);
   4.355 +        ar->blkif = blkif;
   4.356 +        req_s->id = MAKE_ID(blkif->domid, ACTIVE_IDX(ar));
   4.357 +        /* WPRINTK("%3u < %3lu\n", ID_TO_IDX(req_s->id), ar->id); */
   4.358  
   4.359          /* FE -> BE interposition point is here. */
   4.360          
   4.361          /* ------------------------------------------------------------- */
   4.362          /* BLKIF_OP_PROBE_HACK:                                          */
   4.363 -        /* Until we have grant tables, we need to allow the backent to   */
   4.364 -        /* map pages that are either from this domain, or more commonly  */
   4.365 -        /* from the real front end.  We achieve this in a terrible way,  */
   4.366 -        /* by passing the front end's domid allong with PROBE messages   */
   4.367 -        /* Once grant tables appear, this should all go away.            */
   4.368 +        /* Signal to the backend that we are a tap domain.               */
   4.369  
   4.370          if (req_s->operation == BLKIF_OP_PROBE) {
   4.371 -            DPRINTK("Adding FE domid to PROBE request.\n");
   4.372 -            (domid_t)(req_s->frame_and_sects[1]) = ptfe_blkif.domid;
   4.373 +            DPRINTK("Adding BLKTAP_COOKIE to PROBE request.\n");
   4.374 +            req_s->frame_and_sects[1] = BLKTAP_COOKIE;
   4.375          }
   4.376  
   4.377          /* ------------------------------------------------------------- */
   4.378 @@ -137,12 +335,9 @@ irqreturn_t blkif_ptfe_int(int irq, void
   4.379              /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
   4.380              /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
   4.381  
   4.382 -            /* XXX: mapping/copying of attached pages is still not done! */
   4.383 -
   4.384              DPRINTK("req->UFERing\n"); 
   4.385              blktap_write_fe_ring(req_s);
   4.386 -
   4.387 -
   4.388 +            notify_user = 1;
   4.389          }
   4.390  
   4.391          /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
   4.392 @@ -153,61 +348,27 @@ irqreturn_t blkif_ptfe_int(int irq, void
   4.393              /* copy the request message to the BERing */
   4.394  
   4.395              DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 
   4.396 -                    (unsigned)MASK_BLKIF_IDX(i), 
   4.397 -                    (unsigned)MASK_BLKIF_IDX(ptbe_req_prod));
   4.398 -
   4.399 -            req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
   4.400 +                    (unsigned)__SHARED_RING_MASK(BLKIF_RING, 
   4.401 +                        blktap_be_ring.sring, i), 
   4.402 +                    (unsigned)__SHARED_RING_MASK(BLKIF_RING, 
   4.403 +                        blktap_be_ring.sring, blktap_be_ring.req_prod_pvt));
   4.404              
   4.405 -            memcpy(req_d, req_s, sizeof(blkif_request_t));
   4.406 -
   4.407 -            ptbe_req_prod++;
   4.408 +            write_req_to_be_ring(req_s);
   4.409 +            notify_be = 1;
   4.410          }
   4.411      }
   4.412  
   4.413 -    ptfe_blkif.blk_req_cons = i;
   4.414 -
   4.415 -    /* If we have forwarded any responses, notify the appropriate ends. */
   4.416 -    if (notify) {
   4.417 -
   4.418 -        /* we have sent stuff to the be, notify it. */
   4.419 -        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
   4.420 -               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
   4.421 -            wmb();
   4.422 -            blk_ptbe_ring->req_prod = ptbe_req_prod;
   4.423 -
   4.424 -            notify_via_evtchn(blkif_ptbe_evtchn);
   4.425 -            DPRINTK(" -- and notified.\n");
   4.426 -        }
   4.427 -
   4.428 -        /* we sent stuff to the app, notify it. */
   4.429 -        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
   4.430 -             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
   4.431 -
   4.432 -            blktap_kick_user();
   4.433 -        }
   4.434 -    }
   4.435 -
   4.436 +    blkif->blk_ring.req_cons = i;
   4.437 +    
   4.438      /* unlock rings */
   4.439      spin_unlock_irqrestore(&blkif_io_lock, flags);
   4.440 -
   4.441 -    return IRQ_HANDLED;
   4.442 -}
   4.443 -
   4.444 -inline int write_req_to_be_ring(blkif_request_t *req)
   4.445 -{
   4.446 -    blkif_request_t *req_d;
   4.447 -
   4.448 -    req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
   4.449 -    memcpy(req_d, req, sizeof(blkif_request_t));
   4.450 -    ptbe_req_prod++;
   4.451 -
   4.452 -    return 0;
   4.453 -}
   4.454 -
   4.455 -inline void kick_be_domain(void) {
   4.456 -    wmb();
   4.457 -    blk_ptbe_ring->req_prod = ptbe_req_prod;
   4.458 -    notify_via_evtchn(blkif_ptbe_evtchn);
   4.459 +    
   4.460 +    if (notify_user)
   4.461 +        blktap_kick_user();
   4.462 +    if (notify_be)
   4.463 +        kick_be_domain();
   4.464 +    
   4.465 +    return more_to_do;
   4.466  }
   4.467  
   4.468  /*-----[ Data to/from Backend (server) VM ]------------------------------*/
   4.469 @@ -216,31 +377,27 @@ inline void kick_be_domain(void) {
   4.470  irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
   4.471                                    struct pt_regs *ptregs)
   4.472  {
   4.473 -    blkif_response_t  *resp_s, *resp_d;
   4.474 -    BLKIF_RING_IDX be_rp;
   4.475 +    blkif_response_t  *resp_s;
   4.476 +    blkif_t *blkif;
   4.477 +    RING_IDX rp, i;
   4.478      unsigned long flags;
   4.479 -    int notify;
   4.480 -    unsigned long i;
   4.481 -    active_req_t *ar;
   4.482  
   4.483      DPRINTK("PT got BE interrupt.\n");
   4.484  
   4.485      /* lock both rings */
   4.486      spin_lock_irqsave(&blkif_io_lock, flags);
   4.487      
   4.488 -    /* While there are RESPONSES on BERing: */
   4.489 -    be_rp = blk_ptbe_ring->resp_prod;
   4.490 +    rp = blktap_be_ring.sring->rsp_prod;
   4.491      rmb();
   4.492 -    notify = (ptbe_resp_cons != be_rp);
   4.493 -    
   4.494 -    for ( i = ptbe_resp_cons; i != be_rp; i++ )
   4.495 +      
   4.496 +    for ( i = blktap_be_ring.rsp_cons; i != rp; i++)
   4.497      {
   4.498 -        /* BE -> FE interposition point is here. */
   4.499 +        resp_s = RING_GET_RESPONSE(BLKIF_RING, &blktap_be_ring, i);
   4.500          
   4.501 -        /* Get the next response */
   4.502 -        resp_s = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(i)].resp;
   4.503 +        /* BE -> FE interposition point is here. */
   4.504      
   4.505 -       
   4.506 +        blkif = active_reqs[ID_TO_IDX(resp_s->id)].blkif;
   4.507 +        
   4.508          /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
   4.509          if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
   4.510               (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
   4.511 @@ -249,10 +406,9 @@ irqreturn_t blkif_ptbe_int(int irq, void
   4.512              /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
   4.513              /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
   4.514  
   4.515 -            /* XXX: copy/map the attached page! */
   4.516 -
   4.517              DPRINTK("rsp->UBERing\n"); 
   4.518              blktap_write_be_ring(resp_s);
   4.519 +            blktap_kick_user();
   4.520  
   4.521          }
   4.522         
   4.523 @@ -264,254 +420,49 @@ irqreturn_t blkif_ptbe_int(int irq, void
   4.524              /* Copy the response message to FERing */
   4.525           
   4.526              DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 
   4.527 -                    (unsigned) MASK_BLKIF_IDX(i), 
   4.528 -                    (unsigned) MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod));
   4.529 +                    (unsigned)__SHARED_RING_MASK(BLKIF_RING, 
   4.530 +                        blkif->blk_ring.sring, i), 
   4.531 +                    (unsigned)__SHARED_RING_MASK(BLKIF_RING, 
   4.532 +                        blkif->blk_ring.sring, 
   4.533 +                        blkif->blk_ring.rsp_prod_pvt));
   4.534  
   4.535 -            /* remap id, and free the active req. blkif lookup goes here too.*/
   4.536 -            ar = &active_reqs[resp_s->id];
   4.537 -            DPRINTK("%3lu > %3lu\n", resp_s->id, ar->id);
   4.538 -            resp_s->id = ar->id;
   4.539 -            free_active_req(ar);
   4.540 -           
   4.541 -            resp_d = &ptfe_blkif.blk_ring_base->ring[
   4.542 -                MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
   4.543 -
   4.544 -            memcpy(resp_d, resp_s, sizeof(blkif_response_t));
   4.545 -            
   4.546 -            ptfe_blkif.blk_resp_prod++;
   4.547 +            write_resp_to_fe_ring(blkif, resp_s);
   4.548 +            kick_fe_domain(blkif);
   4.549  
   4.550          }
   4.551      }
   4.552 -
   4.553 -    ptbe_resp_cons = i;
   4.554      
   4.555 -    /* If we have forwarded any responses, notify the apropriate domains. */
   4.556 -    if (notify) {
   4.557 -
   4.558 -        /* we have sent stuff to the fe.  notify it. */
   4.559 -        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
   4.560 -               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
   4.561 -            wmb();
   4.562 -            ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
   4.563 -        
   4.564 -            notify_via_evtchn(ptfe_blkif.evtchn);
   4.565 -            DPRINTK(" -- and notified.\n");
   4.566 -        }
   4.567 -
   4.568 -        /* we sent stuff to the app, notify it. */
   4.569 -        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
   4.570 -             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
   4.571 -
   4.572 -            blktap_kick_user();
   4.573 -        }
   4.574 -    }
   4.575 +    blktap_be_ring.rsp_cons = i;
   4.576 +    
   4.577  
   4.578      spin_unlock_irqrestore(&blkif_io_lock, flags);
   4.579 +    
   4.580      return IRQ_HANDLED;
   4.581  }
   4.582  
   4.583 -inline int write_resp_to_fe_ring(blkif_response_t *rsp)
   4.584 -{
   4.585 -    blkif_response_t *resp_d;
   4.586 -    active_req_t *ar;
   4.587 -    
   4.588 -    /* remap id, and free the active req. blkif lookup goes here too.*/
   4.589 -    ar = &active_reqs[rsp->id];
   4.590 -    DPRINTK("%3lu > %3lu\n", rsp->id, ar->id);
   4.591 -    rsp->id = ar->id;
   4.592 -    free_active_req(ar);
   4.593 -            
   4.594 -    resp_d = &ptfe_blkif.blk_ring_base->ring[
   4.595 -        MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
   4.596 -
   4.597 -    memcpy(resp_d, rsp, sizeof(blkif_response_t));
   4.598 -    ptfe_blkif.blk_resp_prod++;
   4.599 -
   4.600 -    return 0;
   4.601 -}
   4.602 -
   4.603 -inline void kick_fe_domain(void) {
   4.604 -    wmb();
   4.605 -    ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
   4.606 -    notify_via_evtchn(ptfe_blkif.evtchn);
   4.607 -    
   4.608 -}
   4.609 -
   4.610 -static inline void flush_requests(void)
   4.611 -{
   4.612 -    wmb(); /* Ensure that the frontend can see the requests. */
   4.613 -    blk_ptbe_ring->req_prod = ptbe_req_prod;
   4.614 -    notify_via_evtchn(blkif_ptbe_evtchn);
   4.615 -}
   4.616 -
   4.617 -/*-----[ Data to/from user space ]----------------------------------------*/
   4.618 -
   4.619 -
   4.620 -int blktap_write_fe_ring(blkif_request_t *req)
   4.621 -{
   4.622 -    blkif_request_t *target;
   4.623 -    int error, i;
   4.624 -
   4.625 -    /*
   4.626 -     * This is called to pass a request from the real frontend domain's
   4.627 -     * blkif ring to the character device.
   4.628 -     */
   4.629 -
   4.630 -    if ( ! blktap_ring_ok ) {
   4.631 -        DPRINTK("blktap: fe_ring not ready for a request!\n");
   4.632 -        return 0;
   4.633 -    }
   4.634 -
   4.635 -    if ( BLKTAP_RING_FULL(RING(&fe_ring)) ) {
   4.636 -        DPRINTK("blktap: fe_ring is full, can't add.\n");
   4.637 -        return 0;
   4.638 -    }
   4.639 -
   4.640 -    target = &fe_ring.ring->ring[MASK_BLKIF_IDX(fe_ring.req_prod)].req;
   4.641 -    memcpy(target, req, sizeof(*req));
   4.642 -
   4.643 -/* maybe move this stuff out into a seperate func ------------------- */
   4.644 -
   4.645 -    /*
   4.646 -     * For now, map attached page into a fixed position into the vma.
   4.647 -     * XXX: make this map to a free page.
   4.648 -     */
   4.649 -
   4.650 -    /* Attempt to map the foreign pages directly in to the application */
   4.651 -    for (i=0; i<target->nr_segments; i++) {
   4.652 -
   4.653 -        /* get an unused virtual address from the char device */
   4.654 -        /* store the old page address */
   4.655 -        /* replace the address with the virtual address */
   4.656 -
   4.657 -        /* blktap_vma->vm_start+((2+i)*PAGE_SIZE) */
   4.658 -
   4.659 -        error = direct_remap_area_pages(blktap_vma->vm_mm, 
   4.660 -                                        MMAP_VADDR(req->id, i), 
   4.661 -                                        target->frame_and_sects[0] & PAGE_MASK,
   4.662 -                                        PAGE_SIZE,
   4.663 -                                        blktap_vma->vm_page_prot,
   4.664 -                                        ptfe_blkif.domid);
   4.665 -        if ( error != 0 ) {
   4.666 -            printk(KERN_INFO "remapping attached page failed! (%d)\n", error);
   4.667 -            return 0;
   4.668 -        }
   4.669 -    }
   4.670 -    /* fix the address of the attached page in the message. */
   4.671 -    /* TODO:      preserve the segment number stuff here... */
   4.672 -    /* target->frame_and_sects[0] = blktap_vma->vm_start + PAGE_SIZE;*/
   4.673 -/* ------------------------------------------------------------------ */
   4.674 -
   4.675 -    
   4.676 -    fe_ring.req_prod++;
   4.677 -
   4.678 -    return 0;
   4.679 -}
   4.680 -
   4.681 -int blktap_write_be_ring(blkif_response_t *rsp)
   4.682 -{
   4.683 -    blkif_response_t *target;
   4.684 +/* Debug : print the current ring indices. */
   4.685  
   4.686 -    /*
   4.687 -     * This is called to pass a request from the real backend domain's
   4.688 -     * blkif ring to the character device.
   4.689 -     */
   4.690 -
   4.691 -    if ( ! blktap_ring_ok ) {
   4.692 -        DPRINTK("blktap: be_ring not ready for a request!\n");
   4.693 -        return 0;
   4.694 -    }
   4.695 -
   4.696 -    if ( BLKTAP_RING_FULL(RING(&be_ring)) ) {
   4.697 -        DPRINTK("blktap: be_ring is full, can't add.\n");
   4.698 -        return 0;
   4.699 -    }
   4.700 -
   4.701 -    target = &be_ring.ring->ring[MASK_BLKIF_IDX(be_ring.rsp_prod)].resp;
   4.702 -    memcpy(target, rsp, sizeof(*rsp));
   4.703 -
   4.704 -
   4.705 -    /* XXX: map attached pages and fix-up addresses in the copied address. */
   4.706 -
   4.707 -    be_ring.rsp_prod++;
   4.708 -
   4.709 -    return 0;
   4.710 -}
   4.711 -
   4.712 -int blktap_read_fe_ring(void)
   4.713 +void print_vm_ring_idxs(void)
   4.714  {
   4.715 -    /* This is called to read responses from the UFE ring. */
   4.716 -
   4.717 -    BLKIF_RING_IDX fe_rp;
   4.718 -    unsigned long i;
   4.719 -    int notify;
   4.720 -
   4.721 -    DPRINTK("blktap_read_fe_ring()\n");
   4.722 -
   4.723 -    fe_rp = fe_ring.ring->resp_prod;
   4.724 -    rmb();
   4.725 -    notify = (fe_rp != fe_ring.rsp_cons);
   4.726 -
   4.727 -    /* if we are forwarding from UFERring to FERing */
   4.728 -    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
   4.729 -
   4.730 -        /* for each outstanding message on the UFEring  */
   4.731 -        for ( i = fe_ring.rsp_cons; i != fe_rp; i++ ) {
   4.732 -
   4.733 -            /* XXX: remap pages on that message as necessary */
   4.734 -            /* copy the message to the UBEring */
   4.735 -
   4.736 -            DPRINTK("resp->fe_ring\n");
   4.737 -            write_resp_to_fe_ring(&fe_ring.ring->ring[MASK_BLKIF_IDX(i)].resp);
   4.738 -        }
   4.739 -    
   4.740 -        fe_ring.rsp_cons = fe_rp;
   4.741 -
   4.742 -        /* notify the fe if necessary */
   4.743 -        if ( notify ) {
   4.744 -            DPRINTK("kick_fe_domain()\n");
   4.745 -            kick_fe_domain();
   4.746 -        }
   4.747 +    int i;
   4.748 +    blkif_t *blkif;
   4.749 +            
   4.750 +    WPRINTK("FE Rings: \n---------\n");
   4.751 +    for ( i = 0; i < 50; i++) { 
   4.752 +        blkif = blkif_find_by_handle((domid_t)i, 0);
   4.753 +        if (blkif != NULL)
   4.754 +            WPRINTK("%2d: req_cons: %2d, rsp_prod_prv: %2d "
   4.755 +                "| req_prod: %2d, rsp_prod: %2d\n", i, 
   4.756 +                blkif->blk_ring.req_cons,
   4.757 +                blkif->blk_ring.rsp_prod_pvt,
   4.758 +                blkif->blk_ring.sring->req_prod,
   4.759 +                blkif->blk_ring.sring->rsp_prod);
   4.760      }
   4.761 -
   4.762 -    return 0;
   4.763 -}
   4.764 -
   4.765 -int blktap_read_be_ring(void)
   4.766 -{
   4.767 -    /* This is called to read responses from the UBE ring. */
   4.768 -
   4.769 -    BLKIF_RING_IDX be_rp;
   4.770 -    unsigned long i;
   4.771 -    int notify;
   4.772 -
   4.773 -    DPRINTK("blktap_read_be_ring()\n");
   4.774 -
   4.775 -    be_rp = be_ring.ring->req_prod;
   4.776 -    rmb();
   4.777 -    notify = (be_rp != be_ring.req_cons);
   4.778 -
   4.779 -    /* if we are forwarding from UFERring to FERing */
   4.780 -    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
   4.781 -
   4.782 -        /* for each outstanding message on the UFEring  */
   4.783 -        for ( i = be_ring.req_cons; i != be_rp; i++ ) {
   4.784 -
   4.785 -            /* XXX: remap pages on that message as necessary */
   4.786 -            /* copy the message to the UBEring */
   4.787 -
   4.788 -            DPRINTK("req->be_ring\n");
   4.789 -            write_req_to_be_ring(&be_ring.ring->ring[MASK_BLKIF_IDX(i)].req);
   4.790 -        }
   4.791 -    
   4.792 -        be_ring.req_cons = be_rp;
   4.793 -
   4.794 -        /* notify the fe if necessary */
   4.795 -        if ( notify ) {
   4.796 -            DPRINTK("kick_be_domain()\n");
   4.797 -            kick_be_domain();
   4.798 -        }
   4.799 -    }
   4.800 -
   4.801 -    return 0;
   4.802 -}
   4.803 +    WPRINTK("BE Ring: \n--------\n");
   4.804 +    WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
   4.805 +        "| req_prod: %2d, rsp_prod: %2d\n",
   4.806 +        blktap_be_ring.rsp_cons,
   4.807 +        blktap_be_ring.req_prod_pvt,
   4.808 +        blktap_be_ring.sring->req_prod,
   4.809 +        blktap_be_ring.sring->rsp_prod);
   4.810 +}        
     5.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Sat Jan 08 17:38:59 2005 +0000
     5.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Wed Jan 12 09:23:50 2005 +0000
     5.3 @@ -37,6 +37,10 @@ struct vm_area_struct *blktap_vma;
     5.4  unsigned long mmap_vstart;
     5.5  unsigned long rings_vstart;
     5.6  
     5.7 +/* Rings up to user space. */
     5.8 +static blkif_front_ring_t blktap_ufe_ring;
     5.9 +static blkif_back_ring_t  blktap_ube_ring;
    5.10 +
    5.11  /* -------[ blktap vm ops ]------------------------------------------- */
    5.12  
    5.13  static struct page *blktap_nopage(struct vm_area_struct *vma,
    5.14 @@ -61,41 +65,39 @@ struct vm_operations_struct blktap_vm_op
    5.15  
    5.16  static int blktap_open(struct inode *inode, struct file *filp)
    5.17  {
    5.18 +    blkif_sring_t *sring;
    5.19 +    
    5.20      if ( test_and_set_bit(0, &blktap_dev_inuse) )
    5.21          return -EBUSY;
    5.22  
    5.23      printk(KERN_ALERT "blktap open.\n");
    5.24  
    5.25      /* Allocate the fe ring. */
    5.26 -    fe_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
    5.27 -    if (fe_ring.ring == NULL)
    5.28 +    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
    5.29 +    if (sring == NULL)
    5.30          goto fail_nomem;
    5.31  
    5.32 -    SetPageReserved(virt_to_page(fe_ring.ring));
    5.33 +    SetPageReserved(virt_to_page(sring));
    5.34      
    5.35 -    fe_ring.ring->req_prod = fe_ring.ring->resp_prod
    5.36 -                           = fe_ring.req_prod
    5.37 -                           = fe_ring.rsp_cons
    5.38 -                           = 0;
    5.39 +    SHARED_RING_INIT(BLKIF_RING, sring);
    5.40 +    FRONT_RING_INIT(BLKIF_RING, &blktap_ufe_ring, sring);
    5.41  
    5.42      /* Allocate the be ring. */
    5.43 -    be_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
    5.44 -    if (be_ring.ring == NULL)
    5.45 +    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
    5.46 +    if (sring == NULL)
    5.47          goto fail_free_fe;
    5.48  
    5.49 -    SetPageReserved(virt_to_page(be_ring.ring));
    5.50 +    SetPageReserved(virt_to_page(sring));
    5.51      
    5.52 -    be_ring.ring->req_prod = be_ring.ring->resp_prod
    5.53 -                           = be_ring.rsp_prod
    5.54 -                           = be_ring.req_cons
    5.55 -                           = 0;
    5.56 +    SHARED_RING_INIT(BLKIF_RING, sring);
    5.57 +    BACK_RING_INIT(BLKIF_RING, &blktap_ube_ring, sring);
    5.58  
    5.59      DPRINTK(KERN_ALERT "blktap open.\n");
    5.60  
    5.61      return 0;
    5.62  
    5.63   fail_free_fe:
    5.64 -    free_page( (unsigned long) fe_ring.ring);
    5.65 +    free_page( (unsigned long) blktap_ufe_ring.sring);
    5.66  
    5.67   fail_nomem:
    5.68      return -ENOMEM;
    5.69 @@ -109,11 +111,11 @@ static int blktap_release(struct inode *
    5.70      printk(KERN_ALERT "blktap closed.\n");
    5.71  
    5.72      /* Free the ring page. */
    5.73 -    ClearPageReserved(virt_to_page(fe_ring.ring));
    5.74 -    free_page((unsigned long) fe_ring.ring);
    5.75 +    ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
    5.76 +    free_page((unsigned long) blktap_ufe_ring.sring);
    5.77  
    5.78 -    ClearPageReserved(virt_to_page(be_ring.ring));
    5.79 -    free_page((unsigned long) be_ring.ring);
    5.80 +    ClearPageReserved(virt_to_page(blktap_ube_ring.sring));
    5.81 +    free_page((unsigned long) blktap_ube_ring.sring);
    5.82      
    5.83      return 0;
    5.84  }
    5.85 @@ -146,16 +148,18 @@ static int blktap_mmap(struct file *filp
    5.86      /* not sure if I really need to do this... */
    5.87      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    5.88  
    5.89 -    DPRINTK("Mapping be_ring page %lx.\n", __pa(be_ring.ring));
    5.90 -    if (remap_page_range(vma, vma->vm_start, __pa(be_ring.ring), PAGE_SIZE, 
    5.91 -                         vma->vm_page_prot)) {
    5.92 -        printk(KERN_ERR "be_ring: remap_page_range failure!\n");
    5.93 +    DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
    5.94 +    if (remap_page_range(vma, vma->vm_start, 
    5.95 +                         __pa(blktap_ube_ring.sring), 
    5.96 +                         PAGE_SIZE, vma->vm_page_prot)) {
    5.97 +        WPRINTK("be_ring: remap_page_range failure!\n");
    5.98      }
    5.99  
   5.100 -    DPRINTK("Mapping fe_ring page %lx.\n", __pa(fe_ring.ring));
   5.101 -    if (remap_page_range(vma, vma->vm_start + PAGE_SIZE, __pa(fe_ring.ring), 
   5.102 +    DPRINTK("Mapping fe_ring page %lx.\n", __pa(blktap_ufe_ring.sring));
   5.103 +    if (remap_page_range(vma, vma->vm_start + PAGE_SIZE, 
   5.104 +                         __pa(blktap_ufe_ring.sring), 
   5.105                           PAGE_SIZE, vma->vm_page_prot)) {
   5.106 -        printk(KERN_ERR "fe_ring: remap_page_range failure!\n");
   5.107 +        WPRINTK("fe_ring: remap_page_range failure!\n");
   5.108      }
   5.109  
   5.110      blktap_vma = vma;
   5.111 @@ -181,7 +185,24 @@ static int blktap_ioctl(struct inode *in
   5.112              printk(KERN_INFO "blktap: set mode to %lx\n", arg);
   5.113              return 0;
   5.114          }
   5.115 -        /* XXX: return a more meaningful error case here. */
   5.116 +    case BLKTAP_IOCTL_PRINT_IDXS:
   5.117 +        {
   5.118 +            print_vm_ring_idxs();
   5.119 +            WPRINTK("User Rings: \n-----------\n");
   5.120 +            WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
   5.121 +                            "| req_prod: %2d, rsp_prod: %2d\n",
   5.122 +                            blktap_ufe_ring.rsp_cons,
   5.123 +                            blktap_ufe_ring.req_prod_pvt,
   5.124 +                            blktap_ufe_ring.sring->req_prod,
   5.125 +                            blktap_ufe_ring.sring->rsp_prod);
   5.126 +            WPRINTK("UB: req_cons: %2d, rsp_prod_prv: %2d "
   5.127 +                            "| req_prod: %2d, rsp_prod: %2d\n",
   5.128 +                            blktap_ube_ring.req_cons,
   5.129 +                            blktap_ube_ring.rsp_prod_pvt,
   5.130 +                            blktap_ube_ring.sring->req_prod,
   5.131 +                            blktap_ube_ring.sring->rsp_prod);
   5.132 +            
   5.133 +        }
   5.134      }
   5.135      return -ENOIOCTLCMD;
   5.136  }
   5.137 @@ -190,11 +211,11 @@ static unsigned int blktap_poll(struct f
   5.138  {
   5.139          poll_wait(file, &blktap_wait, wait);
   5.140  
   5.141 -        if ( (fe_ring.req_prod != fe_ring.ring->req_prod) ||
   5.142 -             (be_ring.rsp_prod != be_ring.ring->resp_prod) ) {
   5.143 +        if ( RING_HAS_UNPUSHED_REQUESTS(BLKIF_RING, &blktap_ufe_ring) ||
   5.144 +             RING_HAS_UNPUSHED_RESPONSES(BLKIF_RING, &blktap_ube_ring) ) {
   5.145  
   5.146 -            fe_ring.ring->req_prod = fe_ring.req_prod;
   5.147 -            be_ring.ring->resp_prod = be_ring.rsp_prod;
   5.148 +            RING_PUSH_REQUESTS(BLKIF_RING, &blktap_ufe_ring);
   5.149 +            RING_PUSH_RESPONSES(BLKIF_RING, &blktap_ube_ring);
   5.150              return POLLIN | POLLRDNORM;
   5.151          }
   5.152  
   5.153 @@ -215,7 +236,149 @@ static struct file_operations blktap_fop
   5.154      release:  blktap_release,
   5.155      mmap:     blktap_mmap,
   5.156  };
   5.157 +    
   5.158 +/*-----[ Data to/from user space ]----------------------------------------*/
   5.159  
   5.160 +
   5.161 +int blktap_write_fe_ring(blkif_request_t *req)
   5.162 +{
   5.163 +    blkif_request_t *target;
   5.164 +    int error, i;
   5.165 +
   5.166 +    /*
   5.167 +     * This is called to pass a request from the real frontend domain's
   5.168 +     * blkif ring to the character device.
   5.169 +     */
   5.170 +
   5.171 +    if ( ! blktap_ring_ok ) {
   5.172 +        DPRINTK("blktap: ufe_ring not ready for a request!\n");
   5.173 +        return 0;
   5.174 +    }
   5.175 +
   5.176 +    if ( RING_FULL(BLKIF_RING, &blktap_ufe_ring) ) {
   5.177 +        DPRINTK("blktap: fe_ring is full, can't add.\n");
   5.178 +        return 0;
   5.179 +    }
   5.180 +
   5.181 +    //target = RING_NEXT_EMPTY_REQUEST(BLKIF_RING, &blktap_ufe_ring);
   5.182 +    target = RING_GET_REQUEST(BLKIF_RING, &blktap_ufe_ring,
   5.183 +            blktap_ufe_ring.req_prod_pvt);
   5.184 +    memcpy(target, req, sizeof(*req));
   5.185 +
   5.186 +    /* Attempt to map the foreign pages directly in to the application */
   5.187 +    for (i=0; i<target->nr_segments; i++) {
   5.188 +
   5.189 +        error = direct_remap_area_pages(blktap_vma->vm_mm, 
   5.190 +                                        MMAP_VADDR(ID_TO_IDX(req->id), i), 
   5.191 +                                        target->frame_and_sects[0] & PAGE_MASK,
   5.192 +                                        PAGE_SIZE,
   5.193 +                                        blktap_vma->vm_page_prot,
   5.194 +                                        ID_TO_DOM(req->id));
   5.195 +        if ( error != 0 ) {
   5.196 +            printk(KERN_INFO "remapping attached page failed! (%d)\n", error);
   5.197 +            /* the request is now dropped on the floor. */
   5.198 +            return 0;
   5.199 +        }
   5.200 +    }
   5.201 +    
   5.202 +    blktap_ufe_ring.req_prod_pvt++;
   5.203 +    
   5.204 +    return 0;
   5.205 +}
   5.206 +
   5.207 +int blktap_write_be_ring(blkif_response_t *rsp)
   5.208 +{
   5.209 +    blkif_response_t *target;
   5.210 +
   5.211 +    /*
   5.212 +     * This is called to pass a request from the real backend domain's
   5.213 +     * blkif ring to the character device.
   5.214 +     */
   5.215 +
   5.216 +    if ( ! blktap_ring_ok ) {
   5.217 +        DPRINTK("blktap: be_ring not ready for a request!\n");
   5.218 +        return 0;
   5.219 +    }
   5.220 +
   5.221 +    /* No test for fullness in the response direction. */
   5.222 +
   5.223 +    //target = RING_NEXT_EMPTY_RESPONSE(BLKIF_RING, &blktap_ube_ring);
   5.224 +    target = RING_GET_RESPONSE(BLKIF_RING, &blktap_ube_ring,
   5.225 +            blktap_ube_ring.rsp_prod_pvt);
   5.226 +    memcpy(target, rsp, sizeof(*rsp));
   5.227 +
   5.228 +    /* no mapping -- pages were mapped in blktap_write_fe_ring() */
   5.229 +
   5.230 +    blktap_ube_ring.rsp_prod_pvt++;
   5.231 +    
   5.232 +    return 0;
   5.233 +}
   5.234 +
   5.235 +int blktap_read_fe_ring(void)
   5.236 +{
   5.237 +    /* This is called to read responses from the UFE ring. */
   5.238 +
   5.239 +    RING_IDX i, rp;
   5.240 +    blkif_response_t *resp_s;
   5.241 +    blkif_t *blkif;
   5.242 +    active_req_t *ar;
   5.243 +
   5.244 +    DPRINTK("blktap_read_fe_ring()\n");
   5.245 +
   5.246 +    /* if we are forwarding from UFERring to FERing */
   5.247 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
   5.248 +
   5.249 +        /* for each outstanding message on the UFEring  */
   5.250 +        //RING_FOREACH_RESPONSE(BLKIF_RING, &blktap_ufe_ring, prod, resp_s) {
   5.251 +        rp = blktap_ufe_ring.sring->rsp_prod;
   5.252 +        rmb();
   5.253 +        
   5.254 +        for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
   5.255 +        {
   5.256 +            resp_s = RING_GET_RESPONSE(BLKIF_RING, &blktap_ufe_ring, i);
   5.257 +            
   5.258 +            DPRINTK("resp->fe_ring\n");
   5.259 +            ar = lookup_active_req(ID_TO_IDX(resp_s->id));
   5.260 +            blkif = ar->blkif;
   5.261 +            write_resp_to_fe_ring(blkif, resp_s);
   5.262 +            kick_fe_domain(blkif);
   5.263 +        }
   5.264 +        
   5.265 +        blktap_ufe_ring.rsp_cons = i;
   5.266 +    }
   5.267 +    return 0;
   5.268 +}
   5.269 +
   5.270 +int blktap_read_be_ring(void)
   5.271 +{
   5.272 +    /* This is called to read requests from the UBE ring. */
   5.273 +
   5.274 +    RING_IDX i, rp;
   5.275 +    blkif_request_t *req_s;
   5.276 +
   5.277 +    DPRINTK("blktap_read_be_ring()\n");
   5.278 +
   5.279 +    /* if we are forwarding from UFERring to FERing */
   5.280 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
   5.281 +
   5.282 +        /* for each outstanding message on the UFEring  */
   5.283 +        //RING_FOREACH_REQUEST(BLKIF_RING, &blktap_ube_ring, prod, req_s) {
   5.284 +        rp = blktap_ube_ring.sring->req_prod;
   5.285 +        rmb();
   5.286 +        for ( i = blktap_ube_ring.req_cons; i != rp; i++ )
   5.287 +        {
   5.288 +            req_s = RING_GET_REQUEST(BLKIF_RING, &blktap_ube_ring, i);
   5.289 +
   5.290 +            DPRINTK("req->be_ring\n");
   5.291 +            write_req_to_be_ring(req_s);
   5.292 +            kick_be_domain();
   5.293 +        }
   5.294 +        
   5.295 +        blktap_ube_ring.req_cons = i;
   5.296 +    }
   5.297 +
   5.298 +    return 0;
   5.299 +}
   5.300  /* -------[ blktap module setup ]------------------------------------- */
   5.301  
   5.302  static struct miscdevice blktap_miscdev = {