]> xenbits.xensource.com Git - people/royger/linux-2.6.18-xen.git/commitdiff
xen/blktap: fix cleanup after unclean application exit
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 19 Apr 2010 16:19:23 +0000 (17:19 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 19 Apr 2010 16:19:23 +0000 (17:19 +0100)
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 <jbeulich@novell.com>
drivers/xen/blktap/blktap.c

index ab8574354cc6e1b690ba06f4e868f53425245f19..04e79d7c860e21a43ca585ec2a11c5b37fa0e0d8 100644 (file)
@@ -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;
 }