Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Tetsu Yamamoto <tyamamot@redhat.com>
Date: Mon, 21 Jan 2008 20:48:22 -0500
Subject: [xen] ia64: create 100GB mem guest, HV softlockup
Message-id: 20080121165209.15518.41360.sendpatchset@dhcp83-164.boston.redhat.com
O-Subject: [RHEL5.2 PATCH 2/4][Take2] Cannot create guest having 100GB memory on Xen-ia64
Bugzilla: 251353

# HG changeset patch
# User Alex Williamson <alex.williamson@hp.com>
# Date 1193156491 21600
# Node ID f9772037c2e7d4bef6585fedafa13929497b5656
# Parent  d105b8c30b7dc81cfaa6564c204b9d275fa7fee5
[IA64] Prevent softlock when destroying VTi domain

Prevent softlock up when VTi domain destruction by making
relinquish_memory() continuable.  It was assumed that
mm_teardown() frees most of page_list so that the list which
is passed to relinquish_memory() is short.  However the
assumption isn't true for VTi domain case because qemu-dm
maps all the domain pages.  To avoid softlock up message,
make relinquish_memory() continuable.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>

Acked-by: Bill Burns <bburns@redhat.com>
Acked-by: "Stephen C. Tweedie" <sct@redhat.com>

diff --git a/arch/ia64/xen/domain.c b/arch/ia64/xen/domain.c
index 5a966df..b03e265 100644
--- a/arch/ia64/xen/domain.c
+++ b/arch/ia64/xen/domain.c
@@ -562,7 +562,9 @@ int arch_domain_create(struct domain *d)
 		goto fail_nomem;
 
 	memset(&d->arch.mm, 0, sizeof(d->arch.mm));
+ 	d->arch.relres = RELRES_not_started;
         d->arch.mm_teardown_offset = 0;
+ 	INIT_LIST_HEAD(&d->arch.relmem_list);
 
 	if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL)
 	    goto fail_nomem;
@@ -705,13 +707,14 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 	return 0;
 }
 
-static void relinquish_memory(struct domain *d, struct list_head *list)
+static int relinquish_memory(struct domain *d, struct list_head *list)
 {
     struct list_head *ent;
     struct page_info *page;
 #ifndef __ia64__
     unsigned long     x, y;
 #endif
+    int               ret = 0;
 
     /* Use a recursive lock, as we may enter 'free_domheap_page'. */
     spin_lock_recursive(&d->page_alloc_lock);
@@ -724,6 +727,7 @@ static void relinquish_memory(struct domain *d, struct list_head *list)
         {
             /* Couldn't get a reference -- someone is freeing this page. */
             ent = ent->next;
+            list_move_tail(&page->list, &d->arch.relmem_list);
             continue;
         }
 
@@ -760,35 +764,72 @@ static void relinquish_memory(struct domain *d, struct list_head *list)
         /* Follow the list chain and /then/ potentially free the page. */
         ent = ent->next;
         BUG_ON(get_gpfn_from_mfn(page_to_mfn(page)) != INVALID_M2P_ENTRY);
+        list_move_tail(&page->list, &d->arch.relmem_list);
         put_page(page);
+
+        if (hypercall_preempt_check()) {
+                ret = -EAGAIN;
+                goto out;
+        }
     }
 
+    list_splice_init(&d->arch.relmem_list, list);
+
+ out:
     spin_unlock_recursive(&d->page_alloc_lock);
+    return ret;
 }
 
 int domain_relinquish_resources(struct domain *d)
 {
-    int ret;
-    /* Relinquish guest resources for VT-i domain. */
-    if (d->arch.is_vti)
-	    vmx_relinquish_guest_resources(d);
-
-    /* Tear down shadow mode stuff. */
-    ret = mm_teardown(d);
-    if (ret != 0)
-        return ret;
+	int ret = 0;
+
+	switch (d->arch.relres) {
+	case RELRES_not_started:
+		/* Relinquish guest resources for VT-i domain. */
+		if (d->arch.is_vti)
+			vmx_relinquish_guest_resources(d);
+		d->arch.relres = RELRES_mm_teardown;
+		/*fallthrough*/
+
+	case RELRES_mm_teardown:
+		/* Tear down shadow mode stuff. */
+		ret = mm_teardown(d);
+		if (ret != 0)
+			return ret;
+		d->arch.relres = RELRES_xen;
+		/* fallthrough */
+
+	case RELRES_xen:
+		/* Relinquish every xen page of memory. */
+		ret = relinquish_memory(d, &d->xenpage_list);
+		if (ret != 0)
+			return ret;
+		d->arch.relres = RELRES_dom;
+		/* fallthrough */
+
+	case RELRES_dom:
+		/* Relinquish every domain page of memory. */
+		ret = relinquish_memory(d, &d->page_list);
+		if (ret != 0)
+			return ret;
+		d->arch.relres = RELRES_done;
+		/* fallthrough */    
+
+	case RELRES_done:
+		break;
 
-    /* Relinquish every page of memory. */
-    relinquish_memory(d, &d->xenpage_list);
-    relinquish_memory(d, &d->page_list);
+	default:
+		BUG();
+	}
 
-    if (d->arch.is_vti && d->arch.sal_data)
-	    xfree(d->arch.sal_data);
+	if (d->arch.is_vti && d->arch.sal_data)
+		xfree(d->arch.sal_data);
 
-    /* Free page used by xen oprofile buffer */
-    free_xenoprof_pages(d);
+	/* Free page used by xen oprofile buffer */
+	free_xenoprof_pages(d);
 
-    return 0;
+	return 0;
 }
 
 unsigned long
diff --git a/include/asm-ia64/domain.h b/include/asm-ia64/domain.h
index 89c3f2d..46f4f28 100644
--- a/include/asm-ia64/domain.h
+++ b/include/asm-ia64/domain.h
@@ -133,7 +133,17 @@ struct arch_domain {
 #endif
 
     /* for domctl_destroy_domain continuation */
+    enum {
+        RELRES_not_started,
+        RELRES_mm_teardown,
+        RELRES_xen,
+        RELRES_dom,
+        RELRES_done,
+    } relres;
+    /* Continuable mm_teardown() */
     unsigned long mm_teardown_offset;
+    /* Continuable domain_relinquish_resources() */
+    struct list_head relmem_list;
 };
 #define INT_ENABLE_OFFSET(v) 		  \
     (sizeof(vcpu_info_t) * (v)->vcpu_id + \