From: Keir Fraser Date: Mon, 19 Apr 2010 16:19:23 +0000 (+0100) Subject: xen/blktap: fix cleanup after unclean application exit X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=4ee3e25985bf61cd3a351b32d19d8475e2254e85;p=legacy%2Flinux-2.6.18-xen.git xen/blktap: fix cleanup after unclean application exit When an application using blktap devices doesn't close the file handle (or mmap-s) of /dev/xen/blktapN, we cannot defer the mmput() on the stored mm until blktap_release(), as that will never be called without the mm's reference count dropping to zero. Signed-off-by: Jan Beulich --- diff --git a/drivers/xen/blktap/blktap.c b/drivers/xen/blktap/blktap.c index ab857435..04e79d7c 100644 --- a/drivers/xen/blktap/blktap.c +++ b/drivers/xen/blktap/blktap.c @@ -637,6 +637,7 @@ static int blktap_open(struct inode *inode, struct file *filp) static int blktap_release(struct inode *inode, struct file *filp) { tap_blkif_t *info = filp->private_data; + struct mm_struct *mm; /* check for control device */ if (!info) @@ -645,7 +646,9 @@ static int blktap_release(struct inode *inode, struct file *filp) info->ring_ok = 0; smp_wmb(); - mmput(info->mm); + mm = xchg(&info->mm, NULL); + if (mm) + mmput(mm); info->mm = NULL; kfree(info->foreign_map.map); info->foreign_map.map = NULL; @@ -1087,7 +1090,7 @@ static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx, INVALID_P2M_ENTRY); } - if (khandle->user != INVALID_GRANT_HANDLE) { + if (mm != NULL && khandle->user != INVALID_GRANT_HANDLE) { BUG_ON(xen_feature(XENFEAT_auto_translated_physmap)); if (!locked++) down_write(&mm->mmap_sem); @@ -1144,6 +1147,7 @@ static void print_stats(blkif_t *blkif) int tap_blkif_schedule(void *arg) { blkif_t *blkif = arg; + tap_blkif_t *info; blkif_get(blkif); @@ -1177,8 +1181,16 @@ int tap_blkif_schedule(void *arg) printk(KERN_DEBUG "%s: exiting\n", current->comm); blkif->xenblkd = NULL; + info = tapfds[blkif->dev_num]; blkif_put(blkif); + if (info) { + struct mm_struct *mm = xchg(&info->mm, NULL); + + if (mm) + mmput(mm); + } + return 0; }