From: Xie Yongji <xieyongji@bytedance.com>
To: mst@redhat.com, jasowang@redhat.com, stefanha@redhat.com,
sgarzare@redhat.com, parav@nvidia.com, akpm@linux-foundation.org,
rdunlap@infradead.org, willy@infradead.org,
viro@zeniv.linux.org.uk, axboe@kernel.dk, bcrl@kvack.org,
corbet@lwn.net
Cc: virtualization@lists.linux-foundation.org,
netdev@vger.kernel.org, kvm@vger.kernel.org, linux-aio@kvack.org,
linux-fsdevel@vger.kernel.org, linux-mm@kvack.org
Subject: [RFC v2 11/13] vduse/iova_domain: Support reclaiming bounce pages
Date: Tue, 22 Dec 2020 22:52:19 +0800 [thread overview]
Message-ID: <20201222145221.711-12-xieyongji@bytedance.com> (raw)
In-Reply-To: <20201222145221.711-1-xieyongji@bytedance.com>
Introduce vduse_domain_reclaim() to support reclaiming bounce page
when necessary. We will do reclaiming chunk by chunk. And only
reclaim the iova chunk that no one used.
Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
---
drivers/vdpa/vdpa_user/iova_domain.c | 83 ++++++++++++++++++++++++++++++++++--
drivers/vdpa/vdpa_user/iova_domain.h | 10 +++++
2 files changed, 89 insertions(+), 4 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/iova_domain.c b/drivers/vdpa/vdpa_user/iova_domain.c
index 27022157abc6..c438cc85d33d 100644
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -29,6 +29,8 @@ struct vduse_mmap_vma {
struct list_head list;
};
+struct percpu_counter vduse_total_bounce_pages;
+
static inline struct page *
vduse_domain_get_bounce_page(struct vduse_iova_domain *domain,
unsigned long iova)
@@ -48,6 +50,13 @@ vduse_domain_set_bounce_page(struct vduse_iova_domain *domain,
unsigned long chunkoff = iova & ~IOVA_CHUNK_MASK;
unsigned long pgindex = chunkoff >> PAGE_SHIFT;
+ if (page) {
+ domain->chunks[index].used_bounce_pages++;
+ percpu_counter_inc(&vduse_total_bounce_pages);
+ } else {
+ domain->chunks[index].used_bounce_pages--;
+ percpu_counter_dec(&vduse_total_bounce_pages);
+ }
domain->chunks[index].bounce_pages[pgindex] = page;
}
@@ -175,6 +184,29 @@ void vduse_domain_remove_mapping(struct vduse_iova_domain *domain,
}
}
+static bool vduse_domain_try_unmap(struct vduse_iova_domain *domain,
+ unsigned long iova, size_t size)
+{
+ struct vduse_mmap_vma *mmap_vma;
+ unsigned long uaddr;
+ bool unmap = true;
+
+ mutex_lock(&domain->vma_lock);
+ list_for_each_entry(mmap_vma, &domain->vma_list, list) {
+ if (!mmap_read_trylock(mmap_vma->vma->vm_mm)) {
+ unmap = false;
+ break;
+ }
+
+ uaddr = iova + mmap_vma->vma->vm_start;
+ zap_page_range(mmap_vma->vma, uaddr, size);
+ mmap_read_unlock(mmap_vma->vma->vm_mm);
+ }
+ mutex_unlock(&domain->vma_lock);
+
+ return unmap;
+}
+
void vduse_domain_unmap(struct vduse_iova_domain *domain,
unsigned long iova, size_t size)
{
@@ -302,6 +334,32 @@ bool vduse_domain_is_direct_map(struct vduse_iova_domain *domain,
return atomic_read(&chunk->map_type) == TYPE_DIRECT_MAP;
}
+int vduse_domain_reclaim(struct vduse_iova_domain *domain)
+{
+ struct vduse_iova_chunk *chunk;
+ int i, freed = 0;
+
+ for (i = domain->chunk_num - 1; i >= 0; i--) {
+ chunk = &domain->chunks[i];
+ if (!chunk->used_bounce_pages)
+ continue;
+
+ if (atomic_cmpxchg(&chunk->state, 0, INT_MIN) != 0)
+ continue;
+
+ if (!vduse_domain_try_unmap(domain,
+ chunk->start, IOVA_CHUNK_SIZE)) {
+ atomic_sub(INT_MIN, &chunk->state);
+ break;
+ }
+ freed += vduse_domain_free_bounce_pages(domain,
+ chunk->start, IOVA_CHUNK_SIZE);
+ atomic_sub(INT_MIN, &chunk->state);
+ }
+
+ return freed;
+}
+
unsigned long vduse_domain_alloc_iova(struct vduse_iova_domain *domain,
size_t size, enum iova_map_type type)
{
@@ -319,10 +377,13 @@ unsigned long vduse_domain_alloc_iova(struct vduse_iova_domain *domain,
if (atomic_read(&chunk->map_type) != type)
continue;
- iova = gen_pool_alloc_algo(chunk->pool, size,
+ if (atomic_fetch_inc(&chunk->state) >= 0) {
+ iova = gen_pool_alloc_algo(chunk->pool, size,
gen_pool_first_fit_align, &data);
- if (iova)
- break;
+ if (iova)
+ break;
+ }
+ atomic_dec(&chunk->state);
}
return iova;
@@ -335,6 +396,7 @@ void vduse_domain_free_iova(struct vduse_iova_domain *domain,
struct vduse_iova_chunk *chunk = &domain->chunks[index];
gen_pool_free(chunk->pool, iova, size);
+ atomic_dec(&chunk->state);
}
static void vduse_iova_chunk_cleanup(struct vduse_iova_chunk *chunk)
@@ -351,7 +413,8 @@ void vduse_iova_domain_destroy(struct vduse_iova_domain *domain)
for (i = 0; i < domain->chunk_num; i++) {
chunk = &domain->chunks[i];
- vduse_domain_free_bounce_pages(domain,
+ if (chunk->used_bounce_pages)
+ vduse_domain_free_bounce_pages(domain,
chunk->start, IOVA_CHUNK_SIZE);
vduse_iova_chunk_cleanup(chunk);
}
@@ -390,8 +453,10 @@ static int vduse_iova_chunk_init(struct vduse_iova_chunk *chunk,
if (!chunk->iova_map)
goto err;
+ chunk->used_bounce_pages = 0;
chunk->start = addr;
atomic_set(&chunk->map_type, TYPE_NONE);
+ atomic_set(&chunk->state, 0);
return 0;
err:
@@ -440,3 +505,13 @@ struct vduse_iova_domain *vduse_iova_domain_create(size_t size)
return NULL;
}
+
+int vduse_domain_init(void)
+{
+ return percpu_counter_init(&vduse_total_bounce_pages, 0, GFP_KERNEL);
+}
+
+void vduse_domain_exit(void)
+{
+ percpu_counter_destroy(&vduse_total_bounce_pages);
+}
diff --git a/drivers/vdpa/vdpa_user/iova_domain.h b/drivers/vdpa/vdpa_user/iova_domain.h
index fe1816287f5f..6815b00629d2 100644
--- a/drivers/vdpa/vdpa_user/iova_domain.h
+++ b/drivers/vdpa/vdpa_user/iova_domain.h
@@ -31,8 +31,10 @@ struct vduse_iova_chunk {
struct gen_pool *pool;
struct page **bounce_pages;
struct vduse_iova_map **iova_map;
+ int used_bounce_pages;
unsigned long start;
atomic_t map_type;
+ atomic_t state;
};
struct vduse_iova_domain {
@@ -44,6 +46,8 @@ struct vduse_iova_domain {
struct list_head vma_list;
};
+extern struct percpu_counter vduse_total_bounce_pages;
+
int vduse_domain_add_vma(struct vduse_iova_domain *domain,
struct vm_area_struct *vma);
@@ -77,6 +81,8 @@ int vduse_domain_bounce_map(struct vduse_iova_domain *domain,
bool vduse_domain_is_direct_map(struct vduse_iova_domain *domain,
unsigned long iova);
+int vduse_domain_reclaim(struct vduse_iova_domain *domain);
+
unsigned long vduse_domain_alloc_iova(struct vduse_iova_domain *domain,
size_t size, enum iova_map_type type);
@@ -90,4 +96,8 @@ void vduse_iova_domain_destroy(struct vduse_iova_domain *domain);
struct vduse_iova_domain *vduse_iova_domain_create(size_t size);
+int vduse_domain_init(void);
+
+void vduse_domain_exit(void);
+
#endif /* _VDUSE_IOVA_DOMAIN_H */
--
2.11.0
next prev parent reply other threads:[~2020-12-22 14:55 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-22 14:52 [RFC v2 00/13] Introduce VDUSE - vDPA Device in Userspace Xie Yongji
2020-12-22 14:52 ` [RFC v2 01/13] mm: export zap_page_range() for driver use Xie Yongji
2020-12-22 15:44 ` Christoph Hellwig
2020-12-22 14:52 ` [RFC v2 02/13] eventfd: track eventfd_signal() recursion depth separately in different cases Xie Yongji
2020-12-22 14:52 ` [RFC v2 03/13] eventfd: Increase the recursion depth of eventfd_signal() Xie Yongji
2020-12-22 14:52 ` [RFC v2 04/13] vdpa: Remove the restriction that only supports virtio-net devices Xie Yongji
2020-12-22 14:52 ` [RFC v2 05/13] vdpa: Pass the netlink attributes to ops.dev_add() Xie Yongji
2020-12-22 14:52 ` [RFC v2 06/13] vduse: Introduce VDUSE - vDPA Device in Userspace Xie Yongji
2020-12-23 8:08 ` Jason Wang
2020-12-23 14:17 ` Yongji Xie
2020-12-24 3:01 ` Jason Wang
2020-12-24 8:34 ` Yongji Xie
2020-12-25 6:59 ` Jason Wang
2021-01-08 13:32 ` Bob Liu
2021-01-10 10:03 ` Yongji Xie
2020-12-22 14:52 ` [RFC v2 07/13] vduse: support get/set virtqueue state Xie Yongji
2020-12-22 14:52 ` [RFC v2 08/13] vdpa: Introduce process_iotlb_msg() in vdpa_config_ops Xie Yongji
2020-12-23 8:36 ` Jason Wang
2020-12-23 11:06 ` Yongji Xie
2020-12-24 2:36 ` Jason Wang
2020-12-24 7:24 ` Yongji Xie
2020-12-22 14:52 ` [RFC v2 09/13] vduse: Add support for processing vhost iotlb message Xie Yongji
2020-12-23 9:05 ` Jason Wang
2020-12-23 12:14 ` [External] " Yongji Xie
2020-12-24 2:41 ` Jason Wang
2020-12-24 7:37 ` Yongji Xie
2020-12-25 2:37 ` Yongji Xie
2020-12-25 7:02 ` Jason Wang
2020-12-25 11:36 ` Yongji Xie
2020-12-25 6:57 ` Jason Wang
2020-12-25 10:31 ` Yongji Xie
2020-12-28 7:43 ` Jason Wang
2020-12-28 8:14 ` Yongji Xie
2020-12-28 8:43 ` Jason Wang
2020-12-28 9:12 ` Yongji Xie
2020-12-29 9:11 ` Jason Wang
2020-12-29 10:26 ` Yongji Xie
2020-12-30 6:10 ` Jason Wang
2020-12-30 7:09 ` Yongji Xie
2020-12-30 8:41 ` Jason Wang
2020-12-30 10:12 ` Yongji Xie
2020-12-31 2:49 ` Jason Wang
2020-12-31 5:15 ` Yongji Xie
2020-12-31 5:49 ` Jason Wang
2020-12-31 6:52 ` Yongji Xie
2020-12-31 7:11 ` Jason Wang
2020-12-31 8:00 ` Yongji Xie
2020-12-22 14:52 ` [RFC v2 10/13] vduse: grab the module's references until there is no vduse device Xie Yongji
2020-12-22 14:52 ` Xie Yongji [this message]
2020-12-22 14:52 ` [RFC v2 12/13] vduse: Add memory shrinker to reclaim bounce pages Xie Yongji
2020-12-22 14:52 ` [RFC v2 13/13] vduse: Introduce a workqueue for irq injection Xie Yongji
2020-12-23 6:38 ` [RFC v2 00/13] Introduce VDUSE - vDPA Device in Userspace Jason Wang
2020-12-23 8:14 ` Jason Wang
2020-12-23 10:59 ` Yongji Xie
2020-12-24 2:24 ` Jason Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201222145221.711-12-xieyongji@bytedance.com \
--to=xieyongji@bytedance.com \
--cc=akpm@linux-foundation.org \
--cc=axboe@kernel.dk \
--cc=bcrl@kvack.org \
--cc=corbet@lwn.net \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-aio@kvack.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=parav@nvidia.com \
--cc=rdunlap@infradead.org \
--cc=sgarzare@redhat.com \
--cc=stefanha@redhat.com \
--cc=viro@zeniv.linux.org.uk \
--cc=virtualization@lists.linux-foundation.org \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).