From patchwork Mon Sep 30 18:54:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Simmons X-Patchwork-Id: 11167103 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D5FDD13BD for ; Mon, 30 Sep 2019 18:58:54 +0000 (UTC) Received: from pdx1-mailman02.dreamhost.com (pdx1-mailman02.dreamhost.com [64.90.62.194]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id BE7C8224D5 for ; Mon, 30 Sep 2019 18:58:54 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BE7C8224D5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=infradead.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lustre-devel-bounces@lists.lustre.org Received: from pdx1-mailman02.dreamhost.com (localhost [IPv6:::1]) by pdx1-mailman02.dreamhost.com (Postfix) with ESMTP id 39F4E5C3E21; Mon, 30 Sep 2019 11:58:02 -0700 (PDT) X-Original-To: lustre-devel@lists.lustre.org Delivered-To: lustre-devel-lustre.org@pdx1-mailman02.dreamhost.com Received: from smtp4.ccs.ornl.gov (smtp4.ccs.ornl.gov [160.91.203.40]) by pdx1-mailman02.dreamhost.com (Postfix) with ESMTP id 21DE25C3165 for ; Mon, 30 Sep 2019 11:57:00 -0700 (PDT) Received: from star.ccs.ornl.gov (star.ccs.ornl.gov [160.91.202.134]) by smtp4.ccs.ornl.gov (Postfix) with ESMTP id 39DB0100537E; Mon, 30 Sep 2019 14:56:56 -0400 (EDT) Received: by star.ccs.ornl.gov (Postfix, from userid 2004) id 36671A9; Mon, 30 Sep 2019 14:56:56 -0400 (EDT) From: James Simmons To: Andreas Dilger , Oleg Drokin , NeilBrown Date: Mon, 30 Sep 2019 14:54:26 -0400 Message-Id: <1569869810-23848-8-git-send-email-jsimmons@infradead.org> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1569869810-23848-1-git-send-email-jsimmons@infradead.org> References: <1569869810-23848-1-git-send-email-jsimmons@infradead.org> Subject: [lustre-devel] [PATCH 007/151] lnet: Allocate MEs and small MDs in own kmem_caches X-BeenThere: lustre-devel@lists.lustre.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "For discussing Lustre software development." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lustre Development List MIME-Version: 1.0 Errors-To: lustre-devel-bounces@lists.lustre.org Sender: "lustre-devel" From: Bruno Faccini As part of LU-3848 and LU-4330, it has been discovered that LNET MEs and small MDs (<=128 Bytes) are allocated in kmem_cache and thus can suffer quite frequent corruptions, from other modules or Kernel parts, that occur there. To avoid this, MEs and small-MDs specific kmem_cache have been created. Also, lnet_libmd struct fields have been re-ordered to optimize its memory foot-print. WC-bug-id: https://jira.whamcloud.com/browse/LU-4330 Lustre-commit: 9d9bb678d6b3 ("LU-4330 lnet: Allocate MEs and small MDs in own kmem_caches") Signed-off-by: Bruno Faccini Reviewed-on: http://review.whamcloud.com/18586 Reviewed-by: Andreas Dilger Reviewed-by: Doug Oucharek Reviewed-by: Oleg Drokin Signed-off-by: James Simmons --- include/linux/lnet/lib-lnet.h | 39 ++++++++++++++++++++++++++++++++++++++- include/linux/lnet/lib-types.h | 2 +- net/lnet/lnet/api-ni.c | 40 ++++++++++++++++++++++++++++++++++++++++ net/lnet/lnet/lib-md.c | 2 +- net/lnet/lnet/lib-me.c | 2 +- net/lnet/lnet/lib-ptl.c | 2 +- 6 files changed, 82 insertions(+), 5 deletions(-) diff --git a/include/linux/lnet/lib-lnet.h b/include/linux/lnet/lib-lnet.h index 776896a..538d457 100644 --- a/include/linux/lnet/lib-lnet.h +++ b/include/linux/lnet/lib-lnet.h @@ -80,6 +80,12 @@ /* default timeout */ #define DEFAULT_PEER_TIMEOUT 180 +#define LNET_SMALL_MD_SIZE offsetof(struct lnet_libmd, md_iov.iov[1]) +extern struct kmem_cache *lnet_mes_cachep; /* MEs kmem_cache */ +extern struct kmem_cache *lnet_small_mds_cachep; /* <= LNET_SMALL_MD_SIZE bytes + * MDs kmem_cache + */ + static inline int lnet_is_route_alive(struct lnet_route *route) { /* gateway is down */ @@ -151,6 +157,24 @@ static inline int lnet_md_unlinkable(struct lnet_libmd *md) cfs_percpt_unlock(the_lnet.ln_res_lock, cpt); } +static inline void +lnet_md_free(struct lnet_libmd *md) +{ + unsigned int size; + + if ((md->md_options & LNET_MD_KIOV) != 0) + size = offsetof(struct lnet_libmd, md_iov.kiov[md->md_niov]); + else + size = offsetof(struct lnet_libmd, md_iov.iov[md->md_niov]); + + if (size <= LNET_SMALL_MD_SIZE) { + CDEBUG(D_MALLOC, "slab-freed 'md' at %p.\n", md); + kmem_cache_free(lnet_small_mds_cachep, md); + } else { + kfree(md); + } +} + static inline int lnet_res_lock_current(void) { @@ -205,7 +229,20 @@ static inline int lnet_md_unlinkable(struct lnet_libmd *md) size = offsetof(struct lnet_libmd, md_iov.iov[niov]); } - md = kzalloc(size, GFP_NOFS); + if (size <= LNET_SMALL_MD_SIZE) { + md = kmem_cache_alloc(lnet_small_mds_cachep, + GFP_NOFS | __GFP_ZERO); + if (md) { + CDEBUG(D_MALLOC, + "slab-alloced 'md' of size %u at %p.\n", + size, md); + } else { + CDEBUG(D_MALLOC, "failed to allocate 'md' of size %u\n", + size); + } + } else { + md = kzalloc(size, GFP_NOFS); + } if (md) { /* Set here in case of early free */ md->md_options = umd->options; diff --git a/include/linux/lnet/lib-types.h b/include/linux/lnet/lib-types.h index 60f9c28..6d2d83a 100644 --- a/include/linux/lnet/lib-types.h +++ b/include/linux/lnet/lib-types.h @@ -164,9 +164,9 @@ struct lnet_libmd { int md_refcount; unsigned int md_options; unsigned int md_flags; + unsigned int md_niov; /* # frags at end of struct */ void *md_user_ptr; struct lnet_eq *md_eq; - unsigned int md_niov; /* # frags */ struct lnet_handle_md md_bulk_handle; union { struct kvec iov[LNET_MAX_IOV]; diff --git a/net/lnet/lnet/api-ni.c b/net/lnet/lnet/api-ni.c index 12b3c44..c33cd1f 100644 --- a/net/lnet/lnet/api-ni.c +++ b/net/lnet/lnet/api-ni.c @@ -216,6 +216,41 @@ static int lnet_discover(struct lnet_process_id id, u32 force, mutex_init(&the_lnet.ln_lnd_mutex); } +struct kmem_cache *lnet_mes_cachep; /* MEs kmem_cache */ +struct kmem_cache *lnet_small_mds_cachep; /* <= LNET_SMALL_MD_SIZE bytes + * MDs kmem_cache + */ + +static int +lnet_descriptor_setup(void) +{ + /* create specific kmem_cache for MEs and small MDs (i.e., originally + * allocated in kmem_cache). + */ + lnet_mes_cachep = kmem_cache_create("lnet_MEs", sizeof(struct lnet_me), + 0, 0, NULL); + if (!lnet_mes_cachep) + return -ENOMEM; + + lnet_small_mds_cachep = kmem_cache_create("lnet_small_MDs", + LNET_SMALL_MD_SIZE, 0, 0, + NULL); + if (!lnet_small_mds_cachep) + return -ENOMEM; + + return 0; +} + +static void +lnet_descriptor_cleanup(void) +{ + kmem_cache_destroy(lnet_small_mds_cachep); + lnet_small_mds_cachep = NULL; + + kmem_cache_destroy(lnet_mes_cachep); + lnet_mes_cachep = NULL; +} + static int lnet_create_remote_nets_table(void) { @@ -701,6 +736,10 @@ struct lnet_libhandle * INIT_LIST_HEAD(&the_lnet.ln_dc_expired); init_waitqueue_head(&the_lnet.ln_dc_waitq); + rc = lnet_descriptor_setup(); + if (rc != 0) + goto failed; + rc = lnet_create_remote_nets_table(); if (rc) goto failed; @@ -798,6 +837,7 @@ struct lnet_libhandle * the_lnet.ln_counters = NULL; } lnet_destroy_remote_nets_table(); + lnet_descriptor_cleanup(); return 0; } diff --git a/net/lnet/lnet/lib-md.c b/net/lnet/lnet/lib-md.c index 33a59fb..8fe3564 100644 --- a/net/lnet/lnet/lib-md.c +++ b/net/lnet/lnet/lib-md.c @@ -82,7 +82,7 @@ LASSERT(!list_empty(&md->md_list)); list_del_init(&md->md_list); - kfree(md); + lnet_md_free(md); } struct page *lnet_kvaddr_to_page(unsigned long vaddr) diff --git a/net/lnet/lnet/lib-me.c b/net/lnet/lnet/lib-me.c index f0365ea..4fe6991 100644 --- a/net/lnet/lnet/lib-me.c +++ b/net/lnet/lnet/lib-me.c @@ -91,7 +91,7 @@ if (!mtable) /* can't match portal type */ return -EPERM; - me = kzalloc(sizeof(*me), GFP_NOFS); + me = kmem_cache_alloc(lnet_mes_cachep, GFP_NOFS | __GFP_ZERO); if (!me) return -ENOMEM; diff --git a/net/lnet/lnet/lib-ptl.c b/net/lnet/lnet/lib-ptl.c index ae061e8..83548f5 100644 --- a/net/lnet/lnet/lib-ptl.c +++ b/net/lnet/lnet/lib-ptl.c @@ -773,7 +773,7 @@ struct list_head * != NULL) { CERROR("Active ME %p on exit\n", me); list_del(&me->me_list); - kfree(me); + kmem_cache_free(lnet_mes_cachep, me); } } /* the extra entry is for MEs with ignore bits */