diff options
-rw-r--r-- | net/9p/trans_common.c | 14 | ||||
-rw-r--r-- | net/9p/trans_common.h | 2 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 18 |
3 files changed, 24 insertions, 10 deletions
diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index 3dff68f05fb9..e5c359c369a6 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c @@ -19,12 +19,18 @@ /** * p9_release_pages - Release pages after the transaction. */ -void p9_release_pages(struct page **pages, int nr_pages) +void p9_release_pages(struct page **pages, int nr_pages, bool from_gup) { int i; - for (i = 0; i < nr_pages; i++) - if (pages[i]) - put_page(pages[i]); + if (from_gup) { + for (i = 0; i < nr_pages; i++) + if (pages[i]) + put_user_page(pages[i]); + } else { + for (i = 0; i < nr_pages; i++) + if (pages[i]) + put_page(pages[i]); + } } EXPORT_SYMBOL(p9_release_pages); diff --git a/net/9p/trans_common.h b/net/9p/trans_common.h index c43babb3f635..c7def00b2dde 100644 --- a/net/9p/trans_common.h +++ b/net/9p/trans_common.h @@ -12,4 +12,4 @@ * */ -void p9_release_pages(struct page **, int); +void p9_release_pages(struct page **, int, bool); diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index b1d39cabf125..945b7a954e57 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -321,11 +321,14 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, struct iov_iter *data, int count, size_t *offs, - int *need_drop) + int *need_drop, + bool *from_gup) { int nr_pages; int err; + *from_gup = false; + if (!iov_iter_count(data)) return 0; @@ -347,6 +350,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, *need_drop = 1; nr_pages = DIV_ROUND_UP(n + *offs, PAGE_SIZE); atomic_add(nr_pages, &vp_pinned); + *from_gup = iov_iter_get_pages_use_gup(data); return n; } else { /* kernel buffer, no need to pin pages */ @@ -412,13 +416,15 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, size_t offs; int need_drop = 0; int kicked = 0; + bool in_from_gup, out_from_gup; p9_debug(P9_DEBUG_TRANS, "virtio request\n"); if (uodata) { __le32 sz; int n = p9_get_mapped_pages(chan, &out_pages, uodata, - outlen, &offs, &need_drop); + outlen, &offs, &need_drop, + &out_from_gup); if (n < 0) { err = n; goto err_out; @@ -437,7 +443,8 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, memcpy(&req->tc.sdata[0], &sz, sizeof(sz)); } else if (uidata) { int n = p9_get_mapped_pages(chan, &in_pages, uidata, - inlen, &offs, &need_drop); + inlen, &offs, &need_drop, + &in_from_gup); if (n < 0) { err = n; goto err_out; @@ -519,11 +526,12 @@ req_retry_pinned: err_out: if (need_drop) { if (in_pages) { - p9_release_pages(in_pages, in_nr_pages); + p9_release_pages(in_pages, in_nr_pages, in_from_gup); atomic_sub(in_nr_pages, &vp_pinned); } if (out_pages) { - p9_release_pages(out_pages, out_nr_pages); + p9_release_pages(out_pages, out_nr_pages, + out_from_gup); atomic_sub(out_nr_pages, &vp_pinned); } /* wakeup anybody waiting for slots to pin pages */ |