# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1225894117 0
# Node ID be9555ea5512d801a50f075037806a37ce17c209
# Parent 2fb13b8cbe134fdb3f18ee21e641e52655066c62
blktap: ensure vma->vm_mm's mmap_sem is being held whenever it is being modified
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
drivers/xen/blktap/blktap.c | 43 +++++++++++++++++++++++++++++++++----------
1 files changed, 33 insertions(+), 10 deletions(-)
diff -r 2fb13b8cbe13 -r be9555ea5512 drivers/xen/blktap/blktap.c
--- a/drivers/xen/blktap/blktap.c Thu Oct 30 13:34:43 2008 +0000
+++ b/drivers/xen/blktap/blktap.c Wed Nov 05 14:08:37 2008 +0000
@@ -611,9 +611,13 @@ static int blktap_release(struct inode *
/* Clear any active mappings and free foreign map table */
if (info->vma) {
+ struct mm_struct *mm = info->vma->vm_mm;
+
+ down_write(&mm->mmap_sem);
zap_page_range(
info->vma, info->vma->vm_start,
info->vma->vm_end - info->vma->vm_start, NULL);
+ up_write(&mm->mmap_sem);
kfree(info->vma->vm_private_data);
@@ -992,12 +996,13 @@ static void fast_flush_area(pending_req_
int tapidx)
{
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- unsigned int i, invcount = 0;
+ unsigned int i, invcount = 0, locked = 0;
struct grant_handle_pair *khandle;
uint64_t ptep;
int ret, mmap_idx;
unsigned long kvaddr, uvaddr;
tap_blkif_t *info;
+ struct mm_struct *mm;
info = tapfds[tapidx];
@@ -1007,13 +1012,15 @@ static void fast_flush_area(pending_req_
return;
}
+ mm = info->vma ? info->vma->vm_mm : NULL;
+
if (info->vma != NULL &&
xen_feature(XENFEAT_auto_translated_physmap)) {
- down_write(&info->vma->vm_mm->mmap_sem);
+ down_write(&mm->mmap_sem);
zap_page_range(info->vma,
MMAP_VADDR(info->user_vstart, u_idx, 0),
req->nr_pages << PAGE_SHIFT, NULL);
- up_write(&info->vma->vm_mm->mmap_sem);
+ up_write(&mm->mmap_sem);
return;
}
@@ -1038,10 +1045,13 @@ static void fast_flush_area(pending_req_
if (khandle->user != INVALID_GRANT_HANDLE) {
BUG_ON(xen_feature(XENFEAT_auto_translated_physmap));
+ if (!locked++)
+ down_write(&mm->mmap_sem);
if (create_lookup_pte_addr(
- info->vma->vm_mm,
+ mm,
MMAP_VADDR(info->user_vstart, u_idx, i),
&ptep) !=0) {
+ up_write(&mm->mmap_sem);
WPRINTK("Couldn't get a pte addr!\n");
return;
}
@@ -1060,10 +1070,17 @@ static void fast_flush_area(pending_req_
GNTTABOP_unmap_grant_ref, unmap, invcount);
BUG_ON(ret);
- if (info->vma != NULL && !xen_feature(XENFEAT_auto_translated_physmap))
+ if (info->vma != NULL &&
+ !xen_feature(XENFEAT_auto_translated_physmap)) {
+ if (!locked++)
+ down_write(&mm->mmap_sem);
zap_page_range(info->vma,
MMAP_VADDR(info->user_vstart, u_idx, 0),
req->nr_pages << PAGE_SHIFT, NULL);
+ }
+
+ if (locked)
+ up_write(&mm->mmap_sem);
}
/******************************************************************
@@ -1346,6 +1363,7 @@ static void dispatch_rw_block_io(blkif_t
int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
int usr_idx;
uint16_t mmap_idx = pending_req->mem_idx;
+ struct mm_struct *mm;
if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV)
goto fail_response;
@@ -1389,6 +1407,9 @@ static void dispatch_rw_block_io(blkif_t
pending_req->status = BLKIF_RSP_OKAY;
pending_req->nr_pages = nseg;
op = 0;
+ mm = info->vma->vm_mm;
+ if (!xen_feature(XENFEAT_auto_translated_physmap))
+ down_write(&mm->mmap_sem);
for (i = 0; i < nseg; i++) {
unsigned long uvaddr;
unsigned long kvaddr;
@@ -1407,9 +1428,9 @@ static void dispatch_rw_block_io(blkif_t
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
/* Now map it to user. */
- ret = create_lookup_pte_addr(info->vma->vm_mm,
- uvaddr, &ptep);
+ ret = create_lookup_pte_addr(mm, uvaddr, &ptep);
if (ret) {
+ up_write(&mm->mmap_sem);
WPRINTK("Couldn't get a pte addr!\n");
goto fail_flush;
}
@@ -1431,6 +1452,8 @@ static void dispatch_rw_block_io(blkif_t
BUG_ON(ret);
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ up_write(&mm->mmap_sem);
+
for (i = 0; i < (nseg*2); i+=2) {
unsigned long uvaddr;
unsigned long kvaddr;
@@ -1504,7 +1527,7 @@ static void dispatch_rw_block_io(blkif_t
goto fail_flush;
if (xen_feature(XENFEAT_auto_translated_physmap))
- down_write(&info->vma->vm_mm->mmap_sem);
+ down_write(&mm->mmap_sem);
/* Mark mapped pages as reserved: */
for (i = 0; i < req->nr_segments; i++) {
unsigned long kvaddr;
@@ -1518,13 +1541,13 @@ static void dispatch_rw_block_io(blkif_t
MMAP_VADDR(info->user_vstart,
usr_idx, i), pg);
if (ret) {
- up_write(&info->vma->vm_mm->mmap_sem);
+ up_write(&mm->mmap_sem);
goto fail_flush;
}
}
}
if (xen_feature(XENFEAT_auto_translated_physmap))
- up_write(&info->vma->vm_mm->mmap_sem);
+ up_write(&mm->mmap_sem);
/*record [mmap_idx,pending_idx] to [usr_idx] mapping*/
info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|