Message ID | 20240731033449.1016195-1-link@vivo.com |
---|---|
State | New |
Headers | show |
Series | udmabuf: use kmem_cache to alloc udmabuf folio | expand |
On Wed, Jul 31, 2024 at 11:34:49AM +0800, Huan Yang wrote: > The current udmabuf_folio contains a list_head and the corresponding > folio pointer, with a size of 24 bytes. udmabuf_folio uses kmalloc to > allocate memory. > > However, kmalloc is a public pool, starting from 64 bytes. This means > that each udmabuf_folio allocation will waste 40 bytes. > > Considering that each udmabuf creates a folio corresponding to a > udmabuf_folio, the wasted memory can be significant in the case of > memory fragmentation. > > Furthermore, if udmabuf is frequently used, the allocation and > deallocation of udmabuf_folio will also be frequent. > > Therefore, this patch adds a kmem_cache dedicated to the allocation and > deallocation of udmabuf_folio.This is expected to improve the > performance of allocation and deallocation within the expected range, > while also avoiding memory waste. > > Signed-off-by: Huan Yang <link@vivo.com> > --- > drivers/dma-buf/udmabuf.c | 18 +++++++++++++++--- > 1 file changed, 15 insertions(+), 3 deletions(-) > > diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c > index 047c3cd2ceff..db4de8c745ce 100644 > --- a/drivers/dma-buf/udmabuf.c > +++ b/drivers/dma-buf/udmabuf.c > @@ -24,6 +24,8 @@ static int size_limit_mb = 64; > module_param(size_limit_mb, int, 0644); > MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in megabytes. Default is 64."); > > +static struct kmem_cache *udmabuf_folio_cachep; > + > struct udmabuf { > pgoff_t pagecount; > struct folio **folios; > @@ -169,7 +171,7 @@ static void unpin_all_folios(struct list_head *unpin_list) > unpin_folio(ubuf_folio->folio); > > list_del(&ubuf_folio->list); > - kfree(ubuf_folio); > + kmem_cache_free(udmabuf_folio_cachep, ubuf_folio); > } > } > > @@ -178,7 +180,7 @@ static int add_to_unpin_list(struct list_head *unpin_list, > { > struct udmabuf_folio *ubuf_folio; > > - ubuf_folio = kzalloc(sizeof(*ubuf_folio), GFP_KERNEL); > + ubuf_folio = kmem_cache_alloc(udmabuf_folio_cachep, GFP_KERNEL); > if (!ubuf_folio) > return -ENOMEM; > > @@ -492,10 +494,20 @@ static int __init udmabuf_dev_init(void) > if (ret < 0) { > pr_err("Could not setup DMA mask for udmabuf device\n"); > misc_deregister(&udmabuf_misc); misc_deregister() is now called twice in this error path, I think you've forgotten to delete this line too? Otherwise lgtm. -Sima > - return ret; > + goto err; > + } > + > + udmabuf_folio_cachep = KMEM_CACHE(udmabuf_folio, 0); > + if (unlikely(!udmabuf_folio_cachep)) { > + ret = -ENOMEM; > + goto err; > } > > return 0; > + > +err: > + misc_deregister(&udmabuf_misc); > + return ret; > } > > static void __exit udmabuf_dev_exit(void) > > base-commit: cd19ac2f903276b820f5d0d89de0c896c27036ed > -- > 2.45.2 >
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 047c3cd2ceff..db4de8c745ce 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -24,6 +24,8 @@ static int size_limit_mb = 64; module_param(size_limit_mb, int, 0644); MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in megabytes. Default is 64."); +static struct kmem_cache *udmabuf_folio_cachep; + struct udmabuf { pgoff_t pagecount; struct folio **folios; @@ -169,7 +171,7 @@ static void unpin_all_folios(struct list_head *unpin_list) unpin_folio(ubuf_folio->folio); list_del(&ubuf_folio->list); - kfree(ubuf_folio); + kmem_cache_free(udmabuf_folio_cachep, ubuf_folio); } } @@ -178,7 +180,7 @@ static int add_to_unpin_list(struct list_head *unpin_list, { struct udmabuf_folio *ubuf_folio; - ubuf_folio = kzalloc(sizeof(*ubuf_folio), GFP_KERNEL); + ubuf_folio = kmem_cache_alloc(udmabuf_folio_cachep, GFP_KERNEL); if (!ubuf_folio) return -ENOMEM; @@ -492,10 +494,20 @@ static int __init udmabuf_dev_init(void) if (ret < 0) { pr_err("Could not setup DMA mask for udmabuf device\n"); misc_deregister(&udmabuf_misc); - return ret; + goto err; + } + + udmabuf_folio_cachep = KMEM_CACHE(udmabuf_folio, 0); + if (unlikely(!udmabuf_folio_cachep)) { + ret = -ENOMEM; + goto err; } return 0; + +err: + misc_deregister(&udmabuf_misc); + return ret; } static void __exit udmabuf_dev_exit(void)
The current udmabuf_folio contains a list_head and the corresponding folio pointer, with a size of 24 bytes. udmabuf_folio uses kmalloc to allocate memory. However, kmalloc is a public pool, starting from 64 bytes. This means that each udmabuf_folio allocation will waste 40 bytes. Considering that each udmabuf creates a folio corresponding to a udmabuf_folio, the wasted memory can be significant in the case of memory fragmentation. Furthermore, if udmabuf is frequently used, the allocation and deallocation of udmabuf_folio will also be frequent. Therefore, this patch adds a kmem_cache dedicated to the allocation and deallocation of udmabuf_folio.This is expected to improve the performance of allocation and deallocation within the expected range, while also avoiding memory waste. Signed-off-by: Huan Yang <link@vivo.com> --- drivers/dma-buf/udmabuf.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) base-commit: cd19ac2f903276b820f5d0d89de0c896c27036ed