extern int m2p_add_override(unsigned long mfn, struct page *page,
                            struct gnttab_map_grant_ref *kmap_op);
 extern int m2p_remove_override(struct page *page,
-                               struct gnttab_map_grant_ref *kmap_op);
+                              struct gnttab_map_grant_ref *kmap_op,
+                              unsigned long mfn);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
                pfn = m2p_find_override_pfn(mfn, ~0);
        }
 
-       /* 
+       /*
         * pfn is ~0 if there are no entries in the m2p for mfn or if the
         * entry doesn't map back to the mfn and m2p_override doesn't have a
         * valid entry for it.
 
                                        "m2p_add_override: pfn %lx not mapped", pfn))
                        return -EINVAL;
        }
-       WARN_ON(PagePrivate(page));
-       SetPagePrivate(page);
-       set_page_private(page, mfn);
-       page->index = pfn_to_mfn(pfn);
-
-       if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
-               return -ENOMEM;
 
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
 }
 EXPORT_SYMBOL_GPL(m2p_add_override);
 int m2p_remove_override(struct page *page,
-               struct gnttab_map_grant_ref *kmap_op)
+                       struct gnttab_map_grant_ref *kmap_op,
+                       unsigned long mfn)
 {
        unsigned long flags;
-       unsigned long mfn;
        unsigned long pfn;
        unsigned long uninitialized_var(address);
        unsigned level;
        pte_t *ptep = NULL;
 
        pfn = page_to_pfn(page);
-       mfn = get_phys_to_machine(pfn);
-       if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
-               return -EINVAL;
 
        if (!PageHighMem(page)) {
                address = (unsigned long)__va(pfn << PAGE_SHIFT);
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
-       WARN_ON(!PagePrivate(page));
-       ClearPagePrivate(page);
 
-       set_phys_to_machine(pfn, page->index);
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
                        struct multicall_space mcs;
 
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST ||
                        !rb_next(&persistent_gnt->node)) {
-                       ret = gnttab_unmap_refs(unmap, NULL, pages,
-                               segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
                pages[segs_to_unmap] = persistent_gnt->page;
 
                if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, NULL, pages,
-                               segs_to_unmap);
+                       ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
                        BUG_ON(ret);
                        put_free_pages(blkif, pages, segs_to_unmap);
                        segs_to_unmap = 0;
                kfree(persistent_gnt);
        }
        if (segs_to_unmap > 0) {
-               ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap);
+               ret = gnttab_unmap_refs(unmap, pages, segs_to_unmap);
                BUG_ON(ret);
                put_free_pages(blkif, pages, segs_to_unmap);
        }
                                    GNTMAP_host_map, pages[i]->handle);
                pages[i]->handle = BLKBACK_INVALID_HANDLE;
                if (++invcount == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
-                       ret = gnttab_unmap_refs(unmap, NULL, unmap_pages,
-                                               invcount);
+                       ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
                        BUG_ON(ret);
                        put_free_pages(blkif, unmap_pages, invcount);
                        invcount = 0;
                }
        }
        if (invcount) {
-               ret = gnttab_unmap_refs(unmap, NULL, unmap_pages, invcount);
+               ret = gnttab_unmap_refs(unmap, unmap_pages, invcount);
                BUG_ON(ret);
                put_free_pages(blkif, unmap_pages, invcount);
        }
        }
 
        if (segs_to_map) {
-               ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map);
+               ret = gnttab_map_refs(map, pages_to_gnt, segs_to_map);
                BUG_ON(ret);
        }
 
 
        }
 
        pr_debug("map %d+%d\n", map->index, map->count);
-       err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
-                       map->pages, map->count);
+       err = gnttab_map_refs_userspace(map->map_ops,
+                                       use_ptemod ? map->kmap_ops : NULL,
+                                       map->pages,
+                                       map->count);
        if (err)
                return err;
 
                }
        }
 
-       err = gnttab_unmap_refs(map->unmap_ops + offset,
-                       use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
-                       pages);
+       err = gnttab_unmap_refs_userspace(map->unmap_ops + offset,
+                                         use_ptemod ? map->kmap_ops + offset : NULL,
+                                         map->pages + offset,
+                                         pages);
        if (err)
                return err;
 
 
 }
 EXPORT_SYMBOL_GPL(gnttab_batch_copy);
 
-int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+int __gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
-                   struct page **pages, unsigned int count)
+                   struct page **pages, unsigned int count,
+                   bool m2p_override)
 {
        int i, ret;
        bool lazy = false;
        pte_t *pte;
-       unsigned long mfn;
+       unsigned long mfn, pfn;
 
+       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map_ops, count);
        if (ret)
                return ret;
                        set_phys_to_machine(map_ops[i].host_addr >> PAGE_SHIFT,
                                        map_ops[i].dev_bus_addr >> PAGE_SHIFT);
                }
-               return ret;
+               return 0;
        }
 
-       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (m2p_override &&
+           !in_interrupt() &&
+           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
                } else {
                        mfn = PFN_DOWN(map_ops[i].dev_bus_addr);
                }
-               ret = m2p_add_override(mfn, pages[i], kmap_ops ?
-                                      &kmap_ops[i] : NULL);
+               pfn = page_to_pfn(pages[i]);
+
+               WARN_ON(PagePrivate(pages[i]));
+               SetPagePrivate(pages[i]);
+               set_page_private(pages[i], mfn);
+
+               pages[i]->index = pfn_to_mfn(pfn);
+               if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               if (m2p_override)
+                       ret = m2p_add_override(mfn, pages[i], kmap_ops ?
+                                              &kmap_ops[i] : NULL);
                if (ret)
                        goto out;
        }
 
        return ret;
 }
+
+int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
+                   struct page **pages, unsigned int count)
+{
+       return __gnttab_map_refs(map_ops, NULL, pages, count, false);
+}
 EXPORT_SYMBOL_GPL(gnttab_map_refs);
 
-int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
+int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
+                             struct gnttab_map_grant_ref *kmap_ops,
+                             struct page **pages, unsigned int count)
+{
+       return __gnttab_map_refs(map_ops, kmap_ops, pages, count, true);
+}
+EXPORT_SYMBOL_GPL(gnttab_map_refs_userspace);
+
+int __gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
                      struct gnttab_map_grant_ref *kmap_ops,
-                     struct page **pages, unsigned int count)
+                     struct page **pages, unsigned int count,
+                     bool m2p_override)
 {
        int i, ret;
        bool lazy = false;
+       unsigned long pfn, mfn;
 
+       BUG_ON(kmap_ops && !m2p_override);
        ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops, count);
        if (ret)
                return ret;
                        set_phys_to_machine(unmap_ops[i].host_addr >> PAGE_SHIFT,
                                        INVALID_P2M_ENTRY);
                }
-               return ret;
+               return 0;
        }
 
-       if (!in_interrupt() && paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
+       if (m2p_override &&
+           !in_interrupt() &&
+           paravirt_get_lazy_mode() == PARAVIRT_LAZY_NONE) {
                arch_enter_lazy_mmu_mode();
                lazy = true;
        }
 
        for (i = 0; i < count; i++) {
-               ret = m2p_remove_override(pages[i], kmap_ops ?
-                                      &kmap_ops[i] : NULL);
+               pfn = page_to_pfn(pages[i]);
+               mfn = get_phys_to_machine(pfn);
+               if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               set_page_private(pages[i], INVALID_P2M_ENTRY);
+               WARN_ON(!PagePrivate(pages[i]));
+               ClearPagePrivate(pages[i]);
+               set_phys_to_machine(pfn, pages[i]->index);
+               if (m2p_override)
+                       ret = m2p_remove_override(pages[i],
+                                                 kmap_ops ?
+                                                  &kmap_ops[i] : NULL,
+                                                 mfn);
                if (ret)
                        goto out;
        }
 
        return ret;
 }
+
+int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *map_ops,
+                   struct page **pages, unsigned int count)
+{
+       return __gnttab_unmap_refs(map_ops, NULL, pages, count, false);
+}
 EXPORT_SYMBOL_GPL(gnttab_unmap_refs);
 
+int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *map_ops,
+                               struct gnttab_map_grant_ref *kmap_ops,
+                               struct page **pages, unsigned int count)
+{
+       return __gnttab_unmap_refs(map_ops, kmap_ops, pages, count, true);
+}
+EXPORT_SYMBOL_GPL(gnttab_unmap_refs_userspace);
+
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
        BUG_ON(grefs_per_grant_frame == 0);
 
 #define gnttab_map_vaddr(map) ((void *)(map.host_virt_addr))
 
 int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
-                   struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count);
+int gnttab_map_refs_userspace(struct gnttab_map_grant_ref *map_ops,
+                             struct gnttab_map_grant_ref *kmap_ops,
+                             struct page **pages, unsigned int count);
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
-                     struct gnttab_map_grant_ref *kunmap_ops,
                      struct page **pages, unsigned int count);
+int gnttab_unmap_refs_userspace(struct gnttab_unmap_grant_ref *unmap_ops,
+                               struct gnttab_map_grant_ref *kunmap_ops,
+                               struct page **pages, unsigned int count);
 
 /* Perform a batch of grant map/copy operations. Retry every batch slot
  * for which the hypervisor returns GNTST_eagain. This is typically due