From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5ADCDC2D0C6 for ; Wed, 11 Dec 2019 16:05:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 30D042073D for ; Wed, 11 Dec 2019 16:05:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576080324; bh=6E00oAINu4WSQ2OxBCVSoVj7KPtNBMXJcbpbuz32U0k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=n3YrqkkFg2RaPQabWpr2lmONtmA7bw/O3oo7xjXyAmr/DLBDzu2///WCZIBMUhZMY M4RQUMdF/oHAwLOYhvD8MejPUBb43G/4mWSD9Qp8266fmVsEEpopZh4Gbo7A+lRU59 F3x1kH4SY+KcNIYBhhrMcZ8VOIG9FE+Bm1kDHj4c= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731252AbfLKQFX (ORCPT ); Wed, 11 Dec 2019 11:05:23 -0500 Received: from mail.kernel.org ([198.145.29.99]:35224 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730431AbfLKPMv (ORCPT ); Wed, 11 Dec 2019 10:12:51 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 928702465B; Wed, 11 Dec 2019 15:12:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576077171; bh=6E00oAINu4WSQ2OxBCVSoVj7KPtNBMXJcbpbuz32U0k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rPTVhdIvg9m/dXJEjlWA5RBhEFdFcJ41zXcT2lnd9pw/yIebuIB/hwbADYkma5dBM zUBzk8Qvw/rCxztElHyVvRyQuDhoNIAa4ie1NO4VtcyTZvr2LLoimrVsfdrZUct6q2 og4hr6WdA2tuQsXPAgOONF+GxSFi6Lk0OqyVhqdA= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Konstantin Khlebnikov , Jan Kara , Sasha Levin Subject: [PATCH AUTOSEL 5.4 056/134] fs/quota: handle overflows of sysctl fs.quota.* and report as unsigned long Date: Wed, 11 Dec 2019 10:10:32 -0500 Message-Id: <20191211151150.19073-56-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191211151150.19073-1-sashal@kernel.org> References: <20191211151150.19073-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Konstantin Khlebnikov [ Upstream commit 6fcbcec9cfc7b3c6a2c1f1a23ebacedff7073e0a ] Quota statistics counted as 64-bit per-cpu counter. Reading sums per-cpu fractions as signed 64-bit int, filters negative values and then reports lower half as signed 32-bit int. Result may looks like: fs.quota.allocated_dquots = 22327 fs.quota.cache_hits = -489852115 fs.quota.drops = -487288718 fs.quota.free_dquots = 22083 fs.quota.lookups = -486883485 fs.quota.reads = 22327 fs.quota.syncs = 335064 fs.quota.writes = 3088689 Values bigger than 2^31-1 reported as negative. All counters except "allocated_dquots" and "free_dquots" are monotonic, thus they should be reported as is without filtering negative values. Kernel doesn't have generic helper for 64-bit sysctl yet, let's use at least unsigned long. Link: https://lore.kernel.org/r/157337934693.2078.9842146413181153727.stgit@buzz Signed-off-by: Konstantin Khlebnikov Signed-off-by: Jan Kara Signed-off-by: Sasha Levin --- fs/quota/dquot.c | 29 +++++++++++++++++------------ include/linux/quota.h | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 6e826b454082c..fa6ec4f96791d 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2860,68 +2860,73 @@ EXPORT_SYMBOL(dquot_quotactl_sysfile_ops); static int do_proc_dqstats(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - unsigned int type = (int *)table->data - dqstats.stat; + unsigned int type = (unsigned long *)table->data - dqstats.stat; + s64 value = percpu_counter_sum(&dqstats.counter[type]); + + /* Filter negative values for non-monotonic counters */ + if (value < 0 && (type == DQST_ALLOC_DQUOTS || + type == DQST_FREE_DQUOTS)) + value = 0; /* Update global table */ - dqstats.stat[type] = - percpu_counter_sum_positive(&dqstats.counter[type]); - return proc_dointvec(table, write, buffer, lenp, ppos); + dqstats.stat[type] = value; + return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); } static struct ctl_table fs_dqstats_table[] = { { .procname = "lookups", .data = &dqstats.stat[DQST_LOOKUPS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "drops", .data = &dqstats.stat[DQST_DROPS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "reads", .data = &dqstats.stat[DQST_READS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "writes", .data = &dqstats.stat[DQST_WRITES], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "cache_hits", .data = &dqstats.stat[DQST_CACHE_HITS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "allocated_dquots", .data = &dqstats.stat[DQST_ALLOC_DQUOTS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "free_dquots", .data = &dqstats.stat[DQST_FREE_DQUOTS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, { .procname = "syncs", .data = &dqstats.stat[DQST_SYNCS], - .maxlen = sizeof(int), + .maxlen = sizeof(unsigned long), .mode = 0444, .proc_handler = do_proc_dqstats, }, diff --git a/include/linux/quota.h b/include/linux/quota.h index f32dd270b8e3f..27aab84fcbaac 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -263,7 +263,7 @@ enum { }; struct dqstats { - int stat[_DQST_DQSTAT_LAST]; + unsigned long stat[_DQST_DQSTAT_LAST]; struct percpu_counter counter[_DQST_DQSTAT_LAST]; }; -- 2.20.1