From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758105AbcIWGnd (ORCPT ); Fri, 23 Sep 2016 02:43:33 -0400 Received: from out0-129.mail.aliyun.com ([140.205.0.129]:34122 "EHLO out0-129.mail.aliyun.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753590AbcIWGna (ORCPT ); Fri, 23 Sep 2016 02:43:30 -0400 X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R191e4;FP=0|-1|-1|-1|0|-1|-1|-1;HT=e02c03306;MF=hillf.zj@alibaba-inc.com;NM=1;PH=DS;RN=7;SR=0;TI=SMTPD_---.7-b1m.Q_1474612973; Reply-To: "Hillf Danton" From: "Hillf Danton" To: "'Vlastimil Babka'" , "'Alexander Viro'" Cc: , , , "'Michal Hocko'" , References: <20160922152831.24165-1-vbabka@suse.cz> In-Reply-To: <20160922152831.24165-1-vbabka@suse.cz> Subject: Re: [PATCH] fs/select: add vmalloc fallback for select(2) Date: Fri, 23 Sep 2016 14:42:53 +0800 Message-ID: <006101d21565$b60a8a70$221f9f50$@alibaba-inc.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Outlook 14.0 Thread-Index: AQLUVJNY75G0glv++L8mb4i0shN7N56CHxOQ Content-Language: zh-cn Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org > > The select(2) syscall performs a kmalloc(size, GFP_KERNEL) where size grows > with the number of fds passed. We had a customer report page allocation > failures of order-4 for this allocation. This is a costly order, so it might > easily fail, as the VM expects such allocation to have a lower-order fallback. > > Such trivial fallback is vmalloc(), as the memory doesn't have to be > physically contiguous. Also the allocation is temporary for the duration of the > syscall, so it's unlikely to stress vmalloc too much. > > Note that the poll(2) syscall seems to use a linked list of order-0 pages, so > it doesn't need this kind of fallback. > > Signed-off-by: Vlastimil Babka > --- > fs/select.c | 15 +++++++++++---- > 1 file changed, 11 insertions(+), 4 deletions(-) > > diff --git a/fs/select.c b/fs/select.c > index 8ed9da50896a..8fe5bddbe99b 100644 > --- a/fs/select.c > +++ b/fs/select.c > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > > #include > > @@ -558,6 +559,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, > struct fdtable *fdt; > /* Allocate small arguments on the stack to save memory and be faster */ > long stack_fds[SELECT_STACK_ALLOC/sizeof(long)]; > + unsigned long alloc_size; > > ret = -EINVAL; > if (n < 0) > @@ -580,10 +582,15 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, > bits = stack_fds; > if (size > sizeof(stack_fds) / 6) { > /* Not enough space in on-stack array; must use kmalloc */ > + alloc_size = 6 * size; > ret = -ENOMEM; > - bits = kmalloc(6 * size, GFP_KERNEL); > - if (!bits) > - goto out_nofds; > + bits = kmalloc(alloc_size, GFP_KERNEL|__GFP_NOWARN); > + if (!bits && alloc_size > PAGE_SIZE) { > + bits = vmalloc(alloc_size); > + > + if (!bits) > + goto out_nofds; > + } Looks like we also have to bail out if kmalloc fails with alloc_size less than PAGE_SIZE. thanks Hillf > } > fds.in = bits; > fds.out = bits + size; > @@ -618,7 +625,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, > > out: > if (bits != stack_fds) > - kfree(bits); > + kvfree(bits); > out_nofds: > return ret; > } > -- > 2.10.0