From patchwork Mon Jul 17 11:52:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315513 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5C8DC001DC for ; Mon, 17 Jul 2023 11:52:53 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 73A7B6B0074; Mon, 17 Jul 2023 07:52:53 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6E9C26B0075; Mon, 17 Jul 2023 07:52:53 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5B1C86B0078; Mon, 17 Jul 2023 07:52:53 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id 4D3DF6B0074 for ; Mon, 17 Jul 2023 07:52:53 -0400 (EDT) Received: from smtpin28.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 162A5A0581 for ; Mon, 17 Jul 2023 11:52:53 +0000 (UTC) X-FDA: 81020942226.28.A316C7C Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf21.hostedemail.com (Postfix) with ESMTP id 5637F1C000F for ; Mon, 17 Jul 2023 11:52:51 +0000 (UTC) Authentication-Results: imf21.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TsAOPnJH; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf21.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594771; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=XNS0pZWYtiz3eLlRvQaHMyf1ULXVatSDvn1Y8OwTP3s=; b=vj45JCWMHg5Ejny8N+744g/KEk4dZ9LMTrO0FTT3QLxSLfmV+ypMA5Jbdz5U8431fXEHtq dyPlCaHH9G3hZf8X84UBRaTYccnKvSweXf5jJsxxQ3H13fSktFrejI567PzvIVl40elaxz XVNVeDWmUYu+ecJm/ynCKAkXqCHfVgM= ARC-Authentication-Results: i=1; imf21.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=TsAOPnJH; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf21.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594771; a=rsa-sha256; cv=none; b=N10f/ueZau7DH/bEjjdh48u6FMcBCNUyUBbZ3SA7yGFX5Vj320Fr/mRDOKvUiC31JOxY+B sw9xoMHgrLpyMjWsHtReM86c+m+Lgc74HorcOCfxTdQR6uN2VGNnB8l+djnv2rrnj4NyJK 09nD73XJb3lGydGW9dhU0x7eeQjkSQU= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 88A7061032; Mon, 17 Jul 2023 11:52:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EA9C5C433C7; Mon, 17 Jul 2023 11:52:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594770; bh=yJe4lhnTjof59vWoLkGO8Qqi3dVE6gVAeA03pQuGI1M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TsAOPnJHZZziesEOWz5VjEy8MCrEPeRToXZg81RrcDiX4eTX8wKnwVA1IvSoWWjDK ZFOjQLFhI0yMHYwpvjwXyc148sefMxnkr08GFVzg9MwGO+/XBCD2y9XBnXftrJkwrh HB9Dvrkp6ZbxNXtBqU8/Y+4D0KkhuZLe+JJpj1wpK1CBgeXAj5H+NuKkWtrxZLRhQm JniNqefLEsuP1YmQveKKRzvIIgpC/4E16yDBDyBZIY8cZFKMG8rSio3SpPS5GeKmCa P74KgqiHZ5Jx+YT4Cr93du0B9oS7ef1uwCmSnEQouQSI1nBBrcqPvv0yx/rIBfM4gB dAZJ+9TpkAgrw== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 1/6] shmem: make shmem_inode_acct_block() return error Date: Mon, 17 Jul 2023 13:52:09 +0200 Message-Id: <20230717115212.208651-2-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 5637F1C000F X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: rwikss5z7ikexatot9bt8duz7ebsqciq X-HE-Tag: 1689594771-515621 X-HE-Meta: U2FsdGVkX19kp/UG3O32PP9f5y78qFvxaihASueuxt7P24hOz+KT2rVm7/IAL+RclzPtzW7dtqZ92n9UFZGxlzcza+un0nFDs1MApCmsYk7aqb4IQ1NQSlcWngUOx9K8rSI0rXvdlv41RvbQOzgV0YcUUuxDjDDC/iaGQfNbyrBI/dRQtD4iRVxqSaPIDZRt7p+U6G0dvzrauvf+r1YE/Mql0k+n40jDbXZZt224an9HopEDIwHAeHexF3cgVEHztyhzzNd7t58fHqVS6T5MqBsGa0OGdWi4rxAZi0mb8747YX7bkrwKkoOFUby1vl0aBe55FUVRN5ry6CNPG4ehc8oJG+mqu7e0eyJhOZvVHVnVaXx31PJnU1/9nbtm25/HGJq7DRfubD2R+eglPdsAC6BOgIEZQZo5Ms8ukDPBM18A/3z6KnWav1lvv07ueO9dYnUv3qBf3YIZfhqr8Wgx5RWcaSGw0+/qdfVkAXmEOq7UJTkqXx1Bobyq7ymgdcNz5JNc6fDrcR3NEn+cSFN/xwAI1VVLZRqJmbuh7t+tuv/iZ0aMPW8gnbBy2PEo0ECbBA9oU3ym9+uV8th4hdcBmAskNYSX73MzeHFs0XUD+994r6TqIUCEjr9d9pbM3hNrU8w4LzS2N6PS3/zlRUP0XvEscq5JNMltThwT+VGVJ3qB0CoqyKObY+aNTLYHXEkaI//J5VUX7ihHI7soHN4h8swA7Yixvs3KAUJe6YbPJkozZB0hn++3dc4Iv/JqLxpTfXcMntbvVCewIADYA9gtF2Mk0liRnnAev9M3/gc/UqKVairx4ji54p8j34dMm5WN/CQntN9KsPB2AYU77AB0BxDhVeqBOXhsCuFcZxyLbc5Pn6wPkFQOx2SdZU6RwFdr0/vvEXnlYB/GuOPSVdO11CQulO/ubRucpICX1bcN6siWn+a+jg1MF2tzbwAXkIk6fnxqsJv8dC89W8MjVTG k9z+YbgA ydJxwaFq4hgD2vxQnLJaUENXvnKp2seO6ru1ZTiSu4EzIkrALZ/NRkGWfbf7MmYMqZaJMlYRc6KjXChRG8zgMY5ZA0Hbafm8b3TzPcROKTCVl56geg1fBCw9gmJ/JMeaJ8M1oeCDliGk4eCCFaLSC0dI21ivYe/eGuv8Ri/UeOSzyDotmPNyAauKZaguc815o9gSS1KsuLh6OwoIFYUNyu7Ut3/VkkGZlSqROHiTcM8TesHCJLA13p+0v+Xc4XchFgTpNveZau8vNBmqke+5hh8ub+zoI95psHe9I4OpiMXTaXvEH1aCJBfkdVHutX+kGPSP17FEB+V6dzoliEkDgASZeYMtEvrC7R3kKNbU2eVFeuKy8KbpzwHiDgHsUgZ1jNbnG X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Lukas Czerner Make shmem_inode_acct_block() return proper error code instead of bool. This will be useful later when we introduce quota support. There should be no functional change. Signed-off-by: Lukas Czerner Signed-off-by: Carlos Maiolino Reviewed-by: Jan Kara --- mm/shmem.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 2f2e0e618072..51d17655a6e1 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -199,13 +199,14 @@ static inline void shmem_unacct_blocks(unsigned long flags, long pages) vm_unacct_memory(pages * VM_ACCT(PAGE_SIZE)); } -static inline bool shmem_inode_acct_block(struct inode *inode, long pages) +static inline int shmem_inode_acct_block(struct inode *inode, long pages) { struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + int err = -ENOSPC; if (shmem_acct_block(info->flags, pages)) - return false; + return err; if (sbinfo->max_blocks) { if (percpu_counter_compare(&sbinfo->used_blocks, @@ -214,11 +215,11 @@ static inline bool shmem_inode_acct_block(struct inode *inode, long pages) percpu_counter_add(&sbinfo->used_blocks, pages); } - return true; + return 0; unacct: shmem_unacct_blocks(info->flags, pages); - return false; + return err; } static inline void shmem_inode_unacct_blocks(struct inode *inode, long pages) @@ -370,7 +371,7 @@ bool shmem_charge(struct inode *inode, long pages) struct shmem_inode_info *info = SHMEM_I(inode); unsigned long flags; - if (!shmem_inode_acct_block(inode, pages)) + if (shmem_inode_acct_block(inode, pages)) return false; /* nrpages adjustment first, then shmem_recalc_inode() when balanced */ @@ -1588,13 +1589,14 @@ static struct folio *shmem_alloc_and_acct_folio(gfp_t gfp, struct inode *inode, struct shmem_inode_info *info = SHMEM_I(inode); struct folio *folio; int nr; - int err = -ENOSPC; + int err; if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) huge = false; nr = huge ? HPAGE_PMD_NR : 1; - if (!shmem_inode_acct_block(inode, nr)) + err = shmem_inode_acct_block(inode, nr); + if (err) goto failed; if (huge) @@ -2445,7 +2447,7 @@ int shmem_mfill_atomic_pte(pmd_t *dst_pmd, int ret; pgoff_t max_off; - if (!shmem_inode_acct_block(inode, 1)) { + if (shmem_inode_acct_block(inode, 1)) { /* * We may have got a page, returned -ENOENT triggering a retry, * and now we find ourselves with -ENOMEM. Release the page, to From patchwork Mon Jul 17 11:52:11 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315514 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2015EB64DC for ; Mon, 17 Jul 2023 11:53:07 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 47B5F6B0075; Mon, 17 Jul 2023 07:53:07 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 42BCE6B0078; Mon, 17 Jul 2023 07:53:07 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 2CBCC8D0001; Mon, 17 Jul 2023 07:53:07 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 1D7AF6B0075 for ; Mon, 17 Jul 2023 07:53:07 -0400 (EDT) Received: from smtpin02.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id E1E12A0583 for ; Mon, 17 Jul 2023 11:53:06 +0000 (UTC) X-FDA: 81020942772.02.3C4F3F4 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf24.hostedemail.com (Postfix) with ESMTP id 1FBC7180011 for ; Mon, 17 Jul 2023 11:53:04 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=QjhrsgFt; spf=pass (imf24.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org; dmarc=pass (policy=none) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594785; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Wq32InAH2gBYYoHF9Ofd9XzMSlQQWj+R7t4StC/4UDA=; b=vgTKpOKM13f/2yEWpo11n/C2dXXBUQicN+sJMDHYhpEJ+9k89mHopBNk0XUxbfaig0fJsW zr9LZuoMYKjWk6voXdTD6BNZzMlGlI5lN5H+KgMTzhEuwaHW07CWd+hRawi4ibZaxKt9+R PaImtFUz11hV/gmyMlpP4Zkn6TEc96Y= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594785; a=rsa-sha256; cv=none; b=2AI++1tONsajYJS6wXTuHHL92VtFiAEbuNGH/syQ+MKIUFxXlZus/tV/K6D6+MkMVU3HWz CDOGZP2gTAnTNtmMS38G0258dTk1fo/O1GpX3PRSiZZFX5xpAlOzU1VjnQuZCYiBG7N4aE 29IvUJAay3cKPqdVHA0Yqu2VHv9ZJpw= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=QjhrsgFt; spf=pass (imf24.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org; dmarc=pass (policy=none) header.from=kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 6403761032; Mon, 17 Jul 2023 11:53:04 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id EDE40C433CA; Mon, 17 Jul 2023 11:52:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594783; bh=HyjiaT6OkD+tH9G9Qx+9mbfsJI7UgpYW54K83e9Gg3U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QjhrsgFtIfHNORCb0SA2biHxF3iS1TmVi3FgSiMaxFY7F42GfK4nSifCq9Zbjl2cs Yk49wNEn7VYJSlaXmOumhs6uIdvhjuMqYpOBiUTnjf3Fkhnl4VtVLfSBhqBczbnLO+ ZVBQ/POuFffFA9ScJZvXYTubCQJrCkGysmDOJO68Db1IJwZwQM7evEZbwwl09Q5KQk vFxs0WMp4xSyJJgrEOIjXy16YXcnJqlr9hj7n7GnXA8rgxF1uQ3r8ru8M0kpbJbneH KZq9TUqZL9RH3BdKfy9hABlJPH5pye3Xsf9yhVJuXPXX4MQBjn6GGvwr8+kId1bZde JD09cDfEK6k9g== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 2/6] shmem: make shmem_get_inode() return ERR_PTR instead of NULL Date: Mon, 17 Jul 2023 13:52:11 +0200 Message-Id: <20230717115212.208651-3-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 1FBC7180011 X-Rspam-User: X-Stat-Signature: aryig8o3rsgatyzinojyip3qgt7htht5 X-Rspamd-Server: rspam03 X-HE-Tag: 1689594784-486184 X-HE-Meta: U2FsdGVkX18RPs1Z37xigEdPus8/fHjdp+oOpBI9QwI+NWpz1EDFMwBUF581NxdUe1XIpPF7iwHEMrCKwE/p78zguyPk1KouOPAVWUIorCuH3AJ6/DqJkUt2Ea3YhLrvUKJj3QMLpedWM9xQIQidWScHSxX3W7mS3jVo7yxP4TiiFGhrUBBnI7tPB9ey2lTLBSCQ8ywY55pT1Oxw42CrAr1k33uTwb7XCtDKV6A5ogaaeKYTCtgjKZwqCe/oWCMv/+1kfSbDekeJF3F04cG1VzGe92i1Lcl7LYosKYLDfw56AaAXbL3af6U1fT6F1vf9l2R6ITmRuZO4qgVUvIbVg6QjJK5STCEs9jZDrpbwk/ef6CFqyDGS5cEVC+yIZ+EIDDg+CEyTx1jA1OCOUSBQgmC+GyGdClEStQvVRE5ce9FGSMEgOJJWm+K0twjDZO2pHXRttQXvFUcnnQt3WElyI110fZkmSG/zoI/b0/+7MVd6ufBIuxrAd6K9NVmKuatLa59vg3ndkV11JF0wCidZbttHKK/yvWociwlb5I812ZPV3y7gf/aTVoTJfmWMgEnCi2cg3EPBWPtpTIRdRngVJi0ZAellSYVNIxFQKKOBi3/2QaKEO3UuiIRiuNuBpCKr7IH6pBu2q4ZPU89SAoChlPnIQCe9A8abrDKsQQOr477iBbhwUZEbc3S5GfF8xRTn8N8u1dhGWQrL2PhDlQLeRcOFqL8HSTqgQAfGi2KDaKwDteFW0Y8HyI1UypbHyVTHuCuxA3Sj5zUVli5p89fnbKgCc49VzO4zBRohNWJ/vl4u5zGGncSF6w7G1K/QMsvPtpVDPkmK8TEdpgpQWc2VxgikSY2iAVmAxga4YE3JhJ8p/Q/4QqG+Y+0+bl4pssFxFBsbSxEA25PAzun3HrSC49sUvfr1Oq2VTUXnn4PA2MtNp6YQ9qbtPHCm0mMteaT+W8YRxjZdnFy2PtqXuuz jWFcpJdu A44GeYLuDdPGeRP3yhMqu3UVb86KoRSythvtz34mkHlbL0g7UT91KsitI93V0FS+nv2k/2shELchS2Iy3U8DefWqj8TzWSgXfhBq2WrzH2ICBl48MPB+1MVKebUJCrLJbXjyiR8vfwaVALNTUuk+xGpCrgKA50rHRs4XDkvp3s4rc7a2vc4zlAYgyFUIgR0KrwAyXk3szO9HNJGl0YRN4vfGMbzpx51V8U17AYDwceszKs9ILc8qwmPfwYASsZ7KJqbBiUQn1f11fzZcmkPg8tOQaI1Z+TJDA85gcOukqHh2kJZz8cdY4aNglYpHUsm9M6IQt6rkmS36W3Wt87ZCZ59P828e0qyE363mJjKiT2DnpXxsmAUe1SnWn9POpYN7xVuD2B4BUOR4PLKW6k5yKuyWutQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Carlos Maiolino Make shmem_get_inode() return ERR_PTR instead of NULL on error. This will be useful later when we introduce quota support. There should be no functional change. Signed-off-by: Lukas Czerner Signed-off-by: Carlos Maiolino Reviewed-by: Jan Kara --- mm/shmem.c | 211 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 119 insertions(+), 92 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 51d17655a6e1..2a7b8060b6f4 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2365,67 +2365,74 @@ static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block struct shmem_inode_info *info; struct shmem_sb_info *sbinfo = SHMEM_SB(sb); ino_t ino; + int err; + + err = shmem_reserve_inode(sb, &ino); + if (err) + return ERR_PTR(err); - if (shmem_reserve_inode(sb, &ino)) - return NULL; inode = new_inode(sb); - if (inode) { - inode->i_ino = ino; - inode_init_owner(idmap, inode, dir, mode); - inode->i_blocks = 0; - inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); - inode->i_generation = get_random_u32(); - info = SHMEM_I(inode); - memset(info, 0, (char *)inode - (char *)info); - spin_lock_init(&info->lock); - atomic_set(&info->stop_eviction, 0); - info->seals = F_SEAL_SEAL; - info->flags = flags & VM_NORESERVE; - info->i_crtime = inode->i_mtime; - info->fsflags = (dir == NULL) ? 0 : - SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED; - if (info->fsflags) - shmem_set_inode_flags(inode, info->fsflags); - INIT_LIST_HEAD(&info->shrinklist); - INIT_LIST_HEAD(&info->swaplist); - if (sbinfo->noswap) - mapping_set_unevictable(inode->i_mapping); - simple_xattrs_init(&info->xattrs); - cache_no_acl(inode); - mapping_set_large_folios(inode->i_mapping); - - switch (mode & S_IFMT) { - default: - inode->i_op = &shmem_special_inode_operations; - init_special_inode(inode, mode, dev); - break; - case S_IFREG: - inode->i_mapping->a_ops = &shmem_aops; - inode->i_op = &shmem_inode_operations; - inode->i_fop = &shmem_file_operations; - mpol_shared_policy_init(&info->policy, - shmem_get_sbmpol(sbinfo)); - break; - case S_IFDIR: - inc_nlink(inode); - /* Some things misbehave if size == 0 on a directory */ - inode->i_size = 2 * BOGO_DIRENT_SIZE; - inode->i_op = &shmem_dir_inode_operations; - inode->i_fop = &simple_dir_operations; - break; - case S_IFLNK: - /* - * Must not load anything in the rbtree, - * mpol_free_shared_policy will not be called. - */ - mpol_shared_policy_init(&info->policy, NULL); - break; - } - lockdep_annotate_inode_mutex_key(inode); - } else + if (!inode) { shmem_free_inode(sb); + return ERR_PTR(-ENOSPC); + } + + inode->i_ino = ino; + inode_init_owner(idmap, inode, dir, mode); + inode->i_blocks = 0; + inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_generation = get_random_u32(); + info = SHMEM_I(inode); + memset(info, 0, (char *)inode - (char *)info); + spin_lock_init(&info->lock); + atomic_set(&info->stop_eviction, 0); + info->seals = F_SEAL_SEAL; + info->flags = flags & VM_NORESERVE; + info->i_crtime = inode->i_mtime; + info->fsflags = (dir == NULL) ? 0 : + SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED; + if (info->fsflags) + shmem_set_inode_flags(inode, info->fsflags); + INIT_LIST_HEAD(&info->shrinklist); + INIT_LIST_HEAD(&info->swaplist); + INIT_LIST_HEAD(&info->swaplist); + if (sbinfo->noswap) + mapping_set_unevictable(inode->i_mapping); + simple_xattrs_init(&info->xattrs); + cache_no_acl(inode); + mapping_set_large_folios(inode->i_mapping); + + switch (mode & S_IFMT) { + default: + inode->i_op = &shmem_special_inode_operations; + init_special_inode(inode, mode, dev); + break; + case S_IFREG: + inode->i_mapping->a_ops = &shmem_aops; + inode->i_op = &shmem_inode_operations; + inode->i_fop = &shmem_file_operations; + mpol_shared_policy_init(&info->policy, + shmem_get_sbmpol(sbinfo)); + break; + case S_IFDIR: + inc_nlink(inode); + /* Some things misbehave if size == 0 on a directory */ + inode->i_size = 2 * BOGO_DIRENT_SIZE; + inode->i_op = &shmem_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + break; + case S_IFLNK: + /* + * Must not load anything in the rbtree, + * mpol_free_shared_policy will not be called. + */ + mpol_shared_policy_init(&info->policy, NULL); + break; + } + + lockdep_annotate_inode_mutex_key(inode); return inode; } @@ -3071,27 +3078,30 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { struct inode *inode; - int error = -ENOSPC; + int error; inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, dev, VM_NORESERVE); - if (inode) { - error = simple_acl_create(dir, inode); - if (error) - goto out_iput; - error = security_inode_init_security(inode, dir, - &dentry->d_name, - shmem_initxattrs, NULL); - if (error && error != -EOPNOTSUPP) - goto out_iput; - error = 0; - dir->i_size += BOGO_DIRENT_SIZE; - dir->i_ctime = dir->i_mtime = current_time(dir); - inode_inc_iversion(dir); - d_instantiate(dentry, inode); - dget(dentry); /* Extra count - pin the dentry in core */ - } + if (IS_ERR(inode)) + return PTR_ERR(inode); + + error = simple_acl_create(dir, inode); + if (error) + goto out_iput; + error = security_inode_init_security(inode, dir, + &dentry->d_name, + shmem_initxattrs, NULL); + if (error && error != -EOPNOTSUPP) + goto out_iput; + + error = 0; + dir->i_size += BOGO_DIRENT_SIZE; + dir->i_ctime = dir->i_mtime = current_time(dir); + inode_inc_iversion(dir); + d_instantiate(dentry, inode); + dget(dentry); /* Extra count - pin the dentry in core */ return error; + out_iput: iput(inode); return error; @@ -3102,20 +3112,26 @@ shmem_tmpfile(struct mnt_idmap *idmap, struct inode *dir, struct file *file, umode_t mode) { struct inode *inode; - int error = -ENOSPC; + int error; inode = shmem_get_inode(idmap, dir->i_sb, dir, mode, 0, VM_NORESERVE); - if (inode) { - error = security_inode_init_security(inode, dir, - NULL, - shmem_initxattrs, NULL); - if (error && error != -EOPNOTSUPP) - goto out_iput; - error = simple_acl_create(dir, inode); - if (error) - goto out_iput; - d_tmpfile(file, inode); + + if (IS_ERR(inode)) { + error = PTR_ERR(inode); + goto err_out; } + + error = security_inode_init_security(inode, dir, + NULL, + shmem_initxattrs, NULL); + if (error && error != -EOPNOTSUPP) + goto out_iput; + error = simple_acl_create(dir, inode); + if (error) + goto out_iput; + d_tmpfile(file, inode); + +err_out: return finish_open_simple(file, error); out_iput: iput(inode); @@ -3290,8 +3306,9 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, inode = shmem_get_inode(idmap, dir->i_sb, dir, S_IFLNK | 0777, 0, VM_NORESERVE); - if (!inode) - return -ENOSPC; + + if (IS_ERR(inode)) + return PTR_ERR(inode); error = security_inode_init_security(inode, dir, &dentry->d_name, shmem_initxattrs, NULL); @@ -3929,12 +3946,13 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) struct shmem_options *ctx = fc->fs_private; struct inode *inode; struct shmem_sb_info *sbinfo; + int error = -ENOMEM; /* Round up to L1_CACHE_BYTES to resist false sharing */ sbinfo = kzalloc(max((int)sizeof(struct shmem_sb_info), L1_CACHE_BYTES), GFP_KERNEL); if (!sbinfo) - return -ENOMEM; + return error; sb->s_fs_info = sbinfo; @@ -3997,8 +4015,10 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) inode = shmem_get_inode(&nop_mnt_idmap, sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE); - if (!inode) + if (IS_ERR(inode)) { + error = PTR_ERR(inode); goto failed; + } inode->i_uid = sbinfo->uid; inode->i_gid = sbinfo->gid; sb->s_root = d_make_root(inode); @@ -4008,7 +4028,7 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) failed: shmem_put_super(sb); - return -ENOMEM; + return error; } static int shmem_get_tree(struct fs_context *fc) @@ -4377,10 +4397,16 @@ EXPORT_SYMBOL_GPL(shmem_truncate_range); #define shmem_vm_ops generic_file_vm_ops #define shmem_anon_vm_ops generic_file_vm_ops #define shmem_file_operations ramfs_file_operations -#define shmem_get_inode(idmap, sb, dir, mode, dev, flags) ramfs_get_inode(sb, dir, mode, dev) #define shmem_acct_size(flags, size) 0 #define shmem_unacct_size(flags, size) do {} while (0) +static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block *sb, struct inode *dir, + umode_t mode, dev_t dev, unsigned long flags) +{ + struct inode *inode = ramfs_get_inode(sb, dir, mode, dev); + return inode ? inode : ERR_PTR(-ENOSPC); +} + #endif /* CONFIG_SHMEM */ /* common code */ @@ -4405,9 +4431,10 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l inode = shmem_get_inode(&nop_mnt_idmap, mnt->mnt_sb, NULL, S_IFREG | S_IRWXUGO, 0, flags); - if (unlikely(!inode)) { + + if (IS_ERR(inode)) { shmem_unacct_size(flags, size); - return ERR_PTR(-ENOSPC); + return ERR_CAST(inode); } inode->i_flags |= i_flags; inode->i_size = size; From patchwork Mon Jul 17 11:52:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315515 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94617C001DC for ; Mon, 17 Jul 2023 11:53:26 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2CC316B0072; Mon, 17 Jul 2023 07:53:26 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 27C816B0078; Mon, 17 Jul 2023 07:53:26 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 16BD18D0001; Mon, 17 Jul 2023 07:53:26 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 0741A6B0072 for ; Mon, 17 Jul 2023 07:53:26 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id D03A7120524 for ; Mon, 17 Jul 2023 11:53:25 +0000 (UTC) X-FDA: 81020943570.06.2E753A9 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf07.hostedemail.com (Postfix) with ESMTP id 158324001E for ; Mon, 17 Jul 2023 11:53:23 +0000 (UTC) Authentication-Results: imf07.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=NgK1YF37; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf07.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594804; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=1IAdq4n5/oIzAGmJbwcaTZVO+ZHOV/slhcqGbtISZa0=; b=zRhJFaDXIo5+XQvjts4677rwTdI/V5g1VSgcLLQXhl8y7MVkwcJKXi68G2mZbV/tSdUv5c QeS4663TiNuk+7zDeP/eBjxvCAEW6ozF6k0fsCae2Y5aToKsck9mXyuXb4m4auNIieYxS+ Lfel8p+ICSK1rVrePAAsayoluTD2BC4= ARC-Authentication-Results: i=1; imf07.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=NgK1YF37; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf07.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594804; a=rsa-sha256; cv=none; b=6CU34jHBGpXiLn0uKyKQ9n2evKqyBCVx8FnuzUbldevKFrGvRg0MfuYXM4WO8gB5nCX4hr oz0a0TSJOl9V9m7u3c8iGC4SCW7cWY2gOCZ1vQk9jJQGIgo2l9erMYJKh7KwAwVZQFEmRz oAF0nvmPvnagDRmhfnWHCvWmbLtKUQM= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 0818A6103C; Mon, 17 Jul 2023 11:53:23 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7F7C3C433C7; Mon, 17 Jul 2023 11:53:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594802; bh=okwg5m+9iRcDR+mIe+e593XoCBrrkAftdLKtFY7t22A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=NgK1YF37XbP9j3RFJRCOWrO8Z9eFBFeaswFRaTRK52mri/14LvTVamSqGrfkgET5I 73ZJ9jFmvCb6Isbl6smJZ3tyVwdYWxF7Ahwog+f2fAJ+qwp50vML0CSnryw9G8SsD4 My7IO/bcA1u4OS/SVGzwTFUp7cbgm5yYgvsUUbCtkCaFfiqMrwB+vy1KpVkb4uOFw2 2mIr7dt13Gt+/Wfj8sJvphMtH1u7YsXK0+4kw9AQ+mL4YC4UbU+TDNJlJYmOk9lnfA sOBjeCrdsfzE7ENtPNcixHssScYzPx6wbx/6f/KdxtYY1nDOVuRfuFOGZap7atOG28 Ry5dPQ9XUWn4g== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 3/6] quota: Check presence of quota operation structures instead of ->quota_read and ->quota_write callbacks Date: Mon, 17 Jul 2023 13:52:13 +0200 Message-Id: <20230717115212.208651-4-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 158324001E X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: jopxeeycc94dqzra55xzk8ukcuewz7sg X-HE-Tag: 1689594803-84931 X-HE-Meta: U2FsdGVkX1+O9AsesjbzO/nU9kGxOWmRddLUxjdzbCmXifkCACF7/aHyFiBtF1T3L+VRLPinJMzDQSwktMhGxGKeg3OdxihkQ0FW0+LnwsQyxcL7u6cxi7Ga8CPhHu9JbULaSKAzdtYFDY10qpNNVcTcd6n5oqAgVfsX04RV8IvUKvZHCN+TuNO+6cDW4sBOokaS+V5uR5ysJmUExN6RG10IiBdhq4Nig+bqWO/tSRT9V4zvNAUvdTmqH/MiQbcjINcIb5iceuw8xAD6TrZuuk1xUQuJqD5BFGWGoufKY8yIZ9lwM7c2KqPUCnvre+ylqL6x21n9U7goA64Tu1ngIFXL1M0mgWLPCG1mN/OUpI000Ftisqbd4SGXadOf8OnPgr1GDN8gdeJo/LatRPcHlM1AqF0awR7dEa7RaE/IRq2lZ2BFWNZCeIZYGsF5x5AeuyA5jrQaCPO+pwA2Bt6N6RtGgitXNNxipr92kCkQKnd3ZChyE+zYWUJsL1mtZDPyLr6SQ7te1KImlENs4fCJXUYWEZ2HQCNZR7PxdPNNclHUqYfJUBG2YXD634E29CuEFKzvL+FL8CNsYZbNsO0EDWb4JPNh+6P4IYzseHXUwF3ZySV+DRUaROi2ZV2Trgd3dnw5GpmzhuyYRKBtb88Nic121lUE5xtyh11+T31p8ith3Rvt3TMVR4MnMgl+V0CHGAy81fKyzlKI5qfR0kDtntKdJ3rxof1S1AEo7KzLNJurp5brkXthJUlZB3EGZIds4uPq75SiGqQIhssLxr5AU/wPYOlSPbymdqkLUiE0Rbb3N+Ewd23zyofWIBmULWUnWWnUDlUa4vJTFMFgDDNwhcy1HU/8QGi9Fa+f68QbQLeKcleAt9mjSdwGnczO0JFz2f9StpRBfoq6e9lBgJluQXQICt4vTaACwQ/ICbRVGRcWKs1J+5LW7L7YpzwHZwVbDDw2jT7GxsjnmOBvrG0 BtccwGtl 4ogh5HewzbjbyNgsYSGCaLAGfJltG8GXvU3bPCwIhxYWsSolY0nkXPlLDuUkjh8yA0jQTry0nlleFJMgK6QX0FTKBkHY+9/boYjPYbJkX1xT2bdjfIlrvPSK3fEx6CZkwfSbg20eBQly49Lwtd6floBFejFs23clMFVm5LThbxemp4oCtNjinFEyvGPZ2GNj8/JOOJJ5IuHEJ9lT0sVRl/STKyR+9yYwU3q6az+sMS4+zMW/KJKbSthpxkLEiD/AeZB/8FG2z9iPZYCbL1ww6CRDV1mquh+O06QgULfxe1HEfqHWhBOzE64/9LWI4kxjUwvRBbqiBOdXY2fP7hljF6ZBK7A== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Jan Kara Currently we check whether superblock has ->quota_read and ->quota_write operations to check whether filesystem supports quotas. However for example for shmfs we will not read or write dquots so check whether quota operations are set in the superblock instead. Signed-off-by: Jan Kara Reviewed-by: Carlos Maiolino --- fs/quota/dquot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index e3e4f4047657..4d826c369da2 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -2367,7 +2367,7 @@ int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, if (!fmt) return -ESRCH; - if (!sb->s_op->quota_write || !sb->s_op->quota_read || + if (!sb->dq_op || !sb->s_qcop || (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) { error = -EINVAL; goto out_fmt; From patchwork Mon Jul 17 11:52:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315516 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7D979EB64DC for ; Mon, 17 Jul 2023 11:53:34 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 193F66B0078; Mon, 17 Jul 2023 07:53:34 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 1459B8D0001; Mon, 17 Jul 2023 07:53:34 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 00D566B007D; Mon, 17 Jul 2023 07:53:33 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id E6A076B0078 for ; Mon, 17 Jul 2023 07:53:33 -0400 (EDT) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id BF117B0DC2 for ; Mon, 17 Jul 2023 11:53:33 +0000 (UTC) X-FDA: 81020943906.23.DC89155 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf19.hostedemail.com (Postfix) with ESMTP id 202B91A000D for ; Mon, 17 Jul 2023 11:53:31 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lUGOgaNh; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf19.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594812; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=QrtdvJDPDhoNM+nIUOzreXjMnv8phOjCrSOh8GGkxoQ=; b=yD1946RmdK6R8K/7v51iqxzBfvK1t98hyXGzAa2UexuHEVVznYSghBl0B+F3phi6eUnbqB 4WVYbaXuo3TzQYd014Ggjj/1gFniK2PW/uVTaKNeR+XlVV/P0uQ2mZG0AYFf5RXlhhaaqe HbgidjnnnuDSbV+UBMBZX14Aiwiturk= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=lUGOgaNh; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf19.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594812; a=rsa-sha256; cv=none; b=bp8dSMlYy1PnEJlL4gvuWYtgELzueAsGhPRPXqa75RpPKdNjThHkOWbPZ26LuzPC2CdXh1 xzXvHfyowx4lMg4B2GwqzkY4jqSn/GIrZd0WTwoMQLz1POiE7Nu1nYqKSVg50qDXee+pn5 ft4u1slWbK1MyPS6/LD23APNMXlZvME= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 62E6461035; Mon, 17 Jul 2023 11:53:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id AE21CC433C9; Mon, 17 Jul 2023 11:53:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594810; bh=7ujiWzBqUHHMtvILuGdMIIGD3amWSSvl55kgym4kt2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lUGOgaNh0d4rSXgKybDBHEzlBProS3bOYj5/wJAu3SaTAZFRUdRrYVq8+Sjthb2BH otBMGTgYfXyThCmDkN4xcdU/UumspTtjl9qTSgCp8g5SS+lxed2iIhugmggRYexRHX gIekHlUuqvJIsEz1oEMRnoLTwIFtf7wGwL8DIImb3iFaplXAI7QsB4IM39Ci3OqvP8 9mVedH95rBuH/S7UCtNXxzbVYvMy/wRMaIUA9RBNPB/qmdzkds4zK6kqnCA8gLVgJX 2JlemVVqUKykaliZIRJBf+Qi5DOUiMjuN06NAbWFVqOjOJrucd17mIAdLXQ590qyJQ QYTiUIkVqoMnQ== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 4/6] shmem: prepare shmem quota infrastructure Date: Mon, 17 Jul 2023 13:52:15 +0200 Message-Id: <20230717115212.208651-5-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 202B91A000D X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: gn6b1t86fh763cd9bei3qui9opeiwati X-HE-Tag: 1689594811-357165 X-HE-Meta: U2FsdGVkX1+OcSEVFP9YGlWTNAUDrMiNCIhpTa5iTaR4nFKssw0R68TsZuEBRcsKF0hsia25Wg7IQA1NTQljOzaUfAuYqUu+yUXOFFJMCBSJQC9jI2spnQvybHGTJwq6KkR72AZC2WdyY+pQRE83SHwuh23KXKEnUWWXhP6CSzDfyT41IBlss/c/G7vTWDzLUS98dUo0ET4EdLZ+bKizTVXYpTTNIzBeh+c4LaqLTaFk2jg5eZ84DNs3OTDM07pPHMlpAmyJT9xEyIHstsslUUW+uhmH/HQZeBWSDPOcLnKIwHJgM0YIGCMt1KyKJA5fkku+tzAZ9/FMlb6c2R0VVR6lEq4R9zBP6qW0cwIQa0g611Q2FwDZFESEG/Niws7OrGqGLO9iNzDNgaftl5RlEKY6UEGDIqvmGoTf+OZKeiYHUF5HSykF4aEUUWAz8RiDMoJMzcx4q8Zr+C4a+0TVnCUIDLSBcr7/rljSIOh+TbvWRcEQw++0/C4lH8ywF0WEEev+PepnMW2hDgOwlO+s/TdrXZ3skkFkK1j4U8BN0Ed6PoeIZ4d8cSSZAQFtO9Tj8xWZh33BRgwoeM6div6qhfZ0rUNNCi3CmrPFAp8KTgRu7Dt3j4v7VnggLqHefXOK4IioWBsFWcABtfwflYr6MAdeOgLoZpam26gXS13FB0H+3u6HvcBdEetBzlLUR4WTc3vItj1HCLzH4ccRDRpfETAfHBp4gP9/O7PFZMdpr57bWL/rYlTon8KoIOmxKWDLBVsRPuI9cwBMGWpAs8Rg62w4KhTA2761hFxW15u6+fq902URSR1bCE9almqjXsnp39CGRQb4N9yL2W0F/jka65zKExZX/wgKjBgpNbvIooniDUHGwhykrzPhCdw5+5VSZy1bZfRF+uAwDiQgbLMJkOFLzXVP1/EJJSMiT/N7sXhyPQCAv9SKuL6U/Q+DdtSJk05+9GuODk1tb/V6Dd5 6T/E/V3p OC7MfYIurvXl9oWaOuzrI1J3f+8jq6YPne4nvzgW2SnCmx/LMBw1sCJ/ToWsfk9CKXGuWriKZzTlW4GxFZ8KLx/KnPkhL+5lEq/yoUKUUABV2R+hMfbRBKs4Qy0df+3lCbigbpJ1h8FQVjKMnFgVeGCqZsWkGRIs5ULUFac7NdUxLwPC+JWhaEuvfvlJ/a3nzvc6R8160xQLb9WYDVoqHNQ9zhZl/coN35v22a6/dIbj2ubAw7dH64WPfcHvd8gMXQVqxB8ADlOiqw6jbuKe1/nquucCYEKxpKH5P6X9m+xccFq5AvBCFcSBSo/bD/MXdXETmrQN5jp658tSGerK+0lPTHq0dy5iFMpEch85giAnqWG8= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Carlos Maiolino Add new shmem quota format, its quota_format_ops together with dquot_operations Signed-off-by: Lukas Czerner Signed-off-by: Carlos Maiolino Reviewed-by: Jan Kara --- fs/Kconfig | 12 ++ include/linux/shmem_fs.h | 12 ++ include/uapi/linux/quota.h | 1 + mm/Makefile | 2 +- mm/shmem_quota.c | 318 +++++++++++++++++++++++++++++++++++++ 5 files changed, 344 insertions(+), 1 deletion(-) create mode 100644 mm/shmem_quota.c diff --git a/fs/Kconfig b/fs/Kconfig index 18d034ec7953..8218a71933f9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -233,6 +233,18 @@ config TMPFS_INODE64 If unsure, say N. +config TMPFS_QUOTA + bool "Tmpfs quota support" + depends on TMPFS + select QUOTA + help + Quota support allows to set per user and group limits for tmpfs + usage. Say Y to enable quota support. Once enabled you can control + user and group quota enforcement with quota, usrquota and grpquota + mount options. + + If unsure, say N. + config ARCH_SUPPORTS_HUGETLBFS def_bool n diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 9029abd29b1c..7abfaf70b58a 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -13,6 +13,10 @@ /* inode in-kernel data */ +#ifdef CONFIG_TMPFS_QUOTA +#define SHMEM_MAXQUOTAS 2 +#endif + struct shmem_inode_info { spinlock_t lock; unsigned int seals; /* shmem seals */ @@ -172,4 +176,12 @@ extern int shmem_mfill_atomic_pte(pmd_t *dst_pmd, #endif /* CONFIG_SHMEM */ #endif /* CONFIG_USERFAULTFD */ +/* + * Used space is stored as unsigned 64-bit value in bytes but + * quota core supports only signed 64-bit values so use that + * as a limit + */ +#define SHMEM_QUOTA_MAX_SPC_LIMIT 0x7fffffffffffffffLL /* 2^63-1 */ +#define SHMEM_QUOTA_MAX_INO_LIMIT 0x7fffffffffffffffLL + #endif diff --git a/include/uapi/linux/quota.h b/include/uapi/linux/quota.h index f17c9636a859..52090105b828 100644 --- a/include/uapi/linux/quota.h +++ b/include/uapi/linux/quota.h @@ -77,6 +77,7 @@ #define QFMT_VFS_V0 2 #define QFMT_OCFS2 3 #define QFMT_VFS_V1 4 +#define QFMT_SHMEM 5 /* Size of block in which space limits are passed through the quota * interface */ diff --git a/mm/Makefile b/mm/Makefile index 678530a07326..d4ee20988dd1 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -51,7 +51,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ util.o mmzone.o vmstat.o backing-dev.o \ mm_init.o percpu.o slab_common.o \ - compaction.o show_mem.o\ + compaction.o show_mem.o shmem_quota.o\ interval_tree.o list_lru.o workingset.o \ debug.o gup.o mmap_lock.o $(mmu-y) diff --git a/mm/shmem_quota.c b/mm/shmem_quota.c new file mode 100644 index 000000000000..c0b531e2ef68 --- /dev/null +++ b/mm/shmem_quota.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * In memory quota format relies on quota infrastructure to store dquot + * information for us. While conventional quota formats for file systems + * with persistent storage can load quota information into dquot from the + * storage on-demand and hence quota dquot shrinker can free any dquot + * that is not currently being used, it must be avoided here. Otherwise we + * can lose valuable information, user provided limits, because there is + * no persistent storage to load the information from afterwards. + * + * One information that in-memory quota format needs to keep track of is + * a sorted list of ids for each quota type. This is done by utilizing + * an rb tree which root is stored in mem_dqinfo->dqi_priv for each quota + * type. + * + * This format can be used to support quota on file system without persistent + * storage such as tmpfs. + * + * Author: Lukas Czerner + * Carlos Maiolino + * + * Copyright (C) 2023 Red Hat, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_TMPFS_QUOTA + +/* + * The following constants define the amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define SHMEM_MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define SHMEM_MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +struct quota_id { + struct rb_node node; + qid_t id; + qsize_t bhardlimit; + qsize_t bsoftlimit; + qsize_t ihardlimit; + qsize_t isoftlimit; +}; + +static int shmem_check_quota_file(struct super_block *sb, int type) +{ + /* There is no real quota file, nothing to do */ + return 1; +} + +/* + * There is no real quota file. Just allocate rb_root for quota ids and + * set limits + */ +static int shmem_read_file_info(struct super_block *sb, int type) +{ + struct quota_info *dqopt = sb_dqopt(sb); + struct mem_dqinfo *info = &dqopt->info[type]; + + info->dqi_priv = kzalloc(sizeof(struct rb_root), GFP_NOFS); + if (!info->dqi_priv) + return -ENOMEM; + + info->dqi_max_spc_limit = SHMEM_QUOTA_MAX_SPC_LIMIT; + info->dqi_max_ino_limit = SHMEM_QUOTA_MAX_INO_LIMIT; + + info->dqi_bgrace = SHMEM_MAX_DQ_TIME; + info->dqi_igrace = SHMEM_MAX_IQ_TIME; + info->dqi_flags = 0; + + return 0; +} + +static int shmem_write_file_info(struct super_block *sb, int type) +{ + /* There is no real quota file, nothing to do */ + return 0; +} + +/* + * Free all the quota_id entries in the rb tree and rb_root. + */ +static int shmem_free_file_info(struct super_block *sb, int type) +{ + struct mem_dqinfo *info = &sb_dqopt(sb)->info[type]; + struct rb_root *root = info->dqi_priv; + struct quota_id *entry; + struct rb_node *node; + + info->dqi_priv = NULL; + node = rb_first(root); + while (node) { + entry = rb_entry(node, struct quota_id, node); + node = rb_next(&entry->node); + + rb_erase(&entry->node, root); + kfree(entry); + } + + kfree(root); + return 0; +} + +static int shmem_get_next_id(struct super_block *sb, struct kqid *qid) +{ + struct mem_dqinfo *info = sb_dqinfo(sb, qid->type); + struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node; + qid_t id = from_kqid(&init_user_ns, *qid); + struct quota_info *dqopt = sb_dqopt(sb); + struct quota_id *entry = NULL; + int ret = 0; + + if (!sb_has_quota_active(sb, qid->type)) + return -ESRCH; + + down_read(&dqopt->dqio_sem); + while (node) { + entry = rb_entry(node, struct quota_id, node); + + if (id < entry->id) + node = node->rb_left; + else if (id > entry->id) + node = node->rb_right; + else + goto got_next_id; + } + + if (!entry) { + ret = -ENOENT; + goto out_unlock; + } + + if (id > entry->id) { + node = rb_next(&entry->node); + if (!node) { + ret = -ENOENT; + goto out_unlock; + } + entry = rb_entry(node, struct quota_id, node); + } + +got_next_id: + *qid = make_kqid(&init_user_ns, qid->type, entry->id); +out_unlock: + up_read(&dqopt->dqio_sem); + return ret; +} + +/* + * Load dquot with limits from existing entry, or create the new entry if + * it does not exist. + */ +static int shmem_acquire_dquot(struct dquot *dquot) +{ + struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); + struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node; + struct rb_node *parent = NULL, *new_node = NULL; + struct quota_id *new_entry, *entry; + qid_t id = from_kqid(&init_user_ns, dquot->dq_id); + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); + int ret = 0; + + mutex_lock(&dquot->dq_lock); + + down_write(&dqopt->dqio_sem); + while (*n) { + parent = *n; + entry = rb_entry(parent, struct quota_id, node); + + if (id < entry->id) + n = &(*n)->rb_left; + else if (id > entry->id) + n = &(*n)->rb_right; + else + goto found; + } + + /* We don't have entry for this id yet, create it */ + new_entry = kzalloc(sizeof(struct quota_id), GFP_NOFS); + if (!new_entry) { + ret = -ENOMEM; + goto out_unlock; + } + + new_entry->id = id; + new_node = &new_entry->node; + rb_link_node(new_node, parent, n); + rb_insert_color(new_node, (struct rb_root *)info->dqi_priv); + entry = new_entry; + +found: + /* Load the stored limits from the tree */ + spin_lock(&dquot->dq_dqb_lock); + dquot->dq_dqb.dqb_bhardlimit = entry->bhardlimit; + dquot->dq_dqb.dqb_bsoftlimit = entry->bsoftlimit; + dquot->dq_dqb.dqb_ihardlimit = entry->ihardlimit; + dquot->dq_dqb.dqb_isoftlimit = entry->isoftlimit; + + if (!dquot->dq_dqb.dqb_bhardlimit && + !dquot->dq_dqb.dqb_bsoftlimit && + !dquot->dq_dqb.dqb_ihardlimit && + !dquot->dq_dqb.dqb_isoftlimit) + set_bit(DQ_FAKE_B, &dquot->dq_flags); + spin_unlock(&dquot->dq_dqb_lock); + + /* Make sure flags update is visible after dquot has been filled */ + smp_mb__before_atomic(); + set_bit(DQ_ACTIVE_B, &dquot->dq_flags); +out_unlock: + up_write(&dqopt->dqio_sem); + mutex_unlock(&dquot->dq_lock); + return ret; +} + +/* + * Store limits from dquot in the tree unless it's fake. If it is fake + * remove the id from the tree since there is no useful information in + * there. + */ +static int shmem_release_dquot(struct dquot *dquot) +{ + struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); + struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node; + qid_t id = from_kqid(&init_user_ns, dquot->dq_id); + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); + struct quota_id *entry = NULL; + + mutex_lock(&dquot->dq_lock); + /* Check whether we are not racing with some other dqget() */ + if (dquot_is_busy(dquot)) + goto out_dqlock; + + down_write(&dqopt->dqio_sem); + while (node) { + entry = rb_entry(node, struct quota_id, node); + + if (id < entry->id) + node = node->rb_left; + else if (id > entry->id) + node = node->rb_right; + else + goto found; + } + + /* We should always find the entry in the rb tree */ + WARN_ONCE(1, "quota id %u from dquot %p, not in rb tree!\n", id, dquot); + up_write(&dqopt->dqio_sem); + mutex_unlock(&dquot->dq_lock); + return -ENOENT; + +found: + if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) { + /* Remove entry from the tree */ + rb_erase(&entry->node, info->dqi_priv); + kfree(entry); + } else { + /* Store the limits in the tree */ + spin_lock(&dquot->dq_dqb_lock); + entry->bhardlimit = dquot->dq_dqb.dqb_bhardlimit; + entry->bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit; + entry->ihardlimit = dquot->dq_dqb.dqb_ihardlimit; + entry->isoftlimit = dquot->dq_dqb.dqb_isoftlimit; + spin_unlock(&dquot->dq_dqb_lock); + } + + clear_bit(DQ_ACTIVE_B, &dquot->dq_flags); + up_write(&dqopt->dqio_sem); + +out_dqlock: + mutex_unlock(&dquot->dq_lock); + return 0; +} + +int shmem_mark_dquot_dirty(struct dquot *dquot) +{ + return 0; +} + +int shmem_dquot_write_info(struct super_block *sb, int type) +{ + return 0; +} + +static const struct quota_format_ops shmem_format_ops = { + .check_quota_file = shmem_check_quota_file, + .read_file_info = shmem_read_file_info, + .write_file_info = shmem_write_file_info, + .free_file_info = shmem_free_file_info, +}; + +struct quota_format_type shmem_quota_format = { + .qf_fmt_id = QFMT_SHMEM, + .qf_ops = &shmem_format_ops, + .qf_owner = THIS_MODULE +}; + +const struct dquot_operations shmem_quota_operations = { + .acquire_dquot = shmem_acquire_dquot, + .release_dquot = shmem_release_dquot, + .alloc_dquot = dquot_alloc, + .destroy_dquot = dquot_destroy, + .write_info = shmem_dquot_write_info, + .mark_dirty = shmem_mark_dquot_dirty, + .get_next_id = shmem_get_next_id, +}; +#endif /* CONFIG_TMPFS_QUOTA */ From patchwork Mon Jul 17 11:52:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 88903C0015E for ; Mon, 17 Jul 2023 11:53:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 31B7F6B0078; Mon, 17 Jul 2023 07:53:50 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 2CB056B007B; Mon, 17 Jul 2023 07:53:50 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 192D66B007D; Mon, 17 Jul 2023 07:53:50 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 0BD1F6B0078 for ; Mon, 17 Jul 2023 07:53:50 -0400 (EDT) Received: from smtpin04.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id BA496405BE for ; Mon, 17 Jul 2023 11:53:49 +0000 (UTC) X-FDA: 81020944578.04.A92DF2C Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf24.hostedemail.com (Postfix) with ESMTP id DF5EA180006 for ; Mon, 17 Jul 2023 11:53:47 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=bbf7EDBF; spf=pass (imf24.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org; dmarc=pass (policy=none) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594828; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=dqwY/sZKbccwa0fELSyGj6RVtMz7lkTb/EhdFQx0O3w=; b=mcRJim6PCU8Inuq7OCVJ5UYYmEKlW8m7MchoijjSH034BTgO1TBFu4foUrLfmaP09jXPwd qY464BDnHsHcDhrTJP7w6RgE1HivpiqD3GyBkjtmOc0uPc9P22/S8aj1ERaWPdvGTS0v9i +mHhnikGu1IxSz+A8nr3KEfG4esxo2I= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594828; a=rsa-sha256; cv=none; b=WItirZy1yJKyS3BBxAqP4+X/E+7cVvCRZcIg76sOZSvQsWfMq/6tb36zKQjQ3dCMDDXCBb td5bdU7zXUkKA35TetfNXoOKw1O/sExutcRADmOQrlajU7XHR8N+cz36VHkQulj6FU7Bhh FFDQQNwMHYSMMncw0t3Kojo2mjFPj2c= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=bbf7EDBF; spf=pass (imf24.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org; dmarc=pass (policy=none) header.from=kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id F1E3361035; Mon, 17 Jul 2023 11:53:46 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 12034C433C8; Mon, 17 Jul 2023 11:53:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594826; bh=Pho13/08KZczHZE+C5mfvanCP206awvU3M7nENcmBcg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bbf7EDBF1H5OjAyZycV++gIgu+huiAV2TOHSYy05tqYi8v9cnp4K2ZgTNV358sQ4x kyYk3EFVxY0C/Mflv/PifiAKlIAs3XTuw5kq+0GuthjJGtg9mcR1diHIQfagfWSF+k zGCIH9sAsg+m8/HhQHqBP4bpij/3ixigkwrk3Fcjcf5PZGvGEt7OASbOBdwn3Q5YVd BvBHoII3AlnSxMfRiysmOyslTdunt1jTiroqSF9WdEH/NZt16kKzXO+eVo8H4ejfk6 coAoI89xRrQZLT3FGv5Rxdg/xr5E7OeBgWomPqYzVyb2u67tW1cA+7fGCXH166b1/U DvGeLCwNNZywQ== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 5/6] shmem: quota support Date: Mon, 17 Jul 2023 13:52:17 +0200 Message-Id: <20230717115212.208651-6-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Stat-Signature: rx5kq9ag6kuh7p3sy8puujc3kmypw4wi X-Rspamd-Server: rspam10 X-Rspamd-Queue-Id: DF5EA180006 X-Rspam-User: X-HE-Tag: 1689594827-465329 X-HE-Meta: U2FsdGVkX19/t7MoTtAIzzKYcnekGrRuwtxbvw8ILTRSX8/g4qZ064Ol+BpyJjOel5YLHepr5YTSjg59UYzakyR0TooaWYeH/DRS600dUGhPzBOx1MPXMTnU8xEbsFtCCmjWOiJn0ETOftPoQqEFECdC8qCzpUTyf4qjpn6zyy2pEepuzUPw6hnIv9Q+e+ZyL5idb+4I0BUQGvf1rP+tMTVF7ToaVsjgXhu3BBsLfjq4F/rCUTm1Y9BV8fisPdGaIn0yb3KCsDCB8e64HX+QelILGiHs+3rWSY6106jLXJWmkarLTiqAVpY/NY+JE3pkAhsIoF/WMbwWKsSIUAR6C2syR/a9xIY33iFKVwJ2w2mVTyZZisgRtNHmIRngTL4mDVBYDLbR0BojJ+Bw8O1tlfrXfw7zyBlfpN2ZbRu+eVgM0jlOM3BIckRruNQcglmhGdSls1encZKQxQY8Z7UxR3YMw4mRB0kSgvkQM11WAmyAdyxNj5olx+xV9Xj8FYMiJrpd7R/MtA6CJcpvQJ8x15oU7/ssq1ZbAG9yF5EoWn0JGkV73yyO8/uzrwn741ehNvVXMMnViPqyWwgbjedsDAd3RwGp3rpc7siRTD9CYmnLlabbPlla69bZxwel4JmZ88ZJCLncO6K3NDZEdPNltFSh0+gZgp3/gNUvnnUMxMQczVZnMhuMAU84jg41Djge09mvBTK95vYOCN8GD6GAdHHxzKOyRM3qA0z5rQUnuHyxW0Ee2lfHR2tLy9HjEKkZLuM+gbMHfZrUZOuBKrtkNHRVKWTb23+5Rx3JT4cRYfwRCUniIrBRrymBA+RWQCis9k+qq5wbtxqePJyKh9803OECiZWOhBno7bSxTx4U3KC2EC+05RFsHqqd5j7Zm64/30OlSXlFFstlqF6FspSxwNLu3WbpzpWN/qFsLuO7bS7REymfEt4PGDSaDMa7I49ySWBPtUyPE9EMIolSqXX BNiqIkL2 VuCZ2fydm5nmEMZ6RFjaSEcwq+Ri2gNSKdqPkD3ONLJgHAVYs2LjpCbZ7/LlT8NRfbnqRY5C5iBYyCjbK4zbMxK/dYYQxPu21neSk7J4uGxkh+wIQm9bgRaZZr+aWymrFT8xx42N1/Ich4WOxfGZbJU+NGKNAUUXQccipvCDBwWqjevnntU9NFcATeS+/hV+0FDnTmX8aw2B1kW5h1qFQLtvBsi7HyPpMD4x/bT5cSttOE8fgyCgavWjBnC5+jgV49euncDDfAaCiuDYl/0VxIKRjgpc25IU6CgY3kBSlSbQWnAWtsLFoYwnih9DaOox3F3MVak8RtM8boPcFqqUBb6avuChUfMtlLieYT80x2qSLtIw= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Carlos Maiolino Now the basic infra-structure is in place, enable quota support for tmpfs. This offers user and group quotas to tmpfs (project quotas will be added later). Also, as other filesystems, the tmpfs quota is not supported within user namespaces yet, so idmapping is not translated. Add Christian's suggestion Signed-off-by: Lukas Czerner Signed-off-by: Carlos Maiolino --- Documentation/filesystems/tmpfs.rst | 15 +++ include/linux/shmem_fs.h | 8 ++ mm/shmem.c | 186 ++++++++++++++++++++++++++-- 3 files changed, 201 insertions(+), 8 deletions(-) diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst index f18f46be5c0c..0c7d8bd052f1 100644 --- a/Documentation/filesystems/tmpfs.rst +++ b/Documentation/filesystems/tmpfs.rst @@ -130,6 +130,21 @@ for emergency or testing purposes. The values you can set for shmem_enabled are: option, for testing == ============================================================ +tmpfs also supports quota with the following mount options + +======== ============================================================= +quota User and group quota accounting and enforcement is enabled on + the mount. Tmpfs is using hidden system quota files that are + initialized on mount. +usrquota User quota accounting and enforcement is enabled on the + mount. +grpquota Group quota accounting and enforcement is enabled on the + mount. +======== ============================================================= + +Note that tmpfs quotas do not support user namespaces so no uid/gid +translation is done if quotas are enabled inside user namespaces. + tmpfs has a mount option to set the NUMA memory allocation policy for all files in that instance (if CONFIG_NUMA is enabled) - which can be adjusted on the fly via 'mount -o remount ...' diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 7abfaf70b58a..1a568a0f542f 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -31,6 +31,9 @@ struct shmem_inode_info { atomic_t stop_eviction; /* hold when working on inode */ struct timespec64 i_crtime; /* file creation time */ unsigned int fsflags; /* flags for FS_IOC_[SG]ETFLAGS */ +#ifdef CONFIG_TMPFS_QUOTA + struct dquot *i_dquot[MAXQUOTAS]; +#endif struct inode vfs_inode; }; @@ -184,4 +187,9 @@ extern int shmem_mfill_atomic_pte(pmd_t *dst_pmd, #define SHMEM_QUOTA_MAX_SPC_LIMIT 0x7fffffffffffffffLL /* 2^63-1 */ #define SHMEM_QUOTA_MAX_INO_LIMIT 0x7fffffffffffffffLL +#ifdef CONFIG_TMPFS_QUOTA +extern const struct dquot_operations shmem_quota_operations; +extern struct quota_format_type shmem_quota_format; +#endif /* CONFIG_TMPFS_QUOTA */ + #endif diff --git a/mm/shmem.c b/mm/shmem.c index 2a7b8060b6f4..7c75f30309ff 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -78,6 +78,7 @@ static struct vfsmount *shm_mnt; #include #include #include +#include #include @@ -116,11 +117,13 @@ struct shmem_options { int huge; int seen; bool noswap; + unsigned short quota_types; #define SHMEM_SEEN_BLOCKS 1 #define SHMEM_SEEN_INODES 2 #define SHMEM_SEEN_HUGE 4 #define SHMEM_SEEN_INUMS 8 #define SHMEM_SEEN_NOSWAP 16 +#define SHMEM_SEEN_QUOTA 32 }; #ifdef CONFIG_TMPFS @@ -212,7 +215,16 @@ static inline int shmem_inode_acct_block(struct inode *inode, long pages) if (percpu_counter_compare(&sbinfo->used_blocks, sbinfo->max_blocks - pages) > 0) goto unacct; + + err = dquot_alloc_block_nodirty(inode, pages); + if (err) + goto unacct; + percpu_counter_add(&sbinfo->used_blocks, pages); + } else { + err = dquot_alloc_block_nodirty(inode, pages); + if (err) + goto unacct; } return 0; @@ -227,6 +239,8 @@ static inline void shmem_inode_unacct_blocks(struct inode *inode, long pages) struct shmem_inode_info *info = SHMEM_I(inode); struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + dquot_free_block_nodirty(inode, pages); + if (sbinfo->max_blocks) percpu_counter_sub(&sbinfo->used_blocks, pages); shmem_unacct_blocks(info->flags, pages); @@ -255,6 +269,47 @@ bool vma_is_shmem(struct vm_area_struct *vma) static LIST_HEAD(shmem_swaplist); static DEFINE_MUTEX(shmem_swaplist_mutex); +#ifdef CONFIG_TMPFS_QUOTA + +static int shmem_enable_quotas(struct super_block *sb, + unsigned short quota_types) +{ + int type, err = 0; + + sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE | DQUOT_NOLIST_DIRTY; + for (type = 0; type < SHMEM_MAXQUOTAS; type++) { + if (!(quota_types & (1 << type))) + continue; + err = dquot_load_quota_sb(sb, type, QFMT_SHMEM, + DQUOT_USAGE_ENABLED | + DQUOT_LIMITS_ENABLED); + if (err) + goto out_err; + } + return 0; + +out_err: + pr_warn("tmpfs: failed to enable quota tracking (type=%d, err=%d)\n", + type, err); + for (type--; type >= 0; type--) + dquot_quota_off(sb, type); + return err; +} + +static void shmem_disable_quotas(struct super_block *sb) +{ + int type; + + for (type = 0; type < SHMEM_MAXQUOTAS; type++) + dquot_quota_off(sb, type); +} + +static struct dquot **shmem_get_dquots(struct inode *inode) +{ + return SHMEM_I(inode)->i_dquot; +} +#endif /* CONFIG_TMPFS_QUOTA */ + /* * shmem_reserve_inode() performs bookkeeping to reserve a shmem inode, and * produces a novel ino for the newly allocated inode. @@ -361,7 +416,6 @@ static void shmem_recalc_inode(struct inode *inode) freed = info->alloced - info->swapped - inode->i_mapping->nrpages; if (freed > 0) { info->alloced -= freed; - inode->i_blocks -= freed * BLOCKS_PER_PAGE; shmem_inode_unacct_blocks(inode, freed); } } @@ -379,7 +433,6 @@ bool shmem_charge(struct inode *inode, long pages) spin_lock_irqsave(&info->lock, flags); info->alloced += pages; - inode->i_blocks += pages * BLOCKS_PER_PAGE; shmem_recalc_inode(inode); spin_unlock_irqrestore(&info->lock, flags); @@ -395,7 +448,6 @@ void shmem_uncharge(struct inode *inode, long pages) spin_lock_irqsave(&info->lock, flags); info->alloced -= pages; - inode->i_blocks -= pages * BLOCKS_PER_PAGE; shmem_recalc_inode(inode); spin_unlock_irqrestore(&info->lock, flags); @@ -1141,6 +1193,21 @@ static int shmem_setattr(struct mnt_idmap *idmap, } } + if (is_quota_modification(idmap, inode, attr)) { + error = dquot_initialize(inode); + if (error) + return error; + } + + /* Transfer quota accounting */ + if (i_uid_needs_update(idmap, attr, inode) || + i_gid_needs_update(idmap, attr, inode)) { + error = dquot_transfer(idmap, inode, attr); + + if (error) + return error; + } + setattr_copy(idmap, inode, attr); if (attr->ia_valid & ATTR_MODE) error = posix_acl_chmod(idmap, dentry, inode->i_mode); @@ -1187,6 +1254,10 @@ static void shmem_evict_inode(struct inode *inode) WARN_ON(inode->i_blocks); shmem_free_inode(inode->i_sb); clear_inode(inode); +#ifdef CONFIG_TMPFS_QUOTA + dquot_free_inode(inode); + dquot_drop(inode); +#endif } static int shmem_find_swap_entries(struct address_space *mapping, @@ -1986,7 +2057,6 @@ static int shmem_get_folio_gfp(struct inode *inode, pgoff_t index, spin_lock_irq(&info->lock); info->alloced += folio_nr_pages(folio); - inode->i_blocks += (blkcnt_t)BLOCKS_PER_PAGE << folio_order(folio); shmem_recalc_inode(inode); spin_unlock_irq(&info->lock); alloced = true; @@ -2357,9 +2427,10 @@ static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags) #define shmem_initxattrs NULL #endif -static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block *sb, - struct inode *dir, umode_t mode, dev_t dev, - unsigned long flags) +static struct inode *__shmem_get_inode(struct mnt_idmap *idmap, + struct super_block *sb, + struct inode *dir, umode_t mode, + dev_t dev, unsigned long flags) { struct inode *inode; struct shmem_inode_info *info; @@ -2436,6 +2507,43 @@ static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block return inode; } +#ifdef CONFIG_TMPFS_QUOTA +static struct inode *shmem_get_inode(struct mnt_idmap *idmap, + struct super_block *sb, struct inode *dir, + umode_t mode, dev_t dev, unsigned long flags) +{ + int err; + struct inode *inode; + + inode = __shmem_get_inode(idmap, sb, dir, mode, dev, flags); + if (IS_ERR(inode)) + return inode; + + err = dquot_initialize(inode); + if (err) + goto errout; + + err = dquot_alloc_inode(inode); + if (err) { + dquot_drop(inode); + goto errout; + } + return inode; + +errout: + inode->i_flags |= S_NOQUOTA; + iput(inode); + return ERR_PTR(err); +} +#else +static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap, + struct super_block *sb, struct inode *dir, + umode_t mode, dev_t dev, unsigned long flags) +{ + return __shmem_get_inode(idmap, sb, dir, mode, dev, flags); +} +#endif /* CONFIG_TMPFS_QUOTA */ + #ifdef CONFIG_USERFAULTFD int shmem_mfill_atomic_pte(pmd_t *dst_pmd, struct vm_area_struct *dst_vma, @@ -2538,7 +2646,6 @@ int shmem_mfill_atomic_pte(pmd_t *dst_pmd, spin_lock_irq(&info->lock); info->alloced++; - inode->i_blocks += BLOCKS_PER_PAGE; shmem_recalc_inode(inode); spin_unlock_irq(&info->lock); @@ -3516,6 +3623,7 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size) static const struct inode_operations shmem_short_symlink_operations = { .getattr = shmem_getattr, + .setattr = shmem_setattr, .get_link = simple_get_link, #ifdef CONFIG_TMPFS_XATTR .listxattr = shmem_listxattr, @@ -3524,6 +3632,7 @@ static const struct inode_operations shmem_short_symlink_operations = { static const struct inode_operations shmem_symlink_inode_operations = { .getattr = shmem_getattr, + .setattr = shmem_setattr, .get_link = shmem_get_link, #ifdef CONFIG_TMPFS_XATTR .listxattr = shmem_listxattr, @@ -3623,6 +3732,9 @@ enum shmem_param { Opt_inode32, Opt_inode64, Opt_noswap, + Opt_quota, + Opt_usrquota, + Opt_grpquota, }; static const struct constant_table shmem_param_enums_huge[] = { @@ -3645,6 +3757,11 @@ const struct fs_parameter_spec shmem_fs_parameters[] = { fsparam_flag ("inode32", Opt_inode32), fsparam_flag ("inode64", Opt_inode64), fsparam_flag ("noswap", Opt_noswap), +#ifdef CONFIG_TMPFS_QUOTA + fsparam_flag ("quota", Opt_quota), + fsparam_flag ("usrquota", Opt_usrquota), + fsparam_flag ("grpquota", Opt_grpquota), +#endif {} }; @@ -3736,6 +3853,24 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) ctx->noswap = true; ctx->seen |= SHMEM_SEEN_NOSWAP; break; + case Opt_quota: + if (fc->user_ns != &init_user_ns) + return invalfc(fc, "Quotas in unprivileged tmpfs mounts are unsupported"); + ctx->seen |= SHMEM_SEEN_QUOTA; + ctx->quota_types |= (QTYPE_MASK_USR | QTYPE_MASK_GRP); + break; + case Opt_usrquota: + if (fc->user_ns != &init_user_ns) + return invalfc(fc, "Quotas in unprivileged tmpfs mounts are unsupported"); + ctx->seen |= SHMEM_SEEN_QUOTA; + ctx->quota_types |= QTYPE_MASK_USR; + break; + case Opt_grpquota: + if (fc->user_ns != &init_user_ns) + return invalfc(fc, "Quotas in unprivileged tmpfs mounts are unsupported"); + ctx->seen |= SHMEM_SEEN_QUOTA; + ctx->quota_types |= QTYPE_MASK_GRP; + break; } return 0; @@ -3843,6 +3978,12 @@ static int shmem_reconfigure(struct fs_context *fc) goto out; } + if (ctx->seen & SHMEM_SEEN_QUOTA && + !sb_any_quota_loaded(fc->root->d_sb)) { + err = "Cannot enable quota on remount"; + goto out; + } + if (ctx->seen & SHMEM_SEEN_HUGE) sbinfo->huge = ctx->huge; if (ctx->seen & SHMEM_SEEN_INUMS) @@ -3934,6 +4075,9 @@ static void shmem_put_super(struct super_block *sb) { struct shmem_sb_info *sbinfo = SHMEM_SB(sb); +#ifdef CONFIG_TMPFS_QUOTA + shmem_disable_quotas(sb); +#endif free_percpu(sbinfo->ino_batch); percpu_counter_destroy(&sbinfo->used_blocks); mpol_put(sbinfo->mpol); @@ -4013,6 +4157,17 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) #endif uuid_gen(&sb->s_uuid); +#ifdef CONFIG_TMPFS_QUOTA + if (ctx->seen & SHMEM_SEEN_QUOTA) { + sb->dq_op = &shmem_quota_operations; + sb->s_qcop = &dquot_quotactl_sysfile_ops; + sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; + + if (shmem_enable_quotas(sb, ctx->quota_types)) + goto failed; + } +#endif /* CONFIG_TMPFS_QUOTA */ + inode = shmem_get_inode(&nop_mnt_idmap, sb, NULL, S_IFDIR | sbinfo->mode, 0, VM_NORESERVE); if (IS_ERR(inode)) { @@ -4188,6 +4343,9 @@ static const struct super_operations shmem_ops = { #ifdef CONFIG_TMPFS .statfs = shmem_statfs, .show_options = shmem_show_options, +#endif +#ifdef CONFIG_TMPFS_QUOTA + .get_dquots = shmem_get_dquots, #endif .evict_inode = shmem_evict_inode, .drop_inode = generic_delete_inode, @@ -4254,6 +4412,14 @@ void __init shmem_init(void) shmem_init_inodecache(); +#ifdef CONFIG_TMPFS_QUOTA + error = register_quota_format(&shmem_quota_format); + if (error < 0) { + pr_err("Could not register quota format\n"); + goto out3; + } +#endif + error = register_filesystem(&shmem_fs_type); if (error) { pr_err("Could not register tmpfs\n"); @@ -4278,6 +4444,10 @@ void __init shmem_init(void) out1: unregister_filesystem(&shmem_fs_type); out2: +#ifdef CONFIG_TMPFS_QUOTA + unregister_quota_format(&shmem_quota_format); +out3: +#endif shmem_destroy_inodecache(); shm_mnt = ERR_PTR(error); } From patchwork Mon Jul 17 11:52:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlos Maiolino X-Patchwork-Id: 13315518 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id EE555EB64DC for ; Mon, 17 Jul 2023 11:53:57 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8C0C16B0072; Mon, 17 Jul 2023 07:53:57 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 870EF6B0074; Mon, 17 Jul 2023 07:53:57 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 738A08D0001; Mon, 17 Jul 2023 07:53:57 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 666236B0072 for ; Mon, 17 Jul 2023 07:53:57 -0400 (EDT) Received: from smtpin23.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 23761804E2 for ; Mon, 17 Jul 2023 11:53:57 +0000 (UTC) X-FDA: 81020944914.23.7AC7B4F Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf19.hostedemail.com (Postfix) with ESMTP id 3C37F1A001B for ; Mon, 17 Jul 2023 11:53:55 +0000 (UTC) Authentication-Results: imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="ExsELo/V"; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf19.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689594835; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=IV0Etlq55XfvNKloTO9/wGyBWhvZhBZRx2TjzNbCC4A=; b=x1833AhRHn1FbeM1k5YKmRFWAwDwabw11ZyNzXFkzmxYpLx5Lj+F5t4S19EOqVU2bsfsVH nDCTtDIKJLeScvSNN1c0vdNvG/NkzOaDIZs5k96Bv8WCuPKka5TUkWDAMfnactzgOIM313 QKYfzGS3NsFWDrMR91GHCi1g3S5PHWA= ARC-Authentication-Results: i=1; imf19.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="ExsELo/V"; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf19.hostedemail.com: domain of cem@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cem@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689594835; a=rsa-sha256; cv=none; b=g9DiZhwdBELVXJQdgyd3PQ7BSHxIMD4PQHtQJH8BMrXpOKGBYDU+Awi7lsxCMZmblM7xkS tk6bFSJWPsfRq9uCRloevrZvv8PbvffZQdGLJUc9w1LgMMNcZXucj6KZP0NjOrhf6n4qCM 35UhUx3/qJBwLXibh0FaFEADEdOiLls= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 71BDD61042; Mon, 17 Jul 2023 11:53:54 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 398D7C433C8; Mon, 17 Jul 2023 11:53:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1689594833; bh=/N8t0zn5r7/pIKRWGGNTxKX3iFdVKBgXPuSClztgPDA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ExsELo/VzdyI0l+5mEzyQHALjofX9VCkyI92vl7b6M3x0pgMCzy6M2r6aVSGxBW9L i/KfrKemwznCNcmq18LfhibbbWIIgwA4a5Ah9mcg8Ze60b4JxhTmwFhdAF5faKDOuI 7QEmsZhVRVeQEibSBXrD70pDhnq7Spbhy3pc8Mdbg2UOA9WHPYugt/bamh5fXGcl3r LyaMpopyuP5J7ibY2NB5sWNEkdGmLT4cNPgEf3y89LBYMxuXNh3dFGzUAyg+TTOCVT IGFyf+aMOz6A5VJQ48kmsxPt1uEtUvk1gMRqmnpbMof+JcqHiT9Pn78AZYl0oDB9db ULF3docgPeL9Q== From: cem@kernel.org To: linux-fsdevel@vger.kernel.org Cc: jack@suse.cz, akpm@linux-foundation.org, viro@zeniv.linux.org.uk, linux-mm@kvack.org, djwong@kernel.org, hughd@google.com, brauner@kernel.org, mcgrof@kernel.org Subject: [PATCH 6/6] Add default quota limit mount options Date: Mon, 17 Jul 2023 13:52:19 +0200 Message-Id: <20230717115212.208651-7-cem@kernel.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230717115212.208651-1-cem@kernel.org> References: <20230717115212.208651-1-cem@kernel.org> MIME-Version: 1.0 X-Rspamd-Queue-Id: 3C37F1A001B X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: qhejca9zzaiw93ycoxbcikycpmucmi1q X-HE-Tag: 1689594834-780995 X-HE-Meta: U2FsdGVkX1+7ix1WStWpd9lrbiZrxJD+ACyGICCjOsgndUuqmNlmGdZkgL6r8OL9mgFVgwA5/+1zmVA+cUNPjD9U45krhghvlgoyTMjBkLYvo8FLG1qcP2GjPqIQg2Ttw9TNTFK6oC1Seh3w1RHk0maI70dGgOQMJVyxGYa5c4p6hkgzRd5yLFIQGQUY58xc6J6Pwt3o33WTDIW/WYe+QflqA1h7f5DiKtu36yMz8oQ/AFMA5Kpee14xn4seW7/7+dhJWiSmu21V3m2E/MvWyCWUIvPODbQCg6eO7TnVKiSoISf801jsz6oPHoES7KMEzPRHhBQ8+TCTN484AlAiAiU78ZE62+QiMskFGz2GVdcWPSzkbX+IrIKpYCPTF9qDpY99QD68sx+nt+4VlafYUwmmd6ntFs3UxoTUrQ9+ugvMr5ywdkNBx0TSF8WcnE3J+LwC5i1CO1K6Ay6nIKB9Jgq58MG5Bg6XSD/UUpJOkCbc3O5LaDJFAn5TUrR/Pc348BPUORT94QfpgEd/Cd1FEmh4Gj/SxfDvU/SbBvOrQl2JilYYc3IjkNnxKFKClAMMD8MaaJk2LUFt0Gb5Hr247LlryQfBZ6Be7RpLoWWSsmmInPg/VLBdcyXsv28jYzmZFsv1qjj3BhazIOzMvhcrmRBwiVbV/XXF+aHadypxRMkPiTgBfETMaBEZrnWFXkDRqmkUnqijvViMzNiTpuHAr4qHwdmoIY2JozbIolXbtt4KiorS9OpkEom+I3QoYzXtKanOU/u4HtqqmmAt6T5+cqag7GR07EeFibEBQ4TSYxkwz3RjAKG+rsUfy3vkCZyssRNXqz0J7TVJLVG5FjJ8JC3Zsy8ptdjRQ/BCHZp/A6mbbk1O2y8zjzYlbt0lVLLbKRqgCNLGHAHBxQq1PcawpjyqcqeSlXPwaJi7uK9n3Rdhs7iP6HgvhvwyyAKwhRbwPUYWAkyZi7mWaGP6vpv PQqSPHaB 5cI2PxUC8YviHpnDnc7Ws82Y+6q6jqzJbffY5siEKNiUvnfgsdFx+Rj8xNdH+kf1xWoueDBzM7patLlYBeA5qV6wGd5IdOwhE6UpGXGtDKbKnVaYRlIsm7P6JlYZruhts4c98GhMUjcA9u4+z9ffXrLDj2iD3pE4C1R/oGs2ZAkzJUfxCJ7d0ja8p815zSByrMNrrPvE2aMjDxwaB5POm2dxit89L3RwafNVb925P/huWx97YMgLF1TNX3dEA5vGDio08b750HSbtVd9feezXXlJ8zKLsJDiIUd7Dmaqek+NiPhI= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Lukas Czerner Allow system administrator to set default global quota limits at tmpfs mount time. Signed-off-by: Lukas Czerner Signed-off-by: Carlos Maiolino Reviewed-by: Jan Kara --- Documentation/filesystems/tmpfs.rst | 34 +++++++++++----- include/linux/shmem_fs.h | 8 ++++ mm/shmem.c | 61 +++++++++++++++++++++++++++++ mm/shmem_quota.c | 34 +++++++++++++++- 4 files changed, 127 insertions(+), 10 deletions(-) diff --git a/Documentation/filesystems/tmpfs.rst b/Documentation/filesystems/tmpfs.rst index 0c7d8bd052f1..f843dbbeb589 100644 --- a/Documentation/filesystems/tmpfs.rst +++ b/Documentation/filesystems/tmpfs.rst @@ -132,15 +132,31 @@ for emergency or testing purposes. The values you can set for shmem_enabled are: tmpfs also supports quota with the following mount options -======== ============================================================= -quota User and group quota accounting and enforcement is enabled on - the mount. Tmpfs is using hidden system quota files that are - initialized on mount. -usrquota User quota accounting and enforcement is enabled on the - mount. -grpquota Group quota accounting and enforcement is enabled on the - mount. -======== ============================================================= +======================== ================================================= +quota User and group quota accounting and enforcement + is enabled on the mount. Tmpfs is using hidden + system quota files that are initialized on mount. +usrquota User quota accounting and enforcement is enabled + on the mount. +grpquota Group quota accounting and enforcement is enabled + on the mount. +usrquota_block_hardlimit Set global user quota block hard limit. +usrquota_inode_hardlimit Set global user quota inode hard limit. +grpquota_block_hardlimit Set global group quota block hard limit. +grpquota_inode_hardlimit Set global group quota inode hard limit. +======================== ================================================= + +None of the quota related mount options can be set or changed on remount. + +Quota limit parameters accept a suffix k, m or g for kilo, mega and giga +and can't be changed on remount. Default global quota limits are taking +effect for any and all user/group/project except root the first time the +quota entry for user/group/project id is being accessed - typically the +first time an inode with a particular id ownership is being created after +the mount. In other words, instead of the limits being initialized to zero, +they are initialized with the particular value provided with these mount +options. The limits can be changed for any user/group id at any time as they +normally can be. Note that tmpfs quotas do not support user namespaces so no uid/gid translation is done if quotas are enabled inside user namespaces. diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 1a568a0f542f..c0058f3bba70 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -42,6 +42,13 @@ struct shmem_inode_info { (FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL) #define SHMEM_FL_INHERITED (FS_NODUMP_FL | FS_NOATIME_FL) +struct shmem_quota_limits { + qsize_t usrquota_bhardlimit; /* Default user quota block hard limit */ + qsize_t usrquota_ihardlimit; /* Default user quota inode hard limit */ + qsize_t grpquota_bhardlimit; /* Default group quota block hard limit */ + qsize_t grpquota_ihardlimit; /* Default group quota inode hard limit */ +}; + struct shmem_sb_info { unsigned long max_blocks; /* How many blocks are allowed */ struct percpu_counter used_blocks; /* How many are allocated */ @@ -60,6 +67,7 @@ struct shmem_sb_info { spinlock_t shrinklist_lock; /* Protects shrinklist */ struct list_head shrinklist; /* List of shinkable inodes */ unsigned long shrinklist_len; /* Length of shrinklist */ + struct shmem_quota_limits qlimits; /* Default quota limits */ }; static inline struct shmem_inode_info *SHMEM_I(struct inode *inode) diff --git a/mm/shmem.c b/mm/shmem.c index 7c75f30309ff..bd02909bacd6 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -118,6 +118,7 @@ struct shmem_options { int seen; bool noswap; unsigned short quota_types; + struct shmem_quota_limits qlimits; #define SHMEM_SEEN_BLOCKS 1 #define SHMEM_SEEN_INODES 2 #define SHMEM_SEEN_HUGE 4 @@ -3735,6 +3736,10 @@ enum shmem_param { Opt_quota, Opt_usrquota, Opt_grpquota, + Opt_usrquota_block_hardlimit, + Opt_usrquota_inode_hardlimit, + Opt_grpquota_block_hardlimit, + Opt_grpquota_inode_hardlimit, }; static const struct constant_table shmem_param_enums_huge[] = { @@ -3761,6 +3766,10 @@ const struct fs_parameter_spec shmem_fs_parameters[] = { fsparam_flag ("quota", Opt_quota), fsparam_flag ("usrquota", Opt_usrquota), fsparam_flag ("grpquota", Opt_grpquota), + fsparam_string("usrquota_block_hardlimit", Opt_usrquota_block_hardlimit), + fsparam_string("usrquota_inode_hardlimit", Opt_usrquota_inode_hardlimit), + fsparam_string("grpquota_block_hardlimit", Opt_grpquota_block_hardlimit), + fsparam_string("grpquota_inode_hardlimit", Opt_grpquota_inode_hardlimit), #endif {} }; @@ -3871,6 +3880,42 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) ctx->seen |= SHMEM_SEEN_QUOTA; ctx->quota_types |= QTYPE_MASK_GRP; break; + case Opt_usrquota_block_hardlimit: + size = memparse(param->string, &rest); + if (*rest || !size) + goto bad_value; + if (size > SHMEM_QUOTA_MAX_SPC_LIMIT) + return invalfc(fc, + "User quota block hardlimit too large."); + ctx->qlimits.usrquota_bhardlimit = size; + break; + case Opt_grpquota_block_hardlimit: + size = memparse(param->string, &rest); + if (*rest || !size) + goto bad_value; + if (size > SHMEM_QUOTA_MAX_SPC_LIMIT) + return invalfc(fc, + "Group quota block hardlimit too large."); + ctx->qlimits.grpquota_bhardlimit = size; + break; + case Opt_usrquota_inode_hardlimit: + size = memparse(param->string, &rest); + if (*rest || !size) + goto bad_value; + if (size > SHMEM_QUOTA_MAX_INO_LIMIT) + return invalfc(fc, + "User quota inode hardlimit too large."); + ctx->qlimits.usrquota_ihardlimit = size; + break; + case Opt_grpquota_inode_hardlimit: + size = memparse(param->string, &rest); + if (*rest || !size) + goto bad_value; + if (size > SHMEM_QUOTA_MAX_INO_LIMIT) + return invalfc(fc, + "Group quota inode hardlimit too large."); + ctx->qlimits.grpquota_ihardlimit = size; + break; } return 0; @@ -3984,6 +4029,18 @@ static int shmem_reconfigure(struct fs_context *fc) goto out; } +#ifdef CONFIG_TMPFS_QUOTA +#define CHANGED_LIMIT(name) \ + (ctx->qlimits.name## hardlimit && \ + (ctx->qlimits.name## hardlimit != sbinfo->qlimits.name## hardlimit)) + + if (CHANGED_LIMIT(usrquota_b) || CHANGED_LIMIT(usrquota_i) || + CHANGED_LIMIT(grpquota_b) || CHANGED_LIMIT(grpquota_i)) { + err = "Cannot change global quota limit on remount"; + goto out; + } +#endif /* CONFIG_TMPFS_QUOTA */ + if (ctx->seen & SHMEM_SEEN_HUGE) sbinfo->huge = ctx->huge; if (ctx->seen & SHMEM_SEEN_INUMS) @@ -4163,6 +4220,10 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_qcop = &dquot_quotactl_sysfile_ops; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; + /* Copy the default limits from ctx into sbinfo */ + memcpy(&sbinfo->qlimits, &ctx->qlimits, + sizeof(struct shmem_quota_limits)); + if (shmem_enable_quotas(sb, ctx->quota_types)) goto failed; } diff --git a/mm/shmem_quota.c b/mm/shmem_quota.c index c0b531e2ef68..e349c0901bce 100644 --- a/mm/shmem_quota.c +++ b/mm/shmem_quota.c @@ -166,6 +166,7 @@ static int shmem_acquire_dquot(struct dquot *dquot) { struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node; + struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info; struct rb_node *parent = NULL, *new_node = NULL; struct quota_id *new_entry, *entry; qid_t id = from_kqid(&init_user_ns, dquot->dq_id); @@ -195,6 +196,14 @@ static int shmem_acquire_dquot(struct dquot *dquot) } new_entry->id = id; + if (dquot->dq_id.type == USRQUOTA) { + new_entry->bhardlimit = sbinfo->qlimits.usrquota_bhardlimit; + new_entry->ihardlimit = sbinfo->qlimits.usrquota_ihardlimit; + } else if (dquot->dq_id.type == GRPQUOTA) { + new_entry->bhardlimit = sbinfo->qlimits.grpquota_bhardlimit; + new_entry->ihardlimit = sbinfo->qlimits.grpquota_ihardlimit; + } + new_node = &new_entry->node; rb_link_node(new_node, parent, n); rb_insert_color(new_node, (struct rb_root *)info->dqi_priv); @@ -224,6 +233,29 @@ static int shmem_acquire_dquot(struct dquot *dquot) return ret; } +static bool shmem_is_empty_dquot(struct dquot *dquot) +{ + struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info; + qsize_t bhardlimit; + qsize_t ihardlimit; + + if (dquot->dq_id.type == USRQUOTA) { + bhardlimit = sbinfo->qlimits.usrquota_bhardlimit; + ihardlimit = sbinfo->qlimits.usrquota_ihardlimit; + } else if (dquot->dq_id.type == GRPQUOTA) { + bhardlimit = sbinfo->qlimits.grpquota_bhardlimit; + ihardlimit = sbinfo->qlimits.grpquota_ihardlimit; + } + + if (test_bit(DQ_FAKE_B, &dquot->dq_flags) || + (dquot->dq_dqb.dqb_curspace == 0 && + dquot->dq_dqb.dqb_curinodes == 0 && + dquot->dq_dqb.dqb_bhardlimit == bhardlimit && + dquot->dq_dqb.dqb_ihardlimit == ihardlimit)) + return true; + + return false; +} /* * Store limits from dquot in the tree unless it's fake. If it is fake * remove the id from the tree since there is no useful information in @@ -261,7 +293,7 @@ static int shmem_release_dquot(struct dquot *dquot) return -ENOENT; found: - if (test_bit(DQ_FAKE_B, &dquot->dq_flags)) { + if (shmem_is_empty_dquot(dquot)) { /* Remove entry from the tree */ rb_erase(&entry->node, info->dqi_priv); kfree(entry);