ia64/linux-2.6.18-xen.hg

changeset 721:be9555ea5512

blktap: ensure vma->vm_mm's mmap_sem is being held whenever it is being modified

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 05 14:08:37 2008 +0000 (2008-11-05)
parents 2fb13b8cbe13
children 509d67fe5120
files drivers/xen/blktap/blktap.c
line diff
     1.1 --- a/drivers/xen/blktap/blktap.c	Thu Oct 30 13:34:43 2008 +0000
     1.2 +++ b/drivers/xen/blktap/blktap.c	Wed Nov 05 14:08:37 2008 +0000
     1.3 @@ -611,9 +611,13 @@ static int blktap_release(struct inode *
     1.4  
     1.5  	/* Clear any active mappings and free foreign map table */
     1.6  	if (info->vma) {
     1.7 +		struct mm_struct *mm = info->vma->vm_mm;
     1.8 +
     1.9 +		down_write(&mm->mmap_sem);
    1.10  		zap_page_range(
    1.11  			info->vma, info->vma->vm_start, 
    1.12  			info->vma->vm_end - info->vma->vm_start, NULL);
    1.13 +		up_write(&mm->mmap_sem);
    1.14  
    1.15  		kfree(info->vma->vm_private_data);
    1.16  
    1.17 @@ -992,12 +996,13 @@ static void fast_flush_area(pending_req_
    1.18  			    int tapidx)
    1.19  {
    1.20  	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
    1.21 -	unsigned int i, invcount = 0;
    1.22 +	unsigned int i, invcount = 0, locked = 0;
    1.23  	struct grant_handle_pair *khandle;
    1.24  	uint64_t ptep;
    1.25  	int ret, mmap_idx;
    1.26  	unsigned long kvaddr, uvaddr;
    1.27  	tap_blkif_t *info;
    1.28 +	struct mm_struct *mm;
    1.29  	
    1.30  
    1.31  	info = tapfds[tapidx];
    1.32 @@ -1007,13 +1012,15 @@ static void fast_flush_area(pending_req_
    1.33  		return;
    1.34  	}
    1.35  
    1.36 +	mm = info->vma ? info->vma->vm_mm : NULL;
    1.37 +
    1.38  	if (info->vma != NULL &&
    1.39  	    xen_feature(XENFEAT_auto_translated_physmap)) {
    1.40 -		down_write(&info->vma->vm_mm->mmap_sem);
    1.41 +		down_write(&mm->mmap_sem);
    1.42  		zap_page_range(info->vma, 
    1.43  			       MMAP_VADDR(info->user_vstart, u_idx, 0), 
    1.44  			       req->nr_pages << PAGE_SHIFT, NULL);
    1.45 -		up_write(&info->vma->vm_mm->mmap_sem);
    1.46 +		up_write(&mm->mmap_sem);
    1.47  		return;
    1.48  	}
    1.49  
    1.50 @@ -1038,10 +1045,13 @@ static void fast_flush_area(pending_req_
    1.51  
    1.52  		if (khandle->user != INVALID_GRANT_HANDLE) {
    1.53  			BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
    1.54 +			if (!locked++)
    1.55 +				down_write(&mm->mmap_sem);
    1.56  			if (create_lookup_pte_addr(
    1.57 -				info->vma->vm_mm,
    1.58 +				mm,
    1.59  				MMAP_VADDR(info->user_vstart, u_idx, i),
    1.60  				&ptep) !=0) {
    1.61 +				up_write(&mm->mmap_sem);
    1.62  				WPRINTK("Couldn't get a pte addr!\n");
    1.63  				return;
    1.64  			}
    1.65 @@ -1060,10 +1070,17 @@ static void fast_flush_area(pending_req_
    1.66  		GNTTABOP_unmap_grant_ref, unmap, invcount);
    1.67  	BUG_ON(ret);
    1.68  	
    1.69 -	if (info->vma != NULL && !xen_feature(XENFEAT_auto_translated_physmap))
    1.70 +	if (info->vma != NULL &&
    1.71 +	    !xen_feature(XENFEAT_auto_translated_physmap)) {
    1.72 +		if (!locked++)
    1.73 +			down_write(&mm->mmap_sem);
    1.74  		zap_page_range(info->vma, 
    1.75  			       MMAP_VADDR(info->user_vstart, u_idx, 0), 
    1.76  			       req->nr_pages << PAGE_SHIFT, NULL);
    1.77 +	}
    1.78 +
    1.79 +	if (locked)
    1.80 +		up_write(&mm->mmap_sem);
    1.81  }
    1.82  
    1.83  /******************************************************************
    1.84 @@ -1346,6 +1363,7 @@ static void dispatch_rw_block_io(blkif_t
    1.85  	int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
    1.86  	int usr_idx;
    1.87  	uint16_t mmap_idx = pending_req->mem_idx;
    1.88 +	struct mm_struct *mm;
    1.89  
    1.90  	if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
    1.91  		goto fail_response;
    1.92 @@ -1389,6 +1407,9 @@ static void dispatch_rw_block_io(blkif_t
    1.93  	pending_req->status    = BLKIF_RSP_OKAY;
    1.94  	pending_req->nr_pages  = nseg;
    1.95  	op = 0;
    1.96 +	mm = info->vma->vm_mm;
    1.97 +	if (!xen_feature(XENFEAT_auto_translated_physmap))
    1.98 +		down_write(&mm->mmap_sem);
    1.99  	for (i = 0; i < nseg; i++) {
   1.100  		unsigned long uvaddr;
   1.101  		unsigned long kvaddr;
   1.102 @@ -1407,9 +1428,9 @@ static void dispatch_rw_block_io(blkif_t
   1.103  
   1.104  		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
   1.105  			/* Now map it to user. */
   1.106 -			ret = create_lookup_pte_addr(info->vma->vm_mm, 
   1.107 -						     uvaddr, &ptep);
   1.108 +			ret = create_lookup_pte_addr(mm, uvaddr, &ptep);
   1.109  			if (ret) {
   1.110 +				up_write(&mm->mmap_sem);
   1.111  				WPRINTK("Couldn't get a pte addr!\n");
   1.112  				goto fail_flush;
   1.113  			}
   1.114 @@ -1431,6 +1452,8 @@ static void dispatch_rw_block_io(blkif_t
   1.115  	BUG_ON(ret);
   1.116  
   1.117  	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
   1.118 +		up_write(&mm->mmap_sem);
   1.119 +
   1.120  		for (i = 0; i < (nseg*2); i+=2) {
   1.121  			unsigned long uvaddr;
   1.122  			unsigned long kvaddr;
   1.123 @@ -1504,7 +1527,7 @@ static void dispatch_rw_block_io(blkif_t
   1.124  		goto fail_flush;
   1.125  
   1.126  	if (xen_feature(XENFEAT_auto_translated_physmap))
   1.127 -		down_write(&info->vma->vm_mm->mmap_sem);
   1.128 +		down_write(&mm->mmap_sem);
   1.129  	/* Mark mapped pages as reserved: */
   1.130  	for (i = 0; i < req->nr_segments; i++) {
   1.131  		unsigned long kvaddr;
   1.132 @@ -1518,13 +1541,13 @@ static void dispatch_rw_block_io(blkif_t
   1.133  					     MMAP_VADDR(info->user_vstart,
   1.134  							usr_idx, i), pg);
   1.135  			if (ret) {
   1.136 -				up_write(&info->vma->vm_mm->mmap_sem);
   1.137 +				up_write(&mm->mmap_sem);
   1.138  				goto fail_flush;
   1.139  			}
   1.140  		}
   1.141  	}
   1.142  	if (xen_feature(XENFEAT_auto_translated_physmap))
   1.143 -		up_write(&info->vma->vm_mm->mmap_sem);
   1.144 +		up_write(&mm->mmap_sem);
   1.145  	
   1.146  	/*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
   1.147  	info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);