From patchwork Sat Dec 7 00:18:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898144 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5351C2563 for ; Sat, 7 Dec 2024 00:18:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530696; cv=none; b=DTAvnHsrgfsdih0GJgS7jRvq8j4kwxQJ/8M/hvnbTo0W2SzhlrMisXKxAuWKYtttrlxiJ2rwSkaEWr3aMpXGfz8n3hQT9X91+2FxEzKffDgFm0SyKx0W2evXeJ94tPV1pMzunHpN1lIrAHKOcuOknLTym5fTf2aZIQ/GN4Kn+MY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530696; c=relaxed/simple; bh=7coKNW/H5VSgE6DB3Kw3Vpuio22A5n8yJOtX8lt5fXg=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KFSTSu9vtE84atgc6EkXcKh9yMkINgbhVzl2s1UJmooonMFs85KtflB8GTnG3xsHUp6iT82gHt0R40pIsWAwmCua8tdX66TAVuGKi1U2Av0U7kJkW/NDt9bjxBlXcxB4et5TUFm/F0GBY9xA6f3Fi4ZaovHM7zI1nh6EZuujoow= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UniMToEW; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="UniMToEW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4F92C4CED1; Sat, 7 Dec 2024 00:18:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530695; bh=7coKNW/H5VSgE6DB3Kw3Vpuio22A5n8yJOtX8lt5fXg=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=UniMToEWLkdvTtBCwj04aQMacdsiVdepH0KVYPKeqMTiH/GNsmRBmGvvpXMttiI6U 3fAMOzeEzn/fzzYrOiOrvlANKDZ8ATiZdaNBJJQt4ADXesdWWf607u5sMctWW7ivNp ezdA4hxh2i0NwxtGu0kgIdca3CkSKM33+FweXj0GrE7yfsPJ1rifhX0EOR5ncw5TP9 quaVvpc00P8iJ0Y1OevDaX5vAR7cACYm/yRNTNyGZ9uoNeeRWC3CiJD6ycOgcU7phD ZC6DPy7H+YcRnIGBf8n/dmhdimIMnAW0RsHP87dQWQwBCerhMVXmm63V5lMtHL7oSv jqulNjVQ92b+Q== Date: Fri, 06 Dec 2024 16:18:15 -0800 Subject: [PATCH 1/7] libfrog: scrub quota file metapaths From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753248.129683.11231628303317171036.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Support scrubbing quota file metadir paths. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- libfrog/scrub.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libfrog/scrub.c b/libfrog/scrub.c index d40364d35ce0b4..129f592e108ae1 100644 --- a/libfrog/scrub.c +++ b/libfrog/scrub.c @@ -187,6 +187,26 @@ const struct xfrog_scrub_descr xfrog_metapaths[XFS_SCRUB_METAPATH_NR] = { .descr = "rtgroup summary", .group = XFROG_SCRUB_GROUP_RTGROUP, }, + [XFS_SCRUB_METAPATH_QUOTADIR] = { + .name = "quotadir", + .descr = "quota file metadir", + .group = XFROG_SCRUB_GROUP_FS, + }, + [XFS_SCRUB_METAPATH_USRQUOTA] = { + .name = "usrquota", + .descr = "user quota file", + .group = XFROG_SCRUB_GROUP_FS, + }, + [XFS_SCRUB_METAPATH_GRPQUOTA] = { + .name = "grpquota", + .descr = "group quota file", + .group = XFROG_SCRUB_GROUP_FS, + }, + [XFS_SCRUB_METAPATH_PRJQUOTA] = { + .name = "prjquota", + .descr = "project quota file", + .group = XFROG_SCRUB_GROUP_FS, + }, }; /* Invoke the scrub ioctl. Returns zero or negative error code. */ From patchwork Sat Dec 7 00:18:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898145 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 94C39322B for ; Sat, 7 Dec 2024 00:18:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530711; cv=none; b=YSQTLap0bFctzDUpRCM+uTNYWUbcY5KH6QBnEbJV0CSjQnIDRmDlfd0DRcd/m5nmrZSgLOoARyRmeHpXpAn3eL+482l0g5iiuUCDKrg4Qnt6pkdiTIxc6F6x3S++2877lz9E/OLkPCC9RiwJpnjDFlDxxOBoRZLH2n5GlpNcqWI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530711; c=relaxed/simple; bh=1beFTftpmrIjss6bEdJKbzPjsNQSLYDlUWl3Qt5db5k=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=iT1Up7eNaSWAnr10j26BrtNz9WSDmHHBrFAGz5MYg1NneCdsmBhSh1akt+psPGmIiUEecGiznibcw69GG3XmPqULNAYUVxmK4XV3TS0Vu9B6yJjDhKw0Xmwv/u9Or1ilwja4Fd2aALcsAmacTc7lnrHj1R8JWNLcj0IiTPwYe6Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NplBBSO5; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NplBBSO5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6ABD1C4CED1; Sat, 7 Dec 2024 00:18:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530711; bh=1beFTftpmrIjss6bEdJKbzPjsNQSLYDlUWl3Qt5db5k=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=NplBBSO5qA374xVaFMykJ2CEbXChQttEfoM3My3YQEs3Un9RxmFeuhnrRAnpfu2Zo coNrq/ZBRzqImOeBcYJ2pgUblKjrqxxOEkbhRxuUYhkDa0cgWxqRF+OPPaCNJehsVj UKx5ZFuYilV4ZFxmWgxUTPa+FBFp28yXxfoXaLyy8hx4cTeG//Psg21BUKKor4+Oi+ RqNM+fWcZ/mah9xZ2GRJzcqkOaCCbpBPd5UC/ie+o2ETD2DXjhKlUpl6C+zCClc8xw dtMyYnREPv+SUS+1X32OsxFzmvF7pXTOWD+oKC8Ca7xqocOGKVA5TdrU4nHzVD673l wJYMG4FAjH2vA== Date: Fri, 06 Dec 2024 16:18:30 -0800 Subject: [PATCH 2/7] xfs_db: support metadir quotas From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753263.129683.13463573262283190371.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Support finding the quota files in the metadata directory. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- db/dquot.c | 59 ++++++++++++++++++++++++++++++++++------------ libxfs/libxfs_api_defs.h | 6 +++++ 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/db/dquot.c b/db/dquot.c index 338d064995155e..d2c76fd70bf1a6 100644 --- a/db/dquot.c +++ b/db/dquot.c @@ -81,6 +81,41 @@ dquot_help(void) { } +static xfs_ino_t +dqtype_to_inode( + struct xfs_mount *mp, + xfs_dqtype_t type) +{ + struct xfs_trans *tp; + struct xfs_inode *dp = NULL; + struct xfs_inode *ip; + xfs_ino_t ret = NULLFSINO; + int error; + + error = -libxfs_trans_alloc_empty(mp, &tp); + if (error) + return NULLFSINO; + + if (xfs_has_metadir(mp)) { + error = -libxfs_dqinode_load_parent(tp, &dp); + if (error) + goto out_cancel; + } + + error = -libxfs_dqinode_load(tp, dp, type, &ip); + if (error) + goto out_dp; + + ret = ip->i_ino; + libxfs_irele(ip); +out_dp: + if (dp) + libxfs_irele(dp); +out_cancel: + libxfs_trans_cancel(tp); + return ret; +} + static int dquot_f( int argc, @@ -88,8 +123,7 @@ dquot_f( { bmap_ext_t bm; int c; - int dogrp; - int doprj; + xfs_dqtype_t type = XFS_DQTYPE_USER; xfs_dqid_t id; xfs_ino_t ino; xfs_extnum_t nex; @@ -97,38 +131,33 @@ dquot_f( int perblock; xfs_fileoff_t qbno; int qoff; - char *s; + const char *s; - dogrp = doprj = optind = 0; + optind = 0; while ((c = getopt(argc, argv, "gpu")) != EOF) { switch (c) { case 'g': - dogrp = 1; - doprj = 0; + type = XFS_DQTYPE_GROUP; break; case 'p': - doprj = 1; - dogrp = 0; + type = XFS_DQTYPE_PROJ; break; case 'u': - dogrp = doprj = 0; + type = XFS_DQTYPE_USER; break; default: dbprintf(_("bad option for dquot command\n")); return 0; } } - s = doprj ? _("project") : dogrp ? _("group") : _("user"); + + s = libxfs_dqinode_path(type); if (optind != argc - 1) { dbprintf(_("dquot command requires one %s id argument\n"), s); return 0; } - ino = mp->m_sb.sb_uquotino; - if (doprj) - ino = mp->m_sb.sb_pquotino; - else if (dogrp) - ino = mp->m_sb.sb_gquotino; + ino = dqtype_to_inode(mp, type); if (ino == 0 || ino == NULLFSINO) { dbprintf(_("no %s quota inode present\n"), s); return 0; diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index a8416dfbb27f59..6b2dc7a30d2547 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -159,6 +159,12 @@ #define xfs_dir_replace libxfs_dir_replace #define xfs_dqblk_repair libxfs_dqblk_repair +#define xfs_dqinode_load libxfs_dqinode_load +#define xfs_dqinode_load_parent libxfs_dqinode_load_parent +#define xfs_dqinode_mkdir_parent libxfs_dqinode_mkdir_parent +#define xfs_dqinode_metadir_create libxfs_dqinode_metadir_create +#define xfs_dqinode_metadir_link libxfs_dqinode_metadir_link +#define xfs_dqinode_path libxfs_dqinode_path #define xfs_dquot_from_disk_ts libxfs_dquot_from_disk_ts #define xfs_dquot_verify libxfs_dquot_verify From patchwork Sat Dec 7 00:18:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898146 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C7F13FF1 for ; Sat, 7 Dec 2024 00:18:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530727; cv=none; b=We5BOmxuAnYW7QXaBgU1We2JFcXaea7WkI9X/OoUFgjzU/zMsaF17I29rFOAjMXOxgtsntKSdJKHa3rgXTMprlfalYrcNU3SycwAEWEmHOZFYoLWqEHHFbarvLj1+HMOFmfP1AgFSMTrzeUQqo1TqcDzinLvy+nPNP7gVyJAP2k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530727; c=relaxed/simple; bh=JCLAzqjET3qlZEtGhGHIiSrsU/pTRxERdQO/3VhrKuo=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VwOa5s+J60hIY/QlJGUWuDIZ35CqHLNymHXNhC0qQz919aicus5G32elw2GM0jS9A0DIaaOWNm7hqjWws7d+J1BRNWdPRLCyoX+9rNXbY4oCx55PkVyWky6uVbj4MShuXspgFASY3dTcaKGDuuZHZuxGWaxxm4rvo83zsYRmTjI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Kr7wcANy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Kr7wcANy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1222CC4CED1; Sat, 7 Dec 2024 00:18:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530727; bh=JCLAzqjET3qlZEtGhGHIiSrsU/pTRxERdQO/3VhrKuo=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Kr7wcANyjN5e1sHwKHJuioygqw80Q0e6ABT/XzhgAZAbKkpXXUmKFX21To3F1Qydu 6nFchQOJeZKoV7BoQ9oayQEqbn62HtZPyu+dkZZoylaQKYvHI/VpQSknziL2YPptth I2MntnAlaHjeCUfdPMju0vtRpw4n8lwF/Jz8ts0mywpMsK8tMsxCAPNbV6ytfKLqRl IHcTxqGNxUMzGC8xOWfgGDtHOB6MDI8r5kV07fNAcbAz0NZmglOHwgDgneFbXhl/lp ZbeylVcsrfE29CZq4Ime/qPhkCQjhZJ7qsr3U6dj1SH56eofrtwPni32M9SbEFWEBs JLk7rJYW/UKgw== Date: Fri, 06 Dec 2024 16:18:46 -0800 Subject: [PATCH 3/7] xfs_repair: refactor quota inumber handling From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753279.129683.18254140495168515228.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong In preparation for putting quota files in the metadata directory tree, refactor repair's quota inumber handling to use its own variables instead of the xfs_mount's. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/dinode.c | 18 ++++---- repair/dir2.c | 12 +++--- repair/globals.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++--- repair/globals.h | 15 ++++--- repair/phase4.c | 96 ++++++++++++++++++-------------------------- repair/phase6.c | 12 +++--- repair/quotacheck.c | 47 +++++++++++++++------- repair/quotacheck.h | 2 + repair/versions.c | 9 +--- repair/xfs_repair.c | 12 ++++-- 10 files changed, 221 insertions(+), 113 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index 2d341975e53993..9ab193bc5fe973 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -1662,29 +1662,29 @@ process_check_metadata_inodes( } return 0; } - if (lino == mp->m_sb.sb_uquotino) { + if (is_quota_inode(XFS_DQTYPE_USER, lino)) { if (*type != XR_INO_UQUOTA) { do_warn(_("user quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); - mp->m_sb.sb_uquotino = NULLFSINO; + clear_quota_inode(XFS_DQTYPE_USER); return 1; } return 0; } - if (lino == mp->m_sb.sb_gquotino) { + if (is_quota_inode(XFS_DQTYPE_GROUP, lino)) { if (*type != XR_INO_GQUOTA) { do_warn(_("group quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); - mp->m_sb.sb_gquotino = NULLFSINO; + clear_quota_inode(XFS_DQTYPE_GROUP); return 1; } return 0; } - if (lino == mp->m_sb.sb_pquotino) { + if (is_quota_inode(XFS_DQTYPE_PROJ, lino)) { if (*type != XR_INO_PQUOTA) { do_warn(_("project quota inode %" PRIu64 " has bad type 0x%x\n"), lino, dinode_fmt(dinoc)); - mp->m_sb.sb_pquotino = NULLFSINO; + clear_quota_inode(XFS_DQTYPE_PROJ); return 1; } return 0; @@ -2980,11 +2980,11 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), else if (lino == mp->m_sb.sb_rsumino || is_rtsummary_inode(lino)) type = XR_INO_RTSUM; - else if (lino == mp->m_sb.sb_uquotino) + else if (is_quota_inode(XFS_DQTYPE_USER, lino)) type = XR_INO_UQUOTA; - else if (lino == mp->m_sb.sb_gquotino) + else if (is_quota_inode(XFS_DQTYPE_GROUP, lino)) type = XR_INO_GQUOTA; - else if (lino == mp->m_sb.sb_pquotino) + else if (is_quota_inode(XFS_DQTYPE_PROJ, lino)) type = XR_INO_PQUOTA; else type = XR_INO_DATA; diff --git a/repair/dir2.c b/repair/dir2.c index ca747c90175e93..ed615662009957 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -265,13 +265,13 @@ process_sf_dir2( is_rtsummary_inode(lino)) { junkit = 1; junkreason = _("realtime summary"); - } else if (lino == mp->m_sb.sb_uquotino) { + } else if (is_quota_inode(XFS_DQTYPE_USER, lino)) { junkit = 1; junkreason = _("user quota"); - } else if (lino == mp->m_sb.sb_gquotino) { + } else if (is_quota_inode(XFS_DQTYPE_GROUP, lino)) { junkit = 1; junkreason = _("group quota"); - } else if (lino == mp->m_sb.sb_pquotino) { + } else if (is_quota_inode(XFS_DQTYPE_PROJ, lino)) { junkit = 1; junkreason = _("project quota"); } else if (lino == mp->m_sb.sb_metadirino) { @@ -746,11 +746,11 @@ process_dir2_data( } else if (ent_ino == mp->m_sb.sb_rsumino || is_rtsummary_inode(ent_ino)) { clearreason = _("realtime summary"); - } else if (ent_ino == mp->m_sb.sb_uquotino) { + } else if (is_quota_inode(XFS_DQTYPE_USER, ent_ino)) { clearreason = _("user quota"); - } else if (ent_ino == mp->m_sb.sb_gquotino) { + } else if (is_quota_inode(XFS_DQTYPE_GROUP, ent_ino)) { clearreason = _("group quota"); - } else if (ent_ino == mp->m_sb.sb_pquotino) { + } else if (is_quota_inode(XFS_DQTYPE_PROJ, ent_ino)) { clearreason = _("project quota"); } else if (ent_ino == mp->m_sb.sb_metadirino) { clearreason = _("metadata directory root"); diff --git a/repair/globals.c b/repair/globals.c index 30995f5298d5a1..99291d6afd61b9 100644 --- a/repair/globals.c +++ b/repair/globals.c @@ -73,12 +73,6 @@ int need_rbmino; int need_rsumino; int lost_quotas; -int have_uquotino; -int have_gquotino; -int have_pquotino; -int lost_uquotino; -int lost_gquotino; -int lost_pquotino; /* configuration vars -- fs geometry dependent */ @@ -119,3 +113,108 @@ int thread_count; /* If nonzero, simulate failure after this phase. */ int fail_after_phase; + +/* quota inode numbers */ +enum quotino_state { + QI_STATE_UNKNOWN, + QI_STATE_HAVE, + QI_STATE_LOST, +}; + +static xfs_ino_t quotinos[3] = { NULLFSINO, NULLFSINO, NULLFSINO }; +static enum quotino_state quotino_state[3]; + +static inline unsigned int quotino_off(xfs_dqtype_t type) +{ + switch (type) { + case XFS_DQTYPE_USER: + return 0; + case XFS_DQTYPE_GROUP: + return 1; + case XFS_DQTYPE_PROJ: + return 2; + } + + ASSERT(0); + return -1; +} + +void +set_quota_inode( + xfs_dqtype_t type, + xfs_ino_t ino) +{ + unsigned int off = quotino_off(type); + + quotinos[off] = ino; + quotino_state[off] = QI_STATE_HAVE; +} + +void +lose_quota_inode( + xfs_dqtype_t type) +{ + unsigned int off = quotino_off(type); + + quotinos[off] = NULLFSINO; + quotino_state[off] = QI_STATE_LOST; +} + +void +clear_quota_inode( + xfs_dqtype_t type) +{ + unsigned int off = quotino_off(type); + + quotinos[off] = NULLFSINO; + quotino_state[off] = QI_STATE_UNKNOWN; +} + +xfs_ino_t +get_quota_inode( + xfs_dqtype_t type) +{ + unsigned int off = quotino_off(type); + + return quotinos[off]; +} + +bool +is_quota_inode( + xfs_dqtype_t type, + xfs_ino_t ino) +{ + unsigned int off = quotino_off(type); + + return quotinos[off] == ino; +} + +bool +is_any_quota_inode( + xfs_ino_t ino) +{ + unsigned int i; + + for(i = 0; i < ARRAY_SIZE(quotinos); i++) + if (quotinos[i] == ino) + return true; + return false; +} + +bool +lost_quota_inode( + xfs_dqtype_t type) +{ + unsigned int off = quotino_off(type); + + return quotino_state[off] == QI_STATE_LOST; +} + +bool +has_quota_inode( + xfs_dqtype_t type) +{ + unsigned int off = quotino_off(type); + + return quotino_state[off] == QI_STATE_HAVE; +} diff --git a/repair/globals.h b/repair/globals.h index 7c2d9c56c8f8a7..b23a06af6cc81b 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -114,12 +114,6 @@ extern int need_rbmino; extern int need_rsumino; extern int lost_quotas; -extern int have_uquotino; -extern int have_gquotino; -extern int have_pquotino; -extern int lost_uquotino; -extern int lost_gquotino; -extern int lost_pquotino; /* configuration vars -- fs geometry dependent */ @@ -165,4 +159,13 @@ extern int fail_after_phase; extern struct libxfs_init x; +void set_quota_inode(xfs_dqtype_t type, xfs_ino_t); +void lose_quota_inode(xfs_dqtype_t type); +void clear_quota_inode(xfs_dqtype_t type); +xfs_ino_t get_quota_inode(xfs_dqtype_t type); +bool is_quota_inode(xfs_dqtype_t type, xfs_ino_t ino); +bool is_any_quota_inode(xfs_ino_t ino); +bool lost_quota_inode(xfs_dqtype_t type); +bool has_quota_inode(xfs_dqtype_t type); + #endif /* _XFS_REPAIR_GLOBAL_H */ diff --git a/repair/phase4.c b/repair/phase4.c index f43f8ecd84e25b..a4183c557a1891 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -23,6 +23,35 @@ bool collect_rmaps; +static inline void +quotino_check_one( + struct xfs_mount *mp, + xfs_dqtype_t type) +{ + struct ino_tree_node *irec; + xfs_ino_t ino; + + if (!has_quota_inode(type)) + return; + + ino = get_quota_inode(type); + if (!libxfs_verify_ino(mp, ino)) + goto bad; + + irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ino), + XFS_INO_TO_AGINO(mp, ino)); + if (!irec) + goto bad; + + if (is_inode_free(irec, ino - irec->ino_startnum)) + goto bad; + + return; + +bad: + lose_quota_inode(type); +} + /* * null out quota inode fields in sb if they point to non-existent inodes. * this isn't as redundant as it looks since it's possible that the sb field @@ -31,57 +60,12 @@ bool collect_rmaps; * be cleared by process_dinode(). */ static void -quotino_check(xfs_mount_t *mp) +quotino_check( + struct xfs_mount *mp) { - ino_tree_node_t *irec; - - if (mp->m_sb.sb_uquotino != NULLFSINO && mp->m_sb.sb_uquotino != 0) { - if (!libxfs_verify_ino(mp, mp->m_sb.sb_uquotino)) - irec = NULL; - else - irec = find_inode_rec(mp, - XFS_INO_TO_AGNO(mp, mp->m_sb.sb_uquotino), - XFS_INO_TO_AGINO(mp, mp->m_sb.sb_uquotino)); - - if (irec == NULL || is_inode_free(irec, - mp->m_sb.sb_uquotino - irec->ino_startnum)) { - mp->m_sb.sb_uquotino = NULLFSINO; - lost_uquotino = 1; - } else - lost_uquotino = 0; - } - - if (mp->m_sb.sb_gquotino != NULLFSINO && mp->m_sb.sb_gquotino != 0) { - if (!libxfs_verify_ino(mp, mp->m_sb.sb_gquotino)) - irec = NULL; - else - irec = find_inode_rec(mp, - XFS_INO_TO_AGNO(mp, mp->m_sb.sb_gquotino), - XFS_INO_TO_AGINO(mp, mp->m_sb.sb_gquotino)); - - if (irec == NULL || is_inode_free(irec, - mp->m_sb.sb_gquotino - irec->ino_startnum)) { - mp->m_sb.sb_gquotino = NULLFSINO; - lost_gquotino = 1; - } else - lost_gquotino = 0; - } - - if (mp->m_sb.sb_pquotino != NULLFSINO && mp->m_sb.sb_pquotino != 0) { - if (!libxfs_verify_ino(mp, mp->m_sb.sb_pquotino)) - irec = NULL; - else - irec = find_inode_rec(mp, - XFS_INO_TO_AGNO(mp, mp->m_sb.sb_pquotino), - XFS_INO_TO_AGINO(mp, mp->m_sb.sb_pquotino)); - - if (irec == NULL || is_inode_free(irec, - mp->m_sb.sb_pquotino - irec->ino_startnum)) { - mp->m_sb.sb_pquotino = NULLFSINO; - lost_pquotino = 1; - } else - lost_pquotino = 0; - } + quotino_check_one(mp, XFS_DQTYPE_USER); + quotino_check_one(mp, XFS_DQTYPE_GROUP); + quotino_check_one(mp, XFS_DQTYPE_PROJ); } static void @@ -107,14 +91,14 @@ quota_sb_check(xfs_mount_t *mp) */ if (fs_quotas && - (mp->m_sb.sb_uquotino == NULLFSINO || mp->m_sb.sb_uquotino == 0) && - (mp->m_sb.sb_gquotino == NULLFSINO || mp->m_sb.sb_gquotino == 0) && - (mp->m_sb.sb_pquotino == NULLFSINO || mp->m_sb.sb_pquotino == 0)) { + !has_quota_inode(XFS_DQTYPE_USER) && + !has_quota_inode(XFS_DQTYPE_GROUP) && + !has_quota_inode(XFS_DQTYPE_PROJ)) { lost_quotas = 1; fs_quotas = 0; - } else if (libxfs_verify_ino(mp, mp->m_sb.sb_uquotino) && - libxfs_verify_ino(mp, mp->m_sb.sb_gquotino) && - libxfs_verify_ino(mp, mp->m_sb.sb_pquotino)) { + } else if (libxfs_verify_ino(mp, get_quota_inode(XFS_DQTYPE_USER)) && + libxfs_verify_ino(mp, get_quota_inode(XFS_DQTYPE_GROUP)) && + libxfs_verify_ino(mp, get_quota_inode(XFS_DQTYPE_PROJ))) { fs_quotas = 1; } } diff --git a/repair/phase6.c b/repair/phase6.c index fa4eeb08265f0c..7bfacb66d4464e 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3189,12 +3189,12 @@ mark_standalone_inodes(xfs_mount_t *mp) if (!fs_quotas) return; - if (mp->m_sb.sb_uquotino && mp->m_sb.sb_uquotino != NULLFSINO) - mark_inode(mp, mp->m_sb.sb_uquotino); - if (mp->m_sb.sb_gquotino && mp->m_sb.sb_gquotino != NULLFSINO) - mark_inode(mp, mp->m_sb.sb_gquotino); - if (mp->m_sb.sb_pquotino && mp->m_sb.sb_pquotino != NULLFSINO) - mark_inode(mp, mp->m_sb.sb_pquotino); + if (has_quota_inode(XFS_DQTYPE_USER)) + mark_inode(mp, get_quota_inode(XFS_DQTYPE_USER)); + if (has_quota_inode(XFS_DQTYPE_GROUP)) + mark_inode(mp, get_quota_inode(XFS_DQTYPE_GROUP)); + if (has_quota_inode(XFS_DQTYPE_PROJ)) + mark_inode(mp, get_quota_inode(XFS_DQTYPE_PROJ)); } static void diff --git a/repair/quotacheck.c b/repair/quotacheck.c index 11e2d64eb34791..c4baf70e41d6b1 100644 --- a/repair/quotacheck.c +++ b/repair/quotacheck.c @@ -203,9 +203,7 @@ quotacheck_adjust( return; /* Quota files are not included in quota counts. */ - if (ino == mp->m_sb.sb_uquotino || - ino == mp->m_sb.sb_gquotino || - ino == mp->m_sb.sb_pquotino) + if (is_any_quota_inode(ino)) return; error = -libxfs_iget(mp, NULL, ino, 0, &ip); @@ -415,20 +413,20 @@ quotacheck_verify( switch (type) { case XFS_DQTYPE_USER: - ino = mp->m_sb.sb_uquotino; dquots = user_dquots; metafile_type = XFS_METAFILE_USRQUOTA; break; case XFS_DQTYPE_GROUP: - ino = mp->m_sb.sb_gquotino; dquots = group_dquots; metafile_type = XFS_METAFILE_GRPQUOTA; break; case XFS_DQTYPE_PROJ: - ino = mp->m_sb.sb_pquotino; dquots = proj_dquots; metafile_type = XFS_METAFILE_PRJQUOTA; break; + default: + ASSERT(0); + return; } /* @@ -443,6 +441,7 @@ quotacheck_verify( if (error) do_error(_("could not alloc transaction to open quota file\n")); + ino = get_quota_inode(type); error = -libxfs_trans_metafile_iget(tp, ino, metafile_type, &ip); if (error) { do_warn( @@ -505,34 +504,28 @@ qc_has_quotafile( struct xfs_mount *mp, xfs_dqtype_t type) { - bool lost; xfs_ino_t ino; unsigned int qflag; switch (type) { case XFS_DQTYPE_USER: - lost = lost_uquotino; - ino = mp->m_sb.sb_uquotino; qflag = XFS_UQUOTA_CHKD; break; case XFS_DQTYPE_GROUP: - lost = lost_gquotino; - ino = mp->m_sb.sb_gquotino; qflag = XFS_GQUOTA_CHKD; break; case XFS_DQTYPE_PROJ: - lost = lost_pquotino; - ino = mp->m_sb.sb_pquotino; qflag = XFS_PQUOTA_CHKD; break; default: return false; } - if (lost) + if (lost_quota_inode(type)) return false; if (!(mp->m_sb.sb_qflags & qflag)) return false; + ino = get_quota_inode(type); if (ino == NULLFSINO || ino == 0) return false; return true; @@ -626,3 +619,29 @@ quotacheck_teardown(void) qc_purge(&group_dquots); qc_purge(&proj_dquots); } + +void +update_sb_quotinos( + struct xfs_mount *mp, + struct xfs_buf *sbp) +{ + bool dirty = false; + + if (mp->m_sb.sb_uquotino != get_quota_inode(XFS_DQTYPE_USER)) { + mp->m_sb.sb_uquotino = get_quota_inode(XFS_DQTYPE_USER); + dirty = true; + } + + if (mp->m_sb.sb_gquotino != get_quota_inode(XFS_DQTYPE_GROUP)) { + mp->m_sb.sb_gquotino = get_quota_inode(XFS_DQTYPE_GROUP); + dirty = true; + } + + if (mp->m_sb.sb_pquotino != get_quota_inode(XFS_DQTYPE_PROJ)) { + mp->m_sb.sb_pquotino = get_quota_inode(XFS_DQTYPE_PROJ); + dirty = true; + } + + if (dirty) + libxfs_sb_to_disk(sbp->b_addr, &mp->m_sb); +} diff --git a/repair/quotacheck.h b/repair/quotacheck.h index dcbf1623947b48..36f9f5a12f7f3e 100644 --- a/repair/quotacheck.h +++ b/repair/quotacheck.h @@ -13,4 +13,6 @@ uint16_t quotacheck_results(void); int quotacheck_setup(struct xfs_mount *mp); void quotacheck_teardown(void); +void update_sb_quotinos(struct xfs_mount *mp, struct xfs_buf *sbp); + #endif /* __XFS_REPAIR_QUOTACHECK_H__ */ diff --git a/repair/versions.c b/repair/versions.c index 7dc91b4597eece..689cc471176da0 100644 --- a/repair/versions.c +++ b/repair/versions.c @@ -104,9 +104,6 @@ parse_sb_version( fs_sb_feature_bits = 0; fs_ino_alignment = 0; fs_has_extflgbit = 1; - have_uquotino = 0; - have_gquotino = 0; - have_pquotino = 0; if (mp->m_sb.sb_versionnum & XFS_SB_VERSION_SHAREDBIT) { do_warn(_("Shared Version bit set. Not supported. Ever.\n")); @@ -166,13 +163,13 @@ _("WARNING: you have a V1 inode filesystem. It would be converted to a\n" fs_quotas = 1; if (mp->m_sb.sb_uquotino != 0 && mp->m_sb.sb_uquotino != NULLFSINO) - have_uquotino = 1; + set_quota_inode(XFS_DQTYPE_USER, mp->m_sb.sb_uquotino); if (mp->m_sb.sb_gquotino != 0 && mp->m_sb.sb_gquotino != NULLFSINO) - have_gquotino = 1; + set_quota_inode(XFS_DQTYPE_GROUP, mp->m_sb.sb_gquotino); if (mp->m_sb.sb_pquotino != 0 && mp->m_sb.sb_pquotino != NULLFSINO) - have_pquotino = 1; + set_quota_inode(XFS_DQTYPE_PROJ, mp->m_sb.sb_pquotino); } if (xfs_has_align(mp)) { diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 2a8a72e7027591..363f8260bd575a 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -1404,7 +1404,9 @@ _("Inode allocation btrees are too corrupted, skipping phases 6 and 7\n")); free_rtgroup_inodes(); } - if (lost_quotas && !have_uquotino && !have_gquotino && !have_pquotino) { + if (lost_quotas && !has_quota_inode(XFS_DQTYPE_USER) && + !has_quota_inode(XFS_DQTYPE_GROUP) && + !has_quota_inode(XFS_DQTYPE_PROJ)) { if (!no_modify) { do_warn( _("Warning: no quota inodes were found. Quotas disabled.\n")); @@ -1421,7 +1423,7 @@ _("Warning: quota inodes were cleared. Quotas disabled.\n")); _("Warning: quota inodes would be cleared. Quotas would be disabled.\n")); } } else { - if (lost_uquotino) { + if (lost_quota_inode(XFS_DQTYPE_USER)) { if (!no_modify) { do_warn( _("Warning: user quota information was cleared.\n" @@ -1433,7 +1435,7 @@ _("Warning: user quota information would be cleared.\n" } } - if (lost_gquotino) { + if (lost_quota_inode(XFS_DQTYPE_GROUP)) { if (!no_modify) { do_warn( _("Warning: group quota information was cleared.\n" @@ -1445,7 +1447,7 @@ _("Warning: group quota information would be cleared.\n" } } - if (lost_pquotino) { + if (lost_quota_inode(XFS_DQTYPE_PROJ)) { if (!no_modify) { do_warn( _("Warning: project quota information was cleared.\n" @@ -1485,6 +1487,8 @@ _("Warning: project quota information would be cleared.\n" if (!sbp) do_error(_("couldn't get superblock\n")); + update_sb_quotinos(mp, sbp); + if ((mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD) != quotacheck_results()) { do_warn(_("Note - quota info will be regenerated on next " "quota mount.\n")); From patchwork Sat Dec 7 00:19:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898147 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18E2E4A1C for ; Sat, 7 Dec 2024 00:19:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530743; cv=none; b=orQq/4vK+C9eUXwGwivu0p9RiTYPa3XOOxDic8FIaLhrKxhvH81nICmZEd4jmJBrKAlbHgDhAc6EK9Zgrm0f+O+OwW8RxcmBj3ai0EFSBz0qFEVVk7Zp30VR07vrU1ILLi4UGpMRyOvFDHe/QJdsz+Yw40WrmM22bpbByW5OiPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530743; c=relaxed/simple; bh=05RybQkomPUSxlOULRYuitna7fvlIX40uS6tMMN899g=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lv5i+gC/etvRNsPlwSd7gNCfgHyYuKg/eiW6uSKuQ3PMB1T1rI3yETf2Zj9dtvO3Z5Oqipdrky2BjR/klIGFOVUTIAmF74A1Fjk3CviODC8rmRIVpzCLY0kJ++ZDgN/CwLIGWaz8Ny8zErhejBO/WFyvlNCWd4tOEC/x7QPq2Ok= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PQytojDA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PQytojDA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADFC7C4CED1; Sat, 7 Dec 2024 00:19:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530742; bh=05RybQkomPUSxlOULRYuitna7fvlIX40uS6tMMN899g=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=PQytojDAM0gZfWDM/7eoCQzgsKaRg7l8+4BsNf2MBfvYEOtOBMo5gULC6zcoiMwGJ K3ILbM9Xnen4tvmd2+eNu2kF7fPIoKh4R3ZR+WohmKQQMD3SBuB0LWcNyb2zgVq9av Hz/jhIb+iEOSct1ZFAK0C0ENFSFAByrpbWuk/52Ha2Nxg1e/MY3uNI+/JpYg+WtnoM 6dr08+w24PnkJMXwyY4xRdDgN3QVTCOJyT5YJq21fTkR0hCAn4Ylw0XEpQYP+b43Ug NYqGt/OCRRmHtPVuC76hANW0JZ1VT1pvr5h6umRp+PgakGpyXaf067aH7ZDATPqLcR 0oZ2QJlH5k5hg== Date: Fri, 06 Dec 2024 16:19:02 -0800 Subject: [PATCH 4/7] xfs_repair: hoist the secondary sb qflags handling From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753294.129683.12319167915814901490.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Hoist all the secondary superblock qflags and quota inode modification code into a separate function so that we can disable it in the next patch. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/agheader.c | 157 +++++++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 72 deletions(-) diff --git a/repair/agheader.c b/repair/agheader.c index fd279559aed973..4a530fd6b8fe96 100644 --- a/repair/agheader.c +++ b/repair/agheader.c @@ -319,6 +319,90 @@ check_v5_feature_mismatch( return XR_AG_SB_SEC; } +/* + * quota inodes and flags in secondary superblocks are never set by mkfs. + * However, they could be set in a secondary if a fs with quotas was growfs'ed + * since growfs copies the new primary into the secondaries. + * + * Also, the in-core inode flags now have different meaning to the on-disk + * flags, and so libxfs_sb_to_disk cannot directly write the + * sb_gquotino/sb_pquotino fields without specific sb_qflags being set. Hence + * we need to zero those fields directly in the sb buffer here. + */ +static int +secondary_sb_quota( + struct xfs_mount *mp, + struct xfs_buf *sbuf, + struct xfs_sb *sb, + xfs_agnumber_t i, + int do_bzero) +{ + struct xfs_dsb *dsb = sbuf->b_addr; + int rval = 0; + + if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) { + if (!no_modify) + sb->sb_uquotino = 0; + if (!do_bzero) { + rval |= XR_AG_SB; + do_warn( + _("non-null user quota inode field in superblock %d\n"), + i); + + } else + rval |= XR_AG_SB_SEC; + } + + if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) { + if (!no_modify) { + sb->sb_gquotino = 0; + dsb->sb_gquotino = 0; + } + if (!do_bzero) { + rval |= XR_AG_SB; + do_warn( + _("non-null group quota inode field in superblock %d\n"), + i); + + } else + rval |= XR_AG_SB_SEC; + } + + /* + * Note that sb_pquotino is not considered a valid sb field for pre-v5 + * superblocks. If it is anything other than 0 it is considered garbage + * data beyond the valid sb and explicitly zeroed above. + */ + if (xfs_has_pquotino(mp) && + sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) { + if (!no_modify) { + sb->sb_pquotino = 0; + dsb->sb_pquotino = 0; + } + if (!do_bzero) { + rval |= XR_AG_SB; + do_warn( + _("non-null project quota inode field in superblock %d\n"), + i); + + } else + rval |= XR_AG_SB_SEC; + } + + if (sb->sb_inprogress == 1 && sb->sb_qflags) { + if (!no_modify) + sb->sb_qflags = 0; + if (!do_bzero) { + rval |= XR_AG_SB; + do_warn(_("non-null quota flags in superblock %d\n"), + i); + } else + rval |= XR_AG_SB_SEC; + } + + return rval; +} + /* * Possible fields that may have been set at mkfs time, * sb_inoalignmt, sb_unit, sb_width and sb_dirblklog. @@ -340,7 +424,6 @@ secondary_sb_whack( struct xfs_sb *sb, xfs_agnumber_t i) { - struct xfs_dsb *dsb = sbuf->b_addr; int do_bzero = 0; int size; char *ip; @@ -426,77 +509,7 @@ secondary_sb_whack( rval |= XR_AG_SB_SEC; } - /* - * quota inodes and flags in secondary superblocks are never set by - * mkfs. However, they could be set in a secondary if a fs with quotas - * was growfs'ed since growfs copies the new primary into the - * secondaries. - * - * Also, the in-core inode flags now have different meaning to the - * on-disk flags, and so libxfs_sb_to_disk cannot directly write the - * sb_gquotino/sb_pquotino fields without specific sb_qflags being set. - * Hence we need to zero those fields directly in the sb buffer here. - */ - - if (sb->sb_inprogress == 1 && sb->sb_uquotino != NULLFSINO) { - if (!no_modify) - sb->sb_uquotino = 0; - if (!do_bzero) { - rval |= XR_AG_SB; - do_warn( - _("non-null user quota inode field in superblock %d\n"), - i); - - } else - rval |= XR_AG_SB_SEC; - } - - if (sb->sb_inprogress == 1 && sb->sb_gquotino != NULLFSINO) { - if (!no_modify) { - sb->sb_gquotino = 0; - dsb->sb_gquotino = 0; - } - if (!do_bzero) { - rval |= XR_AG_SB; - do_warn( - _("non-null group quota inode field in superblock %d\n"), - i); - - } else - rval |= XR_AG_SB_SEC; - } - - /* - * Note that sb_pquotino is not considered a valid sb field for pre-v5 - * superblocks. If it is anything other than 0 it is considered garbage - * data beyond the valid sb and explicitly zeroed above. - */ - if (xfs_has_pquotino(mp) && - sb->sb_inprogress == 1 && sb->sb_pquotino != NULLFSINO) { - if (!no_modify) { - sb->sb_pquotino = 0; - dsb->sb_pquotino = 0; - } - if (!do_bzero) { - rval |= XR_AG_SB; - do_warn( - _("non-null project quota inode field in superblock %d\n"), - i); - - } else - rval |= XR_AG_SB_SEC; - } - - if (sb->sb_inprogress == 1 && sb->sb_qflags) { - if (!no_modify) - sb->sb_qflags = 0; - if (!do_bzero) { - rval |= XR_AG_SB; - do_warn(_("non-null quota flags in superblock %d\n"), - i); - } else - rval |= XR_AG_SB_SEC; - } + rval |= secondary_sb_quota(mp, sbuf, sb, i, do_bzero); /* * if the secondaries agree on a stripe unit/width or inode From patchwork Sat Dec 7 00:19:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898148 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A96434A1C for ; Sat, 7 Dec 2024 00:19:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530758; cv=none; b=rL6DncVwtA24CvPZEIG6tg/HowKXVamH3/FmDDKRp21UIHdZax3KhP51DA9TdlIKs/qLiwCs4XXrYqRWy6CRipxH0lcUqyZRTpaxfAgr5dUZfK/78BJDqXlgb6NSpm/DTeYr7hhgJwyV8SDp0TceEqH4TNOwTCwGBBUPAgx8m2I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530758; c=relaxed/simple; bh=g4Q8cVBkl57XgSJZeoSVgyLrcfXynYS16FoPC5P98tw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kYABCq3H/lt9ipTdKCSE6Dz6AWji2sKQVENeO4gqZqXqxrGC0elOndr5Tqxcbjz0U6vWCpbmfRsVfb6lZZI8Wl2Uu6v5zZuuPw7c1OYNBj5ylSDWR54Ys+J5/aDny6gBTCOa5clHhO78FUR/mx2i5CLAUhOKC8Fuc5X2Jo9VhtE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vL5m/KMo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vL5m/KMo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8258AC4CED1; Sat, 7 Dec 2024 00:19:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530758; bh=g4Q8cVBkl57XgSJZeoSVgyLrcfXynYS16FoPC5P98tw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=vL5m/KMo3hk6ko6I+y5K/IpJzQDGGAcn7NhpcBqtUFvgABAB6oTEwZPvRichj+vbc Uzl2ik73jhni0tDdiDarhDAXGsclyEWbA0ZXV+siUIalUiczuH4umr81XHgghKBU4s yQ8O5jOApgYoAHChDdkmVGffkOyIRojiq2vq9I3MQYe7AADhUcpRu7JWUsI4SnzBsx eYCjrelVdTkRtkKxUJKEJKqdlf0DM7sb2kTg54ZqaA00TXGc/IYpp/7JorQQyuLANh hTjw40IrIHxc2pqTDYYy7eisSuLYjJlHNf85BUJhFNUGTSZbHL2PaSdu+3RysNb0Oc SxVLB3Xe7V6Tw== Date: Fri, 06 Dec 2024 16:19:17 -0800 Subject: [PATCH 5/7] xfs_repair: support quota inodes in the metadata directory From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753310.129683.8156547641009207395.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Handle quota inodes on metadir filesystems. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/agheader.c | 3 + repair/phase2.c | 3 + repair/phase6.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ repair/quotacheck.c | 71 +++++++++++++++++++++++++++++++ repair/quotacheck.h | 1 repair/xfs_repair.c | 3 + 6 files changed, 194 insertions(+), 3 deletions(-) diff --git a/repair/agheader.c b/repair/agheader.c index 4a530fd6b8fe96..e6fca07c6cb4c9 100644 --- a/repair/agheader.c +++ b/repair/agheader.c @@ -509,7 +509,8 @@ secondary_sb_whack( rval |= XR_AG_SB_SEC; } - rval |= secondary_sb_quota(mp, sbuf, sb, i, do_bzero); + if (!xfs_has_metadir(mp)) + rval |= secondary_sb_quota(mp, sbuf, sb, i, do_bzero); /* * if the secondaries agree on a stripe unit/width or inode diff --git a/repair/phase2.c b/repair/phase2.c index 27c873fca76747..71576f5806e473 100644 --- a/repair/phase2.c +++ b/repair/phase2.c @@ -15,6 +15,7 @@ #include "progress.h" #include "scan.h" #include "rt.h" +#include "quotacheck.h" /* workaround craziness in the xlog routines */ int xlog_recover_do_trans(struct xlog *log, struct xlog_recover *t, int p) @@ -625,6 +626,8 @@ phase2( } discover_rtgroup_inodes(mp); + if (xfs_has_metadir(mp) && xfs_has_quota(mp)) + discover_quota_inodes(mp); /* * Upgrade the filesystem now that we've done a preliminary check of diff --git a/repair/phase6.c b/repair/phase6.c index 7bfacb66d4464e..6f124f749116e1 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -20,6 +20,7 @@ #include "versions.h" #include "repair/pptr.h" #include "repair/rt.h" +#include "repair/quotacheck.h" static xfs_ino_t orphanage_ino; @@ -3186,7 +3187,7 @@ mark_standalone_inodes(xfs_mount_t *mp) mark_inode(mp, mp->m_sb.sb_rsumino); } - if (!fs_quotas) + if (!fs_quotas || xfs_has_metadir(mp)) return; if (has_quota_inode(XFS_DQTYPE_USER)) @@ -3408,6 +3409,116 @@ _(" - resetting contents of realtime bitmap and summary inodes\n")); } } +static bool +ensure_quota_file( + struct xfs_inode *dp, + xfs_dqtype_t type) +{ + struct xfs_mount *mp = dp->i_mount; + struct xfs_inode *ip; + const char *name = libxfs_dqinode_path(type); + int error; + + if (!has_quota_inode(type)) + return false; + + if (no_modify) { + if (lost_quota_inode(type)) + do_warn(_("would reset %s quota inode\n"), name); + return false; + } + + if (!lost_quota_inode(type)) { + /* + * The /quotas directory has been discarded, but we should + * be able to iget the quota files directly. + */ + error = -libxfs_metafile_iget(mp, get_quota_inode(type), + xfs_dqinode_metafile_type(type), &ip); + if (error) { + do_warn( +_("Could not open %s quota inode, error %d\n"), + name, error); + lose_quota_inode(type); + } + } + + if (lost_quota_inode(type)) { + /* + * The inode was bad or missing, state that we'll make a new + * one even though we always create a new one. + */ + do_warn(_("resetting %s quota inode\n"), name); + error = -libxfs_dqinode_metadir_create(dp, type, &ip); + if (error) { + do_warn( +_("Couldn't create %s quota inode, error %d\n"), + name, error); + goto bad; + } + } else { + struct xfs_trans *tp; + + /* Erase parent pointers before we create the new link */ + try_erase_parent_ptrs(ip); + + error = -libxfs_dqinode_metadir_link(dp, type, ip); + if (error) { + do_warn( +_("Couldn't link %s quota inode, error %d\n"), + name, error); + goto bad; + } + + /* + * Reset the link count to 1 because quota files are never + * hardlinked, but the link above probably bumped it. + */ + error = -libxfs_trans_alloc_inode(ip, &M_RES(mp)->tr_ichange, + 0, 0, false, &tp); + if (!error) { + set_nlink(VFS_I(ip), 1); + libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + error = -libxfs_trans_commit(tp); + } + if (error) + do_error( +_("Couldn't reset link count on %s quota inode, error %d\n"), + name, error); + } + + /* Mark the inode in use. */ + mark_ino_inuse(mp, ip->i_ino, S_IFREG, dp->i_ino); + mark_ino_metadata(mp, ip->i_ino); + libxfs_irele(ip); + return true; +bad: + /* Zeroes qflags */ + quotacheck_skip(); + return false; +} + +static void +reset_quota_metadir_inodes( + struct xfs_mount *mp) +{ + struct xfs_inode *dp = NULL; + int error; + + error = -libxfs_dqinode_mkdir_parent(mp, &dp); + if (error) + do_error(_("failed to create quota metadir (%d)\n"), + error); + + mark_ino_inuse(mp, dp->i_ino, S_IFDIR, mp->m_metadirip->i_ino); + mark_ino_metadata(mp, dp->i_ino); + + ensure_quota_file(dp, XFS_DQTYPE_USER); + ensure_quota_file(dp, XFS_DQTYPE_GROUP); + ensure_quota_file(dp, XFS_DQTYPE_PROJ); + libxfs_irele(dp); +} + void phase6(xfs_mount_t *mp) { @@ -3461,6 +3572,9 @@ phase6(xfs_mount_t *mp) else reset_rt_sb_inodes(mp); + if (xfs_has_metadir(mp) && xfs_has_quota(mp) && !no_modify) + reset_quota_metadir_inodes(mp); + mark_standalone_inodes(mp); do_log(_(" - traversing filesystem ...\n")); diff --git a/repair/quotacheck.c b/repair/quotacheck.c index c4baf70e41d6b1..8c7339b267d8e6 100644 --- a/repair/quotacheck.c +++ b/repair/quotacheck.c @@ -645,3 +645,74 @@ update_sb_quotinos( if (dirty) libxfs_sb_to_disk(sbp->b_addr, &mp->m_sb); } + +static inline int +mark_quota_inode( + struct xfs_trans *tp, + struct xfs_inode *dp, + xfs_dqtype_t type) +{ + struct xfs_inode *ip; + int error; + + error = -libxfs_dqinode_load(tp, dp, type, &ip); + if (error == ENOENT) + return 0; + if (error) + goto out_corrupt; + + set_quota_inode(type, ip->i_ino); + libxfs_irele(ip); + return 0; + +out_corrupt: + lose_quota_inode(type); + return error; +} + +/* Mark the reachable quota metadata inodes prior to the inode scan. */ +void +discover_quota_inodes( + struct xfs_mount *mp) +{ + struct xfs_trans *tp; + struct xfs_inode *dp = NULL; + int error, err2; + + error = -libxfs_trans_alloc_empty(mp, &tp); + if (error) + goto out; + + error = -libxfs_dqinode_load_parent(tp, &dp); + if (error) + goto out_cancel; + + error = mark_quota_inode(tp, dp, XFS_DQTYPE_USER); + err2 = mark_quota_inode(tp, dp, XFS_DQTYPE_GROUP); + if (err2 && !error) + error = err2; + error = mark_quota_inode(tp, dp, XFS_DQTYPE_PROJ); + if (err2 && !error) + error = err2; + + libxfs_irele(dp); +out_cancel: + libxfs_trans_cancel(tp); +out: + if (error) { + switch (error) { + case EFSCORRUPTED: + do_warn( + _("corruption in metadata directory tree while discovering quota inodes\n")); + break; + case ENOENT: + /* Do nothing, we'll just clear qflags later. */ + break; + default: + do_warn( + _("couldn't discover quota inodes, err %d\n"), + error); + break; + } + } +} diff --git a/repair/quotacheck.h b/repair/quotacheck.h index 36f9f5a12f7f3e..24c9ffa418a3bf 100644 --- a/repair/quotacheck.h +++ b/repair/quotacheck.h @@ -14,5 +14,6 @@ int quotacheck_setup(struct xfs_mount *mp); void quotacheck_teardown(void); void update_sb_quotinos(struct xfs_mount *mp, struct xfs_buf *sbp); +void discover_quota_inodes(struct xfs_mount *mp); #endif /* __XFS_REPAIR_QUOTACHECK_H__ */ diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 363f8260bd575a..9509f04685c870 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -1487,7 +1487,8 @@ _("Warning: project quota information would be cleared.\n" if (!sbp) do_error(_("couldn't get superblock\n")); - update_sb_quotinos(mp, sbp); + if (!xfs_has_metadir(mp)) + update_sb_quotinos(mp, sbp); if ((mp->m_sb.sb_qflags & XFS_ALL_QUOTA_CHKD) != quotacheck_results()) { do_warn(_("Note - quota info will be regenerated on next " From patchwork Sat Dec 7 00:19:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898149 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 573A14A1C for ; Sat, 7 Dec 2024 00:19:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530774; cv=none; b=p1xUZwfeUUAnyQesMSYZLQG/19O1k10QR1/E56GGDkzMnp3WyxPwBpYuVrd5Vul0SReFHmAVIUQS6kEQWnUP3sPfwerB4XFU20utm1sXKcDiydlxuQtZFmng4vlq5oY+Ti2U3D1XaI4Hdyfc8RwloIdZB5HH7EH7C6WMZTCL+YU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530774; c=relaxed/simple; bh=5PghecbICmijGbLThgrWHAJvLzQk7W23W/9cDLwsLts=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SuuQ6jOHbjDjGsc4sef7kKk/aXeyZ70VPb5H+I6tYf5+2VA+v1MlbeKBcMrRfP9hRCOxtmeflVEpuuI7Ts4UrQ+Szfw6w00tSPdn22k1ltyz3RTC2mMad+8Hl/TIVacdqvawKG7JtC2kowNg+E9DaVRpqHAdts+Vw+OiINSaLJg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HaMTXvSI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HaMTXvSI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 30B08C4CED1; Sat, 7 Dec 2024 00:19:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530774; bh=5PghecbICmijGbLThgrWHAJvLzQk7W23W/9cDLwsLts=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=HaMTXvSIQJtJDr2h83qtM3zcq9fhA0RweGFLlpLfJ2odgRDTc2necdVtsV1jBfqu8 Hsq74VxVOQFfvt/9AtrxpNKxjuitzAHeLUjWstW0R1SJ+XSbIjEnU4i5VkyunIKrEZ Vul/j5LzFi+gqO9/eSxpCWshg4kfWYb9Dt6FiYzDetY/IwLWSqw0jcetPoeOsFER6i NrOsMRsuiJSnBFkN1H8XQ5oqUOR+gqAGdhqvs8rHx/VuHZVQX5a7ejpZqJMb/QR64Z gMSJhnReIBzTg2fFBzYF5pt1bBG4vgN4TFxeI6OwoAaL+ypWgljFr+5P9+wXNRmBNZ HQ7573FnTrMfQ== Date: Fri, 06 Dec 2024 16:19:33 -0800 Subject: [PATCH 6/7] xfs_repair: try not to trash qflags on metadir filesystems From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753324.129683.11573020537942192605.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Try to preserve the accounting and enforcement quota flags when repairing filesystems. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- repair/agheader.c | 3 ++- repair/phase4.c | 20 ++++++++++++++++++++ repair/sb.c | 3 +++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/repair/agheader.c b/repair/agheader.c index e6fca07c6cb4c9..89a23a869a02e4 100644 --- a/repair/agheader.c +++ b/repair/agheader.c @@ -642,7 +642,8 @@ verify_set_agheader(xfs_mount_t *mp, struct xfs_buf *sbuf, xfs_sb_t *sb, sb->sb_fdblocks = 0; sb->sb_frextents = 0; - sb->sb_qflags = 0; + if (!xfs_has_metadir(mp)) + sb->sb_qflags = 0; } rval |= XR_AG_SB; diff --git a/repair/phase4.c b/repair/phase4.c index a4183c557a1891..728d9ed84cdc7a 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -71,6 +71,26 @@ quotino_check( static void quota_sb_check(xfs_mount_t *mp) { + if (xfs_has_metadir(mp)) { + /* + * Metadir filesystems try to preserve the quota accounting + * and enforcement flags so that users don't have to remember + * to supply quota mount options. Phase 1 discovered the + * QUOTABIT flag (fs_quotas) and phase 2 discovered the quota + * inodes from the metadir for us. + * + * If QUOTABIT wasn't set but we found quota inodes, signal + * phase 5 to add the feature bit for us. We do not ever + * downgrade the filesystem. + */ + if (!fs_quotas && + (has_quota_inode(XFS_DQTYPE_USER) || + has_quota_inode(XFS_DQTYPE_GROUP) || + has_quota_inode(XFS_DQTYPE_PROJ))) + fs_quotas = 1; + return; + } + /* * if the sb says we have quotas and we lost both, * signal a superblock downgrade. that will cause diff --git a/repair/sb.c b/repair/sb.c index d52ab2ffeaf28c..0e4827e046780b 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -233,6 +233,9 @@ find_secondary_sb(xfs_sb_t *rsb) if (!retval) retval = __find_secondary_sb(rsb, XFS_AG_MIN_BYTES, BSIZE); + if (retval && xfs_sb_version_hasmetadir(rsb)) + do_warn(_("quota accounting and enforcement flags lost\n")); + return retval; } From patchwork Sat Dec 7 00:19:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13898150 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDAB94A24 for ; Sat, 7 Dec 2024 00:19:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530790; cv=none; b=dhhlUK9XQxIGmmW6zBVHdY8cHzeWN6f8OZljhm/80Gl0Hor7D/HmeMEdb5/7JLwIDPmzfkIpGz3nUdHnVSHpS8qzLbjdPLhTPl4v75tg5tzZP6YUkMoZCC9J3FRn7lmRVZT+MRuD4iSmAoiHUj21F7ftEpc+2MeaMzhprPL9CfA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1733530790; c=relaxed/simple; bh=5xqDPrKM6wCepA18xHwYgjL3pH0B/ouDYCmMr0GH9hU=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MiFUx9zTHsbxFLQ9HZ6werNrG6xf7BJ/XVQmKDCA+cccSBAtt2bJjP+ujmwlmgBwLLQtAvOuNQ6a+3JFlv2PYjXLYIAqerJqI73CvaUX7MOjr5F1xDQWiHo1ndlEMJidcSo5YcX5uOQAuepnbd09ghr9wOQQ9yc4A+F14oQX8zU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ekzoJ+Tl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ekzoJ+Tl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C3A92C4CED1; Sat, 7 Dec 2024 00:19:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1733530789; bh=5xqDPrKM6wCepA18xHwYgjL3pH0B/ouDYCmMr0GH9hU=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=ekzoJ+TlEuD8CpUcDaZk7qL9vDwfm2QF/7QdGpv3tPGCW1nyrhR9OSU5Pi0PVwPUc GvDfV8dtWu+HfUx4KStMa30genExNZNpUui5HGid61DEihIldt96xxbhqk1RshivaE nxqzEV/A7joQec6g2UG85a/H+vT421a1uJ5q5NhDGsl9Rz+hhvS6Zkbvq06psUXe5F BBJ/VaAQyz+yJuFuCmSp7YuBUBrw7U0Rfd0ArxAIc+o0sRTIS8zffcjyzs9HTnFY6b uoDzqVC9CLeYEe6EJvhuUAOQ98pUiN0C1ehKdH7LlaceycO8zAjlZII1sN/curTZX9 xQqCdJWqx578w== Date: Fri, 06 Dec 2024 16:19:49 -0800 Subject: [PATCH 7/7] mkfs: add quota flags when setting up filesystem From: "Darrick J. Wong" To: aalbersh@kernel.org, djwong@kernel.org Cc: hch@lst.de, linux-xfs@vger.kernel.org Message-ID: <173352753340.129683.15235240531842313664.stgit@frogsfrogsfrogs> In-Reply-To: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> References: <173352753222.129683.17995064282877591283.stgit@frogsfrogsfrogs> Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong If we're creating a metadir filesystem, the quota accounting and enforcement flags persist until the sysadmin changes them. Add a means to specify those qflags at format time. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- man/man8/mkfs.xfs.8.in | 48 ++++++++++++++++++++ mkfs/xfs_mkfs.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in index c6a15bd2cb1e5e..5a4d481061ff48 100644 --- a/man/man8/mkfs.xfs.8.in +++ b/man/man8/mkfs.xfs.8.in @@ -340,6 +340,54 @@ .SH OPTIONS See the .BI xfs_scrub (8) manual page for more information on this property. +.TP +.B uquota +If the metadata directory feature is enabled, the +.B \-m uquota +option will set up user quota accounting and enforcement at format time; +specifying the quota options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. +.TP +.B gquota +If the metadata directory feature is enabled, the +.B \-m gquota +option will set up group quota accounting and enforcement at format time; +specifying the quota options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. +.TP +.B pquota +If the metadata directory feature is enabled, the +.B \-m pquota +option will set up project quota accounting and enforcement at format time; +specifying the quota options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. +.TP +.B uqnoenforce +If the metadata directory feature is enabled, the +.B \-m uqnoenforce +option will set up user quota accounting at format time; specifying the quota +options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. +.TP +.B gqnoenforce +If the metadata directory feature is enabled, the +.B \-m gqnoenforce +option will set up group quota accounting at format time; specifying the quota +options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. +.TP +.B pqnoenforce +If the metadata directory feature is enabled, the +.B \-m pqnoenforce +option will set up project quota accounting at format time; specifying the +quota options in fstab is no longer unnecessary. +If metadata directories are not enabled, quotas must still be enabled via +fstab. .RE .PP .PD 0 diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index cd00f3b3bd88f7..b644022a5091ba 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -153,6 +153,12 @@ enum { M_BIGTIME, M_AUTOFSCK, M_METADIR, + M_UQUOTA, + M_GQUOTA, + M_PQUOTA, + M_UQNOENFORCE, + M_GQNOENFORCE, + M_PQNOENFORCE, M_MAX_OPTS, }; @@ -833,6 +839,12 @@ static struct opt_params mopts = { [M_BIGTIME] = "bigtime", [M_AUTOFSCK] = "autofsck", [M_METADIR] = "metadir", + [M_UQUOTA] = "uquota", + [M_GQUOTA] = "gquota", + [M_PQUOTA] = "pquota", + [M_UQNOENFORCE] = "uqnoenforce", + [M_GQNOENFORCE] = "gqnoenforce", + [M_PQNOENFORCE] = "pqnoenforce", [M_MAX_OPTS] = NULL, }, .subopt_params = { @@ -888,6 +900,48 @@ static struct opt_params mopts = { .maxval = 1, .defaultval = 1, }, + { .index = M_UQUOTA, + .conflicts = { { &mopts, M_UQNOENFORCE }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + { .index = M_GQUOTA, + .conflicts = { { &mopts, M_GQNOENFORCE }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + { .index = M_PQUOTA, + .conflicts = { { &mopts, M_GQNOENFORCE }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + { .index = M_UQNOENFORCE, + .conflicts = { { &mopts, M_UQUOTA }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + { .index = M_GQNOENFORCE, + .conflicts = { { &mopts, M_GQUOTA }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, + { .index = M_PQNOENFORCE, + .conflicts = { { &mopts, M_PQUOTA }, + { NULL, LAST_CONFLICT } }, + .minval = 0, + .maxval = 1, + .defaultval = 1, + }, }, }; @@ -945,6 +999,8 @@ struct sb_feat_args { bool nortalign; bool nrext64; bool exchrange; /* XFS_SB_FEAT_INCOMPAT_EXCHRANGE */ + + uint16_t qflags; }; struct cli_params { @@ -1083,6 +1139,8 @@ usage( void ) /* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1,\n\ inobtcount=0|1,bigtime=0|1,autofsck=xxx,\n\ metadir=0|1]\n\ +/* quota */ [-m uquota|uqnoenforce,gquota|gqnoenforce,\n\ + pquota|pqnoenforce]\n\ /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num|noalign),\n\ sectsize=num,concurrency=num]\n\ @@ -1921,6 +1979,30 @@ meta_opts_parser( case M_METADIR: cli->sb_feat.metadir = getnum(value, opts, subopt); break; + case M_UQUOTA: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_UQUOTA_ACCT | XFS_UQUOTA_ENFD; + break; + case M_GQUOTA: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_GQUOTA_ACCT | XFS_GQUOTA_ENFD; + break; + case M_PQUOTA: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_PQUOTA_ACCT | XFS_PQUOTA_ENFD; + break; + case M_UQNOENFORCE: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_UQUOTA_ACCT; + break; + case M_GQNOENFORCE: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_GQUOTA_ACCT; + break; + case M_PQNOENFORCE: + if (getnum(value, opts, subopt)) + cli->sb_feat.qflags |= XFS_PQUOTA_ACCT; + break; default: return -EINVAL; } @@ -2517,6 +2599,12 @@ _("metadata directory not supported without CRC support\n")); usage(); } cli->sb_feat.metadir = false; + + if (cli->sb_feat.qflags) { + fprintf(stderr, +_("persistent quota flags not supported without CRC support\n")); + usage(); + } } if (!cli->sb_feat.finobt) { @@ -2562,6 +2650,26 @@ _("cowextsize not supported without reflink support\n")); cli->sb_feat.exchrange = true; } + if (cli->sb_feat.qflags && cli->xi->rt.name) { + fprintf(stderr, +_("persistent quota flags not supported with realtime volumes\n")); + usage(); + } + + /* + * Persistent quota flags requires metadir support because older + * kernels (or current kernels with old filesystems) will reset qflags + * in the absence of any quota mount options. + */ + if (cli->sb_feat.qflags && !cli->sb_feat.metadir) { + if (cli_opt_set(&mopts, M_METADIR)) { + fprintf(stderr, +_("persistent quota flags not supported without metadir support\n")); + usage(); + } + cli->sb_feat.metadir = true; + } + /* * Exchange-range will be needed for space reorganization on filesystems * with realtime rmap or realtime reflink enabled, and there is no good @@ -3812,6 +3920,9 @@ sb_set_features( if (fp->dirftype && !fp->crcs_enabled) sbp->sb_features2 |= XFS_SB_VERSION2_FTYPE; + if (fp->qflags) + sbp->sb_versionnum |= XFS_SB_VERSION_QUOTABIT; + /* update whether extended features are in use */ if (sbp->sb_features2 != 0) sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT; @@ -4338,7 +4449,7 @@ finish_superblock_setup( (cfg->loginternal ? cfg->logblocks : 0); sbp->sb_frextents = 0; /* will do a free later */ sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0; - sbp->sb_qflags = 0; + sbp->sb_qflags = cfg->sb_feat.qflags; sbp->sb_unit = cfg->dsunit; sbp->sb_width = cfg->dswidth; mp->m_features |= libxfs_sb_version_to_features(sbp);