diff -rubN b/xen/arch/x86/mm/hap/p2m-ept.c a/xen/arch/x86/mm/hap/p2m-ept.c
--- b/xen/arch/x86/mm/hap/p2m-ept.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/arch/x86/mm/hap/p2m-ept.c	2011-01-19 16:36:27.000000000 +0800
@@ -38,17 +38,22 @@
                                       p2m_query_t q)
 {
     int r;
+    int do_locking = !p2m_locked_by_me(d->arch.p2m);
+
+    if(do_locking)
     p2m_lock(d->arch.p2m);
 
     /* Check to make sure this is still PoD */
     if ( entry->avail1 != p2m_populate_on_demand )
     {
+        if(do_locking)
         p2m_unlock(d->arch.p2m);
         return 0;
     }
 
     r = p2m_pod_demand_populate(d, gfn, order, q);
 
+    if(do_locking)
     p2m_unlock(d->arch.p2m);
 
     return r;
diff -rubN b/xen/arch/x86/mm/mem_sharing.c a/xen/arch/x86/mm/mem_sharing.c
--- b/xen/arch/x86/mm/mem_sharing.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/arch/x86/mm/mem_sharing.c	2011-01-30 19:12:24.000000000 +0800
@@ -57,6 +57,7 @@
 
 static shr_handle_t next_handle = 1;
 static atomic_t nr_saved_mfns = ATOMIC_INIT(0); 
+int mem_sharing_debug_mfn(unsigned long mfn);
 
 typedef struct shr_hash_entry 
 {
@@ -168,6 +169,65 @@
     xfree(gfn);
 }
 
+static shr_hash_entry_t* mem_sharing_hash_lookup_by_gfn(
+                            struct domain *d,
+                            unsigned long gfn 
+        )
+{
+    shr_hash_entry_t *ce;
+    int i;
+ 
+    for(i = 0; i < SHR_HASH_LENGTH; i++){
+        ce = shr_hash[i];
+        while(ce != NULL)
+        {
+            struct list_head *le, *te;
+            struct gfn_info *sgfn;
+            list_for_each_safe(le, te, &ce->gfns)
+            {
+                sgfn = list_entry(le, struct gfn_info, list);
+                if(sgfn->domain == d->domain_id && sgfn->gfn == gfn){
+                    mem_sharing_debug_mfn(mfn_x(ce->mfn));
+                    printk("gfn handle %lu\n", ce->handle);
+                }
+            }
+            ce = ce->next;
+        }
+    }
+
+    return NULL;
+}
+static unsigned long mem_sharing_hash_lookup_by_mfn(
+        unsigned long mfn
+        )
+{
+    shr_hash_entry_t *ce;
+    int i;
+ 
+    for(i = 0; i < SHR_HASH_LENGTH; i++){
+        ce = shr_hash[i];
+        while(ce != NULL )
+        {
+            if(mfn_x(ce->mfn) == mfn){
+                struct list_head *le, *te;
+                struct gfn_info *sgfn = NULL;
+                mem_sharing_debug_mfn(mfn_x(ce->mfn));
+                printk("handle %lu ", ce->handle);
+                list_for_each_safe(le, te, &ce->gfns)
+                {
+                    sgfn = list_entry(le, struct gfn_info, list);
+                    printk("did %u, gfn %lu ", sgfn->domain, sgfn->gfn);
+                }
+                printk("end\n");
+                return sgfn->gfn;
+            }
+            ce = ce->next;
+        }
+    }
+
+    return 0;
+}
+
 static shr_hash_entry_t* mem_sharing_hash_lookup(shr_handle_t handle)
 {
     shr_hash_entry_t *e;
@@ -183,6 +243,73 @@
     return NULL;
 }
 
+void mem_sharing_hash_iter_detail(void)
+{
+    shr_hash_entry_t *ce;
+    int i,j;
+    int count_e= 0;
+
+    shr_lock();
+    j = 0;
+    for(i = 0; i < SHR_HASH_LENGTH; i++){
+
+        ce = shr_hash[i];
+        if(ce && ce->next != NULL)
+            printk("===> %d <==== ", i);
+
+        while(ce != NULL)
+        {
+            struct list_head *le, *te;
+            struct gfn_info *gfn;
+            j = 0;
+            printk("--%lu--", ce->handle);
+            list_for_each_safe(le, te, &ce->gfns)
+            {
+                gfn = list_entry(le, struct gfn_info, list);
+                j++;
+                printk("%d ", gfn->domain);
+            }
+            printk(",(%d)\n", j);
+            count_e++;
+            ce = ce->next;
+        }
+    }
+    printk("===>total handles %d total gfns %d next_handle %lu\n", count_e, j, next_handle);
+    shr_unlock();
+}
+
+
+void mem_sharing_hash_iter(void)
+{
+    shr_hash_entry_t *ce;
+    int i,j;
+    int count_e= 0;
+
+    shr_lock();
+    j = 0;
+    for(i = 0; i < SHR_HASH_LENGTH; i++){
+//      printk("========> %d <\n", i);
+        ce = shr_hash[i];
+        while(ce != NULL)
+        {
+            struct list_head *le, *te;
+            struct gfn_info *gfn;
+//          printk("--%lu--", ce->handle);
+            list_for_each_safe(le, te, &ce->gfns)
+            {
+                gfn = list_entry(le, struct gfn_info, list);
+                j++;
+//              printk("%d ", gfn->domain);
+            }
+//          printk(",(%d)\n", j);
+            count_e++;
+            ce = ce->next;
+        }
+    }
+    printk("===>total handles %d total gfns %d next_handle: %lu\n", count_e, j, next_handle);
+    shr_unlock();
+}
+
 static shr_hash_entry_t* mem_sharing_hash_insert(shr_handle_t handle, mfn_t mfn)
 {
     shr_hash_entry_t *e, **ee;
@@ -293,6 +420,7 @@
 #endif
 
 
+extern void pagealloc_info(unsigned char key);
 static struct page_info* mem_sharing_alloc_page(struct domain *d, 
                                                 unsigned long gfn,
                                                 int must_succeed)
@@ -310,6 +438,7 @@
         /* We do not support 'must_succeed' any more. External operations such
          * as grant table mappings may fail with OOM condition! 
          */
+        pagealloc_info('m');
         BUG();
     }
     else
@@ -402,7 +531,7 @@
 static grant_entry_header_t *
 shared_entry_header(struct grant_table *t, grant_ref_t ref)
 {
-    ASSERT(t->gt_version != 0);
+    BUG_ON(t->gt_version == 0);
     if (t->gt_version == 1)
         return (grant_entry_header_t*)&shared_entry_v1(t, ref);
     else
@@ -451,16 +580,18 @@
     if(list_has_one_entry(&gfn->list))
     {
         d = get_domain_by_id(gfn->domain);
+        if(!d){
+            printk("========>did is %d\n", gfn->domain);
+            return -1;
+        }
         BUG_ON(!d);
         if(sharing) 
             atomic_inc(&d->shr_pages);
         else
             atomic_dec(&d->shr_pages);
         put_domain(d);
-
         return 1;
     }
-    mem_sharing_audit();
 
     return 0;
 }
@@ -505,6 +636,7 @@
 
     *phandle = 0UL;
 
+    shr_lock();
     mfn = gfn_to_mfn(d, gfn, &p2mt);
 
     /* Check if mfn is valid */
@@ -512,29 +644,33 @@
     if (!mfn_valid(mfn))
         goto out;
 
+    /* Return the handle if the page is already shared */
+    page = mfn_to_page(mfn);
+    if (p2m_is_shared(p2mt)) {
+        *phandle = page->shr_handle;
+        ret = 0;
+        goto out;
+    }
+
     /* Check p2m type */
     if (!p2m_is_sharable(p2mt))
         goto out;
 
     /* Try to convert the mfn to the sharable type */
-    page = mfn_to_page(mfn);
     ret = page_make_sharable(d, page, expected_refcnt); 
     if(ret) 
         goto out;
 
     /* Create the handle */
     ret = -ENOMEM;
-    shr_lock(); 
     handle = next_handle++;  
     if((hash_entry = mem_sharing_hash_insert(handle, mfn)) == NULL)
     {
-        shr_unlock();
         goto out;
     }
     if((gfn_info = mem_sharing_gfn_alloc()) == NULL)
     {
         mem_sharing_hash_destroy(hash_entry);
-        shr_unlock();
         goto out;
     }
 
@@ -545,10 +681,14 @@
          * it a few lines above.
          * The mfn needs to revert back to rw type. This should never fail,
          * since no-one knew that the mfn was temporarily sharable */
+    
+        printk("==make share fail");
+        mem_sharing_debug_gfn(d, gfn);
         BUG_ON(page_make_private(d, page) != 0);
         mem_sharing_hash_destroy(hash_entry);
         mem_sharing_gfn_destroy(gfn_info, 0);
-        shr_unlock();
+        printk("==make share fail2");
+        mem_sharing_debug_gfn(d, gfn);
         goto out;
     }
 
@@ -562,11 +702,13 @@
     gfn_info->domain = d->domain_id;
     page->shr_handle = handle;
     *phandle = handle;
-    shr_unlock();
 
     ret = 0;
 
 out:
+    shr_unlock();
+    if(0)
+        mem_sharing_hash_lookup_by_mfn(mfn_x(mfn));
     return ret;
 }
 
@@ -575,9 +717,16 @@
     shr_hash_entry_t *se, *ce;
     struct page_info *spage, *cpage;
     struct list_head *le, *te;
-    struct gfn_info *gfn;
-    struct domain *d;
+    struct gfn_info *gfn = NULL;
+    struct domain *cd = NULL;
+    struct domain *sd = NULL;
+    struct gfn_info *sgfn;
     int ret;
+    int count = 0;
+
+    BUG_ON(ch == sh);
+    BUG_ON(ch > next_handle);
+    BUG_ON(sh > next_handle);
 
     shr_lock();
 
@@ -590,30 +739,97 @@
     spage = mfn_to_page(se->mfn); 
     cpage = mfn_to_page(ce->mfn); 
     /* gfn lists always have at least one entry => save to call list_entry */
-    mem_sharing_gfn_account(gfn_get_info(&ce->gfns), 1);
-    mem_sharing_gfn_account(gfn_get_info(&se->gfns), 1);
+    gfn = gfn_get_info(&ce->gfns);
+    if(!list_has_one_entry(&gfn->list)){
+        list_for_each_safe(le, te, &ce->gfns)
+        gfn = list_entry(le, struct gfn_info, list);
+        printk("gfn %lx did %u\n", gfn->gfn, gfn->domain);
+        BUG();
+    }
+
+    if(mem_sharing_gfn_account(gfn_get_info(&ce->gfns), 1) == -1){
+        printk("=====client not found, server %d client %d\n", gfn_get_info(&se->gfns)->domain, gfn_get_info(&ce->gfns)->domain);
+        ret = XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID;
+        goto err_out;
+    }
+
+    sgfn = gfn_get_info(&se->gfns);
+    if(mem_sharing_gfn_account(sgfn, 1)==-1){
+        printk("=====server not found, server %d client %d\n", gfn_get_info(&se->gfns)->domain, gfn_get_info(&ce->gfns)->domain);
+        ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+        goto err_out;
+    }
+
     list_for_each_safe(le, te, &ce->gfns)
     {
         gfn = list_entry(le, struct gfn_info, list);
         /* Get the source page and type, this should never fail 
          * because we are under shr lock, and got non-null se */
-        BUG_ON(!get_page_and_type(spage, dom_cow, PGT_shared_page));
+        cd = rcu_lock_domain_by_id(gfn->domain);
+        sd = rcu_lock_domain_by_id(sgfn->domain);
+        if(!cd || cd->is_dying || !sd || sd->is_dying){
+            if(!cd)
+                printk("cd is NULL %d\n", gfn->domain);
+            else if(cd->is_dying)
+                printk("cd is dying %d %d\n", cd->is_dying, gfn->domain);
+            else if(!sd)
+                printk("sd is NULL %d\n", gfn->domain);
+            else if(sd->is_dying){
+                printk("sd is dying %d %d %d c %d\n", sd->is_dying, sgfn->domain, gfn->domain, count++);
+            }
+
+            /*release lock if we have d*/
+            if(cd)
+                rcu_unlock_domain(cd);
+            if(sd)
+                rcu_unlock_domain(sd);
+            continue;
+        }
+
+        if(!get_page_and_type(spage, dom_cow, PGT_shared_page)){
+            mem_sharing_debug_gfn(cd, gfn->gfn);
+            mem_sharing_debug_gfn(sd, sgfn->gfn);
+            printk("c->dying %d s->dying %d spage %p se->mfn %lx\n", cd->is_dying, sd->is_dying, spage, se->mfn);
+            printk("Debug page: MFN=%lx is ci=%lx, ti=%lx, owner_id=%d\n",
+                    mfn_x(page_to_mfn(spage)), 
+                    spage->count_info, 
+                    spage->u.inuse.type_info,
+                    page_get_owner(spage)->domain_id);
+            BUG();
+        }
         /* Move the gfn_info from ce list to se list */
         list_del(&gfn->list);
-        d = get_domain_by_id(gfn->domain);
-        BUG_ON(!d);
-        BUG_ON(set_shared_p2m_entry(d, gfn->gfn, se->mfn) == 0);
-        put_domain(d);
+        //d = get_domain_by_id(gfn->domain);
+        //mem_sharing_debug_gfn(d, gfn->gfn);
+        BUG_ON(set_shared_p2m_entry(cd, gfn->gfn, se->mfn) == 0);
         list_add(&gfn->list, &se->gfns);
         put_page_and_type(cpage);
+        rcu_unlock_domain(cd);
+        rcu_unlock_domain(sd);
+        //mem_sharing_debug_gfn(d, gfn->gfn);
     } 
-    ASSERT(list_empty(&ce->gfns));
+    /* Free the client page when no gfn refer to*/
+    if (list_empty(&ce->gfns) && test_and_clear_bit(_PGC_allocated, &cpage->count_info)){
+        put_page(cpage);
     mem_sharing_hash_delete(ch);
     atomic_inc(&nr_saved_mfns);
-    /* Free the client page */
-    if(test_and_clear_bit(_PGC_allocated, &cpage->count_info))
-        put_page(cpage);
     ret = 0;
+    }else{
+        ret = XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID;
+    }
+
+/*    mem_sharing_debug_gfn(d, gfn->gfn);
+    printk("Debug page: MFN=%lx is ci=%lx, ti=%lx, owner_id=%d, h=%lu\n",
+           mfn_x(page_to_mfn(cpage)), 
+           cpage->count_info, 
+           cpage->u.inuse.type_info,
+           page_get_owner(cpage)->domain_id, cpage->shr_handle);
+    printk("Debug page: MFN=%lx is ci=%lx, ti=%lx, owner_id=%d, h=%lu\n",
+           mfn_x(page_to_mfn(cpage)), 
+           spage->count_info, 
+           spage->u.inuse.type_info,
+           page_get_owner(spage)->domain_id, spage->shr_handle);
+*/
     
 err_out:
     shr_unlock();
@@ -634,16 +850,35 @@
     struct gfn_info *gfn_info = NULL;
     shr_handle_t handle;
     struct list_head *le;
+    struct domain *ld = NULL;
 
+    mem_sharing_audit();
+    /* Remove the gfn_info from the list */
+    shr_lock();
     mfn = gfn_to_mfn(d, gfn, &p2mt);
+    /* Has someone already unshared it? */
+
+    if (!p2m_is_shared(p2mt)){
+        printk("===>already unshared, flag %u\n", flags);
+        shr_unlock();
+        return 0;
+    }
+
+    if (!mfn_valid(mfn)){
+        mem_sharing_debug_gfn(d, gfn);
+    }
 
     page = mfn_to_page(mfn);
     handle = page->shr_handle;
  
-    mem_sharing_audit();
     /* Remove the gfn_info from the list */
-    shr_lock();
     hash_entry = mem_sharing_hash_lookup(handle); 
+
+    if(!hash_entry){
+        printk("entry handle %lu\n",handle);
+        mem_sharing_debug_gfn(d, gfn);
+        mem_sharing_hash_lookup_by_gfn(d,gfn);
+    }
     list_for_each(le, &hash_entry->gfns)
     {
         gfn_info = list_entry(le, struct gfn_info, list);
@@ -677,18 +912,51 @@
         return 0;
     }
  
+    ld = rcu_lock_domain_by_id(d->domain_id);                                                                                                         
+    BUG_ON(!ld);
+
     ret = page_make_private(d, page);
     BUG_ON(last_gfn & ret);
     if(ret == 0) goto private_page_found;
         
+    if(ld->is_dying )
+    {
+        if(!ld)
+            printk("d is NULL %d\n", d->domain_id);
+        else
+            printk("d is dying %d %d\n", d->is_dying, d->domain_id);
+
+        /*decrease page type count and destory gfn*/
+        put_page_and_type(page);
+        mem_sharing_gfn_destroy(gfn_info, !last_gfn);
+
+        if(last_gfn) 
+            mem_sharing_hash_delete(handle);
+        else 
+            /* Even though we don't allocate a private page, we have to account
+             * for the MFN that originally backed this PFN. */
+            atomic_dec(&nr_saved_mfns);
+
+        /*set mfn invalid*/
+        printk("did %d gfn %lx to invalid\n", d->domain_id, gfn);
+        BUG_ON(set_shared_p2m_entry_invalid(d, gfn)==0);
+        rcu_unlock_domain(ld);
+        shr_unlock();
+        return -EAGAIN;
+    }
+
     old_page = page;
     page = mem_sharing_alloc_page(d, gfn, flags & MEM_SHARING_MUST_SUCCEED);
-    BUG_ON(!page && (flags & MEM_SHARING_MUST_SUCCEED));
     if(!page) 
     {
+        mem_sharing_debug_gfn(d, gfn);
+        printk("---domain is %d, max_pages %u, total_pages %u \n", d->is_dying, d->max_pages, d->tot_pages);
+        BUG_ON(!d);
+        BUG_ON(!page && (flags & MEM_SHARING_MUST_SUCCEED));
         /* We've failed to obtain memory for private page. Need to re-add the
          * gfn_info to relevant list */
         list_add(&gfn_info->list, &hash_entry->gfns);
+        rcu_unlock_domain(ld);
         shr_unlock();
         return -ENOMEM;
     }
@@ -709,7 +977,6 @@
         mem_sharing_hash_delete(handle);
     else
         atomic_dec(&nr_saved_mfns);
-    shr_unlock();
 
     if(p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) != 
                                                 p2m_ram_shared) 
@@ -719,7 +986,8 @@
     }
     /* Update m2p entry */
     set_gpfn_from_mfn(mfn_x(page_to_mfn(page)), gfn);
-
+    rcu_unlock_domain(ld);
+    shr_unlock();
     return 0;
 }
 
diff -rubN b/xen/arch/x86/mm/p2m.c a/xen/arch/x86/mm/p2m.c
--- b/xen/arch/x86/mm/p2m.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/arch/x86/mm/p2m.c	2011-01-30 22:20:53.000000000 +0800
@@ -1720,6 +1720,8 @@
 #endif
 
     p2m_lock(p2m);
+    printk(KERN_INFO "teardown %d\n",d->domain_id);
+    printk("teardown %d\n",d->domain_id);
 
 
 #ifdef __x86_64__
@@ -2426,11 +2428,35 @@
     return rc;
 }
 
+int
+set_shared_p2m_entry_invalid(struct domain *d, unsigned long gfn)
+{
+    int rc = 0;
+    int need_lock = !p2m_locked_by_me(d->arch.p2m);
+
+    if ( !paging_mode_translate(d) )
+        return 0;
+
+    if ( need_lock ) 
+        p2m_lock(d->arch.p2m);
+    
+    rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0, p2m_invalid);
+
+    if ( need_lock ) 
+        p2m_unlock(d->arch.p2m);
+
+    if ( 0 == rc )
+        gdprintk(XENLOG_ERR,
+            "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx %d\n",
+            gmfn_to_mfn(d, gfn), d->is_dying);
+    return rc;
+}
 #ifdef __x86_64__
 int
 set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
 {
     int rc = 0;
+    int need_lock = !p2m_locked_by_me(d->arch.p2m);
     p2m_type_t ot;
     mfn_t omfn;
 
@@ -2446,7 +2472,15 @@
     set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
 
     P2M_DEBUG("set shared %lx %lx\n", gfn, mfn_x(mfn));
+    if ( need_lock ) 
+        p2m_lock(d->arch.p2m);
+    if(!mfn_valid(mfn)){
+        printk("did %d gfn %lx ==\n", d->domain_id, gfn);
+        BUG();
+    }
     rc = set_p2m_entry(d, gfn, mfn, 0, p2m_ram_shared);
+    if ( need_lock ) 
+        p2m_unlock(d->arch.p2m);
     if ( 0 == rc )
         gdprintk(XENLOG_ERR,
             "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
diff -rubN b/xen/arch/x86/mm.c a/xen/arch/x86/mm.c
--- b/xen/arch/x86/mm.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/arch/x86/mm.c	2011-01-31 11:26:21.000000000 +0800
@@ -116,6 +116,7 @@
 #include <asm/setup.h>
 #include <asm/mem_sharing.h>
 
+extern int mem_sharing_debug_mfn(unsigned long mfn);
 /*
  * Mapping of first 2 or 4 megabytes of memory. This is mapped with 4kB
  * mappings to avoid type conflicts with fixed-range MTRRs covering the
@@ -2342,7 +2343,8 @@
 
                 /* No special validation needed for writable pages. */
                 /* Page tables and GDT/LDT need to be scanned for validity. */
-                if ( type == PGT_writable_page )
+                if ( type == PGT_writable_page || type == 
+                    PGT_shared_page )
                     nx |= PGT_validated;
             }
         }
@@ -3167,15 +3169,12 @@
                     else if ( p2m_ram_shared == l1e_p2mt )
                     {
                         /* Unshare the page for RW foreign mappings */
-                        if ( l1e_get_flags(l1e) & _PAGE_RW )
-                        {
                             rc = mem_sharing_unshare_page(pg_owner, 
                                                           l1e_get_pfn(l1e), 
                                                           0);
                             if ( rc )
                                 break; 
                         }
-                    } 
 #endif
 
                     okay = mod_l1_entry(va, l1e, mfn,
@@ -3857,32 +3856,24 @@
                        struct page_info *page, 
                        int expected_refcnt)
 {
-    unsigned long x, nx, y;
-
-    /* Acquire ref first, so that the page doesn't dissapear from us */
-    if(!get_page(page, d))
-        return -EINVAL;
-
     spin_lock(&d->page_alloc_lock);
 
     /* Change page type and count atomically */
-    y = page->u.inuse.type_info;
-    nx = PGT_shared_page | PGT_validated | 1; 
-    do {
-        x = y;
-        /* We can only change the type if count is zero, and 
-           type is PGT_none */
-        if((x & (PGT_type_mask | PGT_count_mask)) != PGT_none)
+    if (!get_page_and_type(page, d, PGT_shared_page) )
         {
-            put_page(page);
             spin_unlock(&d->page_alloc_lock);
-            return -EEXIST;
+        return -EINVAL;
         }
-        y = cmpxchg(&page->u.inuse.type_info, x, nx);
-    } while(x != y);
 
-    /* Check if the ref count is 2. The first from PGT_allocated, and the second
-     * from get_page at the top of this function */
+    /* Check it wasn't already sharable and undo if it was */
+    if ( (page->u.inuse.type_info & PGT_count_mask) != 1 )
+    {
+        put_page_and_type(page);
+        spin_unlock(&d->page_alloc_lock);
+        return -EEXIST;
+    }
+    /* Check if the ref count is 2. The first from PGT_allocated, and
+       +     * the second from get_page_and_type at the top of this function */
     if(page->count_info != (PGC_allocated | (2 + expected_refcnt)))
     {
         /* Return type count back to zero */
@@ -3895,39 +3886,26 @@
     d->tot_pages--;
     page_list_del(page, &d->page_list);
     spin_unlock(&d->page_alloc_lock);
-
-    /* NOTE: We are not putting the page back. In effect this function acquires
-     * one ref and type ref for the caller */
-
     return 0;
 }
 
 int page_make_private(struct domain *d, struct page_info *page)
 {
-    unsigned long x, y;
-
     if(!get_page(page, dom_cow))
         return -EINVAL;
     
     spin_lock(&d->page_alloc_lock);
 
-    /* Change page type and count atomically */
-    y = page->u.inuse.type_info;
-    do {
-        x = y;
         /* We can only change the type if count is one */
-        if((x & (PGT_type_mask | PGT_count_mask)) != 
-                (PGT_shared_page | 1))
+    if ( (page->u.inuse.type_info & (PGT_type_mask | PGT_count_mask))
+            != (PGT_shared_page | 1) )
         {
             put_page(page);
             spin_unlock(&d->page_alloc_lock);
             return -EEXIST;
         }
-        y = cmpxchg(&page->u.inuse.type_info, x, PGT_none);
-    } while(x != y);
-
-    /* We dropped type ref above, drop one ref count too */
-    put_page(page);
+    /* Drop the final typecount */
+    put_page_and_type(page);
 
     /* Change the owner */
     ASSERT(page_get_owner(page) == dom_cow);
diff -rubN b/xen/common/keyhandler.c a/xen/common/keyhandler.c
--- b/xen/common/keyhandler.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/common/keyhandler.c	2011-01-31 11:10:54.000000000 +0800
@@ -19,6 +19,8 @@
 
 static struct keyhandler *key_table[256];
 static unsigned char keypress_key;
+extern void mem_sharing_hash_iter(void);
+extern void mem_sharing_hash_iter_detail(void);
 
 char keyhandler_scratch[1024];
 
@@ -63,6 +65,7 @@
         if ( key_table[i] != NULL ) 
             printk(" key '%c' (ascii '%02x') => %s\n", 
                    isprint(i) ? i : ' ', i, key_table[i]->desc);
+    mem_sharing_hash_iter();
 }
 
 static struct keyhandler show_handlers_keyhandler = {
@@ -119,6 +122,9 @@
 {
     struct vcpu *v;
 
+    mem_sharing_hash_iter_detail();
+    return;
+
     if ( dom0 == NULL )
         return;
 
diff -rubN b/xen/common/page_alloc.c a/xen/common/page_alloc.c
--- b/xen/common/page_alloc.c	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/common/page_alloc.c	2011-01-19 16:40:48.000000000 +0800
@@ -69,6 +69,7 @@
 /* Broken page list, protected by heap_lock. */
 PAGE_LIST_HEAD(page_broken_list);
 
+void pagealloc_info(unsigned char key);
 /*************************
  * BOOT-TIME ALLOCATOR
  */
@@ -1260,7 +1261,7 @@
                             -1);
 }
 
-static void pagealloc_info(unsigned char key)
+void pagealloc_info(unsigned char key)
 {
     unsigned int zone = MEMZONE_XEN;
     unsigned long n, total = 0;
diff -rubN b/xen/include/asm-x86/p2m.h a/xen/include/asm-x86/p2m.h
--- b/xen/include/asm-x86/p2m.h	2011-01-31 10:51:55.000000000 +0800
+++ a/xen/include/asm-x86/p2m.h	2011-01-31 11:06:02.000000000 +0800
@@ -316,15 +316,22 @@
                                        int must_succeed)
 {
     mfn_t mfn;
+    int ret;
 
     mfn = gfn_to_mfn(d, gfn, p2mt);
 #ifdef __x86_64__
     if ( p2m_is_shared(*p2mt) )
     {
-        if ( mem_sharing_unshare_page(d, gfn,
-                                      must_succeed 
-                                      ? MEM_SHARING_MUST_SUCCEED : 0) )
+        ret = mem_sharing_unshare_page(d, gfn,
+                must_succeed ? MEM_SHARING_MUST_SUCCEED : 0);
+        if(ret < 0)
         {
+            if ( must_succeed && d->is_dying )
+            {
+                printk("unshare failed dying %d\n", d->is_dying);
+                mfn = _mfn(INVALID_MFN);
+                *p2mt=p2m_invalid;
+            }else
             BUG_ON(must_succeed);
             return mfn;
         }
@@ -437,6 +444,8 @@
 #ifdef __x86_64__
 /* Modify p2m table for shared gfn */
 int set_shared_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+int
+set_shared_p2m_entry_invalid(struct domain *d, unsigned long gfn);
 /* Check if a nominated gfn is valid to be paged out */
 int p2m_mem_paging_nominate(struct domain *d, unsigned long gfn);
 /* Evict a frame */
