Skip to content

Commit f594998

Browse files
Souptick Joardergregkh
authored andcommitted
xen/gntdev.c: Mark pages as dirty
commit 779055842da5b2e508f3ccf9a8153cb1f704f566 upstream. There seems to be a bug in the original code when gntdev_get_page() is called with writeable=true then the page needs to be marked dirty before being put. To address this, a bool writeable is added in gnt_dev_copy_batch, set it in gntdev_grant_copy_seg() (and drop `writeable` argument to gntdev_get_page()) and then, based on batch->writeable, use set_page_dirty_lock(). Fixes: a4cdb55 (xen/gntdev: add ioctl for grant copy) Suggested-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Souptick Joarder <jrdr.linux@gmail.com> Cc: John Hubbard <jhubbard@nvidia.com> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Juergen Gross <jgross@suse.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/1599375114-32360-1-git-send-email-jrdr.linux@gmail.com Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 67e326e commit f594998

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

drivers/xen/gntdev.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,17 +720,18 @@ struct gntdev_copy_batch {
720720
s16 __user *status[GNTDEV_COPY_BATCH];
721721
unsigned int nr_ops;
722722
unsigned int nr_pages;
723+
bool writeable;
723724
};
724725

725726
static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt,
726-
bool writeable, unsigned long *gfn)
727+
unsigned long *gfn)
727728
{
728729
unsigned long addr = (unsigned long)virt;
729730
struct page *page;
730731
unsigned long xen_pfn;
731732
int ret;
732733

733-
ret = get_user_pages_fast(addr, 1, writeable ? FOLL_WRITE : 0, &page);
734+
ret = get_user_pages_fast(addr, 1, batch->writeable ? FOLL_WRITE : 0, &page);
734735
if (ret < 0)
735736
return ret;
736737

@@ -746,9 +747,13 @@ static void gntdev_put_pages(struct gntdev_copy_batch *batch)
746747
{
747748
unsigned int i;
748749

749-
for (i = 0; i < batch->nr_pages; i++)
750+
for (i = 0; i < batch->nr_pages; i++) {
751+
if (batch->writeable && !PageDirty(batch->pages[i]))
752+
set_page_dirty_lock(batch->pages[i]);
750753
put_page(batch->pages[i]);
754+
}
751755
batch->nr_pages = 0;
756+
batch->writeable = false;
752757
}
753758

754759
static int gntdev_copy(struct gntdev_copy_batch *batch)
@@ -837,8 +842,9 @@ static int gntdev_grant_copy_seg(struct gntdev_copy_batch *batch,
837842
virt = seg->source.virt + copied;
838843
off = (unsigned long)virt & ~XEN_PAGE_MASK;
839844
len = min(len, (size_t)XEN_PAGE_SIZE - off);
845+
batch->writeable = false;
840846

841-
ret = gntdev_get_page(batch, virt, false, &gfn);
847+
ret = gntdev_get_page(batch, virt, &gfn);
842848
if (ret < 0)
843849
return ret;
844850

@@ -856,8 +862,9 @@ static int gntdev_grant_copy_seg(struct gntdev_copy_batch *batch,
856862
virt = seg->dest.virt + copied;
857863
off = (unsigned long)virt & ~XEN_PAGE_MASK;
858864
len = min(len, (size_t)XEN_PAGE_SIZE - off);
865+
batch->writeable = true;
859866

860-
ret = gntdev_get_page(batch, virt, true, &gfn);
867+
ret = gntdev_get_page(batch, virt, &gfn);
861868
if (ret < 0)
862869
return ret;
863870

0 commit comments

Comments
 (0)