From patchwork Thu Feb 1 01:39:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 10194991 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4470F60362 for ; Thu, 1 Feb 2018 01:40:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5DDE928897 for ; Thu, 1 Feb 2018 01:40:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 52AEA288B2; Thu, 1 Feb 2018 01:40:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EBD1628897 for ; Thu, 1 Feb 2018 01:40:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755844AbeBABkC (ORCPT ); Wed, 31 Jan 2018 20:40:02 -0500 Received: from ipmailnode02.adl6.internode.on.net ([150.101.137.148]:36450 "EHLO ipmailnode02.adl6.internode.on.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754559AbeBABkC (ORCPT ); Wed, 31 Jan 2018 20:40:02 -0500 Received: from ppp59-167-129-252.static.internode.on.net (HELO dastard) ([59.167.129.252]) by ipmail02.adl6.internode.on.net with ESMTP; 01 Feb 2018 12:10:00 +1030 Received: from discord.disaster.area ([192.168.1.111]) by dastard with esmtp (Exim 4.80) (envelope-from ) id 1eh3r5-0004wl-NI for linux-xfs@vger.kernel.org; Thu, 01 Feb 2018 12:39:59 +1100 Received: from dave by discord.disaster.area with local (Exim 4.90) (envelope-from ) id 1eh3r5-0000E7-MC for linux-xfs@vger.kernel.org; Thu, 01 Feb 2018 12:39:59 +1100 From: Dave Chinner To: linux-xfs@vger.kernel.org Subject: [PATCH] xfs: fall back to vmalloc when allocation log vector buffers Date: Thu, 1 Feb 2018 12:39:59 +1100 Message-Id: <20180201013959.829-1-david@fromorbit.com> X-Mailer: git-send-email 2.15.1 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dave Chinner When using large directory blocks, we regularly see memory allocations of >64k being made for the shadow log vector buffer. When we are under memory pressure, kmalloc() may not be able to find contiguous memory chunks large enough to satisfy these allocations easily, and if memory is fragmented we can potentially stall here. TO avoid this problem, switch the log vector buffer allocation to use kmem_alloc_large(). This will allow failed allocations to fall back to vmalloc and so remove the dependency on large contiguous regions of memory being available. This should prevent slowdowns and potential stalls when memory is low and/or fragmented. Signed-Off-By: Dave Chinner Reviewed-by: Darrick J. Wong --- fs/xfs/kmem.c | 6 +++--- fs/xfs/kmem.h | 8 +++++++- fs/xfs/xfs_log_cil.c | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c index 393b6849aeb3..7bace03dc9dc 100644 --- a/fs/xfs/kmem.c +++ b/fs/xfs/kmem.c @@ -46,13 +46,13 @@ kmem_alloc(size_t size, xfs_km_flags_t flags) } void * -kmem_zalloc_large(size_t size, xfs_km_flags_t flags) +kmem_alloc_large(size_t size, xfs_km_flags_t flags) { unsigned nofs_flag = 0; void *ptr; gfp_t lflags; - ptr = kmem_zalloc(size, flags | KM_MAYFAIL); + ptr = kmem_alloc(size, flags | KM_MAYFAIL); if (ptr) return ptr; @@ -67,7 +67,7 @@ kmem_zalloc_large(size_t size, xfs_km_flags_t flags) nofs_flag = memalloc_nofs_save(); lflags = kmem_flags_convert(flags); - ptr = __vmalloc(size, lflags | __GFP_ZERO, PAGE_KERNEL); + ptr = __vmalloc(size, lflags, PAGE_KERNEL); if (flags & KM_NOFS) memalloc_nofs_restore(nofs_flag); diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 4b87472f35bc..6023b594ead7 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h @@ -71,7 +71,7 @@ kmem_flags_convert(xfs_km_flags_t flags) } extern void *kmem_alloc(size_t, xfs_km_flags_t); -extern void *kmem_zalloc_large(size_t size, xfs_km_flags_t); +extern void *kmem_alloc_large(size_t size, xfs_km_flags_t); extern void *kmem_realloc(const void *, size_t, xfs_km_flags_t); static inline void kmem_free(const void *ptr) { @@ -85,6 +85,12 @@ kmem_zalloc(size_t size, xfs_km_flags_t flags) return kmem_alloc(size, flags | KM_ZERO); } +static inline void * +kmem_zalloc_large(size_t size, xfs_km_flags_t flags) +{ + return kmem_alloc_large(size, flags | KM_ZERO); +} + /* * Zone interfaces */ diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 43aa42a3a5d3..61ab5c0a4c45 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -202,7 +202,7 @@ xlog_cil_alloc_shadow_bufs( */ kmem_free(lip->li_lv_shadow); - lv = kmem_alloc(buf_size, KM_SLEEP|KM_NOFS); + lv = kmem_alloc_large(buf_size, KM_SLEEP|KM_NOFS); memset(lv, 0, xlog_cil_iovec_space(niovecs)); lv->lv_item = lip;