From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756230AbYFKHQA (ORCPT ); Wed, 11 Jun 2008 03:16:00 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752998AbYFKHPx (ORCPT ); Wed, 11 Jun 2008 03:15:53 -0400 Received: from bombadil.infradead.org ([18.85.46.34]:39021 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752932AbYFKHPw (ORCPT ); Wed, 11 Jun 2008 03:15:52 -0400 Subject: Re: [PATCH] sched: fair group: fix divide by zero From: Peter Zijlstra To: Lai Jiangshan Cc: mingo@elte.hu, Linux Kernel Mailing List In-Reply-To: <484F7AC5.8040206@cn.fujitsu.com> References: <484F7AC5.8040206@cn.fujitsu.com> Content-Type: text/plain Date: Wed, 11 Jun 2008 09:15:47 +0200 Message-Id: <1213168547.31518.66.camel@twins> Mime-Version: 1.0 X-Mailer: Evolution 2.22.1.1 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, 2008-06-11 at 15:12 +0800, Lai Jiangshan wrote: > I found a bug which can be reproduced by this way:(linux-2.6.26-rc5, x86-64) > (use 2^32, 2^33, ...., 2^63 as shares value) I think the same thing to do is limit the shares value to something smaller instead of using an even more expensive divide. > # mkdir /dev/cpuctl > # mount -t cgroup -o cpu cpuctl /dev/cpuctl > # cd /dev/cpuctl > # mkdir sub > # echo 0x8000000000000000 > sub/cpu.shares > # echo $$ > sub/tasks > oops here! divide by zero. > > This is because do_div() expects the 2th parameter to be 32 bits, > but unsigned long is 64 bits in x86_64. > > Signed-off-by: Lai Jiangshan > --- > diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c > index 08ae848..d3005b4 100644 > --- a/kernel/sched_fair.c > +++ b/kernel/sched_fair.c > @@ -368,7 +368,7 @@ static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se) > cfs_rq = cfs_rq_of(se); > > slice *= se->load.weight; > - do_div(slice, cfs_rq->load.weight); > + slice = div64_u64(slice, cfs_rq->load.weight); > } > > > @@ -399,7 +399,7 @@ static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se) > weight += se->load.weight; > > vslice *= NICE_0_LOAD; > - do_div(vslice, weight); > + vslice = div64_u64(vslice, weight); > } > > return vslice; > >