struct privcmd_dm_op_buf kbufs[], unsigned int num,
        struct page *pages[], unsigned int nr_pages, unsigned int *pinned)
 {
-       unsigned int i;
+       unsigned int i, off = 0;
 
-       for (i = 0; i < num; i++) {
+       for (i = 0; i < num; ) {
                unsigned int requested;
                int page_count;
 
                requested = DIV_ROUND_UP(
                        offset_in_page(kbufs[i].uptr) + kbufs[i].size,
-                       PAGE_SIZE);
+                       PAGE_SIZE) - off;
                if (requested > nr_pages)
                        return -ENOSPC;
 
                page_count = pin_user_pages_fast(
-                       (unsigned long) kbufs[i].uptr,
+                       (unsigned long)kbufs[i].uptr + off * PAGE_SIZE,
                        requested, FOLL_WRITE, pages);
-               if (page_count < 0)
-                       return page_count;
+               if (page_count <= 0)
+                       return page_count ? : -EFAULT;
 
                *pinned += page_count;
                nr_pages -= page_count;
                pages += page_count;
+
+               off = (requested == page_count) ? 0 : off + page_count;
+               i += !off;
        }
 
        return 0;
        }
 
        rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &pinned);
-       if (rc < 0) {
-               nr_pages = pinned;
+       if (rc < 0)
                goto out;
-       }
 
        for (i = 0; i < kdata.num; i++) {
                set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
        xen_preemptible_hcall_end();
 
 out:
-       unlock_pages(pages, nr_pages);
+       unlock_pages(pages, pinned);
        kfree(xbufs);
        kfree(pages);
        kfree(kbufs);