[BLKTAP] avoid race between tapdisk and xvd daemon with ufe_ring.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 7 Nov 2006 11:14:52 +0000 (11:14 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 7 Nov 2006 11:14:52 +0000 (11:14 +0000)
- Tapdisk updates rsp_cons by ioctl(). on the other hand xvd daemon
  reads rsp_cons in do_block_io_op() with RING_FULL().
  Copy request and memory barrier before updating rsp_cons.
- Tapdisk access req_prod_pvt with select(). on the other hand xvd
  daemon updates it in do_block_io_op().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c

index d8bf0919348093575969b55f1c72432db7581c6c..48c3f7988915330d33fca96d80500acee15f619d 100644 (file)
@@ -538,8 +538,10 @@ static int blktap_release(struct inode *inode, struct file *filp)
        }
        
        if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) {
-               kthread_stop(info->blkif->xenblkd);
-               info->blkif->xenblkd = NULL;
+               if (info->blkif->xenblkd != NULL) {
+                       kthread_stop(info->blkif->xenblkd);
+                       info->blkif->xenblkd = NULL;
+               }
                info->status = CLEANSHUTDOWN;
        }       
        return 0;
@@ -1007,11 +1009,14 @@ static int blktap_read_ufe_ring(tap_blkif_t *info)
        rmb();
         
        for (i = info->ufe_ring.rsp_cons; i != rp; i++) {
+               blkif_response_t res;
                resp = RING_GET_RESPONSE(&info->ufe_ring, i);
+               memcpy(&res, resp, sizeof(res));
+               mb(); /* rsp_cons read by RING_FULL() in do_block_io_op(). */
                ++info->ufe_ring.rsp_cons;
 
                /*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/
-               usr_idx = (int)resp->id;
+               usr_idx = (int)res.id;
                pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx]));
                mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]);
 
@@ -1044,8 +1049,8 @@ static int blktap_read_ufe_ring(tap_blkif_t *info)
                        map[offset] = NULL;
                }
                fast_flush_area(pending_req, pending_idx, usr_idx, info->minor);
-               make_response(blkif, pending_req->id, resp->operation,
-                             resp->status);
+               make_response(blkif, pending_req->id, res.operation,
+                             res.status);
                info->idx_map[usr_idx] = INVALID_REQ;
                blkif_put(pending_req->blkif);
                free_req(pending_req);
@@ -1330,6 +1335,7 @@ static void dispatch_rw_block_io(blkif_t *blkif,
                                  info->ufe_ring.req_prod_pvt);
        memcpy(target, req, sizeof(*req));
        target->id = usr_idx;
+       wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */
        info->ufe_ring.req_prod_pvt++;
        return;