ia64/xen-unstable
changeset 3421:70b803ca7d24
bitkeeper revision 1.1159.219.1 (41e4eca6eauLGi5osqpDb_OmwLgatA)
Some fixes and cleanups to the blktap code.
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 = {