Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4341

kernel-2.6.18-194.11.1.el5.src.rpm

From: Stephen C. Tweedie <sct@redhat.com>
Subject: [RHEL-5 Patch 2/2] Update xen paravirt framebuffer to upstream protocol, attempt #2
Date: Fri, 15 Dec 2006 15:05:40 +0000
Bugzilla: 218048
Message-Id: <1166195140.6246.25.camel@sisko.scot.redhat.com>
Changelog: xen: Update xen paravirt framebuffer to upstream protocol (fixes)


Hi,

This is the 2nd posting of the xen PV-FB patch, updated to apply
cleanly against current RHEL-5 CVS HEAD.  Addresses kernel side of
blocker bug 218048.  The patch below should be dropped into CVS as
linux-2.6-xen-pvfb-fixes.patch, and contains purely locking changes
since Wednesday's four-patch posting, to address the problems identified
then (mainly the calling of zap_page_range from within a spinlock.)
Full description of the locking issue already posted on virtualist.

--Stephen


--- linux-2.6.18.noarch/drivers/xen/fbfront/xenfb.c.~1~	2006-12-15 14:32:32.000000000 +0000
+++ linux-2.6.18.noarch/drivers/xen/fbfront/xenfb.c	2006-12-15 14:33:45.000000000 +0000
@@ -49,8 +49,9 @@ struct xenfb_info
 	struct timer_list	refresh;
 	int			dirty;
 	int			x1, y1, x2, y2;	/* dirty rectangle,
-						   protected by mm_lock */
-	spinlock_t		mm_lock;
+						   protected by dirty_lock */
+	spinlock_t		dirty_lock;
+	struct mutex		mm_lock;
 	int			nr_pages;
 	struct page		**pages;
 	struct list_head	mappings; /* protected by mm_lock */
@@ -114,14 +115,16 @@ static void xenfb_update_screen(struct x
 	if (xenfb_queue_full(info))
 		return;
 
-	spin_lock_irqsave(&info->mm_lock, flags);
+	mutex_lock(&info->mm_lock);
 
+	spin_lock_irqsave(&info->dirty_lock, flags);
 	y1 = info->y1;
 	y2 = info->y2;
 	x1 = info->x1;
 	x2 = info->x2;
 	info->x1 = info->y1 = INT_MAX;
 	info->x2 = info->y2 = 0;
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
 
 	list_for_each_entry(map, &info->mappings, link) {
 		if (!map->faults)
@@ -131,7 +134,7 @@ static void xenfb_update_screen(struct x
 		map->faults = 0;
 	}
 
-	spin_unlock_irqrestore(&info->mm_lock, flags);
+	mutex_unlock(&info->mm_lock);
 
 	xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
 }
@@ -216,9 +219,9 @@ static void xenfb_refresh(struct xenfb_i
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&info->mm_lock, flags);
+	spin_lock_irqsave(&info->dirty_lock, flags);
 	__xenfb_refresh(info, x1, y1, w, h);
-	spin_unlock_irqrestore(&info->mm_lock, flags);
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
 }
 
 static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
@@ -255,14 +258,13 @@ static void xenfb_vm_close(struct vm_are
 {
 	struct xenfb_mapping *map = vma->vm_private_data;
 	struct xenfb_info *info = map->info;
-	unsigned long flags;
 
-	spin_lock_irqsave(&info->mm_lock, flags);
+	mutex_lock(&info->mm_lock);
 	if (atomic_dec_and_test(&map->map_refs)) {
 		list_del(&map->link);
 		kfree(map);
 	}
-	spin_unlock_irqrestore(&info->mm_lock, flags);
+	mutex_unlock(&info->mm_lock);
 }
 
 static struct page *xenfb_vm_nopage(struct vm_area_struct *vma,
@@ -278,7 +280,8 @@ static struct page *xenfb_vm_nopage(stru
 	if (pgnr >= info->nr_pages)
 		return NOPAGE_SIGBUS;
 
-	spin_lock_irqsave(&info->mm_lock, flags);
+	mutex_lock(&info->mm_lock);
+	spin_lock_irqsave(&info->dirty_lock, flags);
 	page = info->pages[pgnr];
 	get_page(page);
 	map->faults++;
@@ -288,7 +291,8 @@ static struct page *xenfb_vm_nopage(stru
 	if (y2 > info->fb_info->var.yres)
 		y2 = info->fb_info->var.yres;
 	__xenfb_refresh(info, 0, y1, info->fb_info->var.xres, y2 - y1);
-	spin_unlock_irqrestore(&info->mm_lock, flags);
+	spin_unlock_irqrestore(&info->dirty_lock, flags);
+	mutex_unlock(&info->mm_lock);
 
 	if (type)
 		*type = VM_FAULT_MINOR;
@@ -305,7 +309,6 @@ static struct vm_operations_struct xenfb
 static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma)
 {
 	struct xenfb_info *info = fb_info->par;
-	unsigned long flags;
 	struct xenfb_mapping *map;
 	int map_pages;
 
@@ -329,9 +332,9 @@ static int xenfb_mmap(struct fb_info *fb
 	map->info = info;
 	atomic_set(&map->map_refs, 1);
 
-	spin_lock_irqsave(&info->mm_lock, flags);
+	mutex_lock(&info->mm_lock);
 	list_add(&map->link, &info->mappings);
-	spin_unlock_irqrestore(&info->mm_lock, flags);
+	mutex_unlock(&info->mm_lock);
 
 	vma->vm_ops = &xenfb_vm_ops;
 	vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED);
@@ -388,7 +391,8 @@ static int __devinit xenfb_probe(struct 
 	info->xbdev = dev;
 	info->irq = -1;
 	info->x1 = info->y1 = INT_MAX;
-	spin_lock_init(&info->mm_lock);
+	spin_lock_init(&info->dirty_lock);
+	mutex_init(&info->mm_lock);
 	init_waitqueue_head(&info->wq);
 	init_timer(&info->refresh);
 	info->refresh.function = xenfb_timer;