From patchwork Thu Oct 17 19:10:01 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: 13840741 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 DB7AB21C17C for ; Thu, 17 Oct 2024 19:10:01 +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=1729192201; cv=none; b=j1y663sH4pA+hmBTWsLe6ysmJGJnHvavVqN2E2NDQjaE/EJOApP3vG8YbwCqlu2iAyAVUrS9xCHsYghWHzmNsH7smQiJcim6yqZX9J+e+OC8gA6cdW01r2h6eM7kydcN1WnnNUy+6aLTgbxlXF3bMgRZNMe3APblJqqXSramKRE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192201; c=relaxed/simple; bh=Ghg8E08pjCYzdcD2fnG9nduoTiOPZud0RlUBIwmjog4=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hZJPRxXMQAwCpbdXqBkuqYMFG08ScBXakcJk6U4p3wwvHqRaSyGIkXtnY0/jUHxPE+oa5d4KhSMAokSGYPBJUIWHt/RSrbPqsMjCK+KT2/eeztFEQG6Z+7vdXol95GSbTdcRJBTXPl3UsSlo6PnPxHvyXvptFthiywMHTv9Luyg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=avsRNROj; 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="avsRNROj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B09C5C4CEC3; Thu, 17 Oct 2024 19:10:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192201; bh=Ghg8E08pjCYzdcD2fnG9nduoTiOPZud0RlUBIwmjog4=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=avsRNROj0+o4qSFZbrP5KQevJ3S4Rs7rRji77RvOUkesI8TP1WygQlCGT5ONRvljx sagIQHun8Xtf04tsoLMqqJmYhtUocu1y9/y1guwbeKUevIAcv6dFQ4TkGFchs+U4ZF PHTAJ8uXSquN6S4p95K7W2RZl/EqYoI4lBLH75OaXh31CtvfB8DH5EKcEgwYf240wR HqQfn5Zciq30n6zquNHxFosFRC10tVKbxLv43/XPiqfjFhL5j9Qqiuu7RNuYw44Fvj xXyl3hIzQEUVMy6oRSWgOPHJPp42C3o58+z1RCk3Lud7OJNZW2m1DGJnh7q5CFwDn8 49fB/4gbrgekQ== Date: Thu, 17 Oct 2024 12:10:01 -0700 Subject: [PATCH 1/4] xfs: refactor xfs_qm_destroy_quotainos From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072646.3454331.3256955076038945929.stgit@frogsfrogsfrogs> In-Reply-To: <172919072618.3454331.12971255439040173668.stgit@frogsfrogsfrogs> References: <172919072618.3454331.12971255439040173668.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 Reuse this function instead of open-coding the logic. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_qm.c | 53 ++++++++++++++++++++--------------------------------- 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 28b1420bac1dd2..b37e80fe7e86a6 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -40,7 +40,6 @@ STATIC int xfs_qm_init_quotainos(struct xfs_mount *mp); STATIC int xfs_qm_init_quotainfo(struct xfs_mount *mp); -STATIC void xfs_qm_destroy_quotainos(struct xfs_quotainfo *qi); STATIC void xfs_qm_dqfree_one(struct xfs_dquot *dqp); /* * We use the batch lookup interface to iterate over the dquots as it @@ -226,6 +225,24 @@ xfs_qm_unmount_rt( xfs_rtgroup_rele(rtg); } +STATIC void +xfs_qm_destroy_quotainos( + struct xfs_quotainfo *qi) +{ + if (qi->qi_uquotaip) { + xfs_irele(qi->qi_uquotaip); + qi->qi_uquotaip = NULL; /* paranoia */ + } + if (qi->qi_gquotaip) { + xfs_irele(qi->qi_gquotaip); + qi->qi_gquotaip = NULL; + } + if (qi->qi_pquotaip) { + xfs_irele(qi->qi_pquotaip); + qi->qi_pquotaip = NULL; + } +} + /* * Called from the vfsops layer. */ @@ -250,20 +267,8 @@ xfs_qm_unmount_quotas( /* * Release the quota inodes. */ - if (mp->m_quotainfo) { - if (mp->m_quotainfo->qi_uquotaip) { - xfs_irele(mp->m_quotainfo->qi_uquotaip); - mp->m_quotainfo->qi_uquotaip = NULL; - } - if (mp->m_quotainfo->qi_gquotaip) { - xfs_irele(mp->m_quotainfo->qi_gquotaip); - mp->m_quotainfo->qi_gquotaip = NULL; - } - if (mp->m_quotainfo->qi_pquotaip) { - xfs_irele(mp->m_quotainfo->qi_pquotaip); - mp->m_quotainfo->qi_pquotaip = NULL; - } - } + if (mp->m_quotainfo) + xfs_qm_destroy_quotainos(mp->m_quotainfo); } STATIC int @@ -1712,24 +1717,6 @@ xfs_qm_init_quotainos( return error; } -STATIC void -xfs_qm_destroy_quotainos( - struct xfs_quotainfo *qi) -{ - if (qi->qi_uquotaip) { - xfs_irele(qi->qi_uquotaip); - qi->qi_uquotaip = NULL; /* paranoia */ - } - if (qi->qi_gquotaip) { - xfs_irele(qi->qi_gquotaip); - qi->qi_gquotaip = NULL; - } - if (qi->qi_pquotaip) { - xfs_irele(qi->qi_pquotaip); - qi->qi_pquotaip = NULL; - } -} - STATIC void xfs_qm_dqfree_one( struct xfs_dquot *dqp) From patchwork Thu Oct 17 19:10:12 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: 13840742 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 05A541E0DC3 for ; Thu, 17 Oct 2024 19:10:12 +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=1729192213; cv=none; b=Qhhe9f3wM9S5tSI8DxtADMX5dVTplo5uJXhAuik8wUSE7oUidsm09xezUUMn+6cP4kCQn0Mex47juKKfnH0QEGRAdo/NxupsEaofgmVO6J4KoF79EbQQtMqGQiLdsk0RL1aYcfRbRydM8Gy0x33izltAylqhQ1ofnUXmKuI4QwA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192213; c=relaxed/simple; bh=fv9YCJd3pfZdGHemSmALjKqFXFkGOMIaQjiJ3nPHsns=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qU+3i+zi8KsLK1ILmMY5aLCJgHYuTNbIy44mubiOFVhH0CkIBHH29HWAcyKAII296LFteMbsCztteBecLMYyhrr0KiduyXOkVoFJ3Us5XXjETplDvA6UflYJHAVn6eaP7rI8LgZEz8PDYHJDIqCDhtWHH3hSqoSn1LOpk5r2/mo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FWIHQNvx; 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="FWIHQNvx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9668BC4CEC3; Thu, 17 Oct 2024 19:10:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192212; bh=fv9YCJd3pfZdGHemSmALjKqFXFkGOMIaQjiJ3nPHsns=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=FWIHQNvxvPq1X4sUJQkmgPz7g7N3DpZ0jrgX0UzPazJrL9mzcNqRlv7NgyDSW8+BN aJB3v9nQNIgoQy+qpRFZv4qtw4fUGnuOVrP+kRzDajmNY7XyTxgPsmiQeSmL8bGTjz xNOPhOeplumY87SRYFWAwm9UvQ4x5E7+SLCQu5cArHJ3FzuyYUd+iPfYxHBPtl4k0/ FHFvSoM8mDvlWC3EyzbZeQL144HxFAcMXJhmJ9Smycv6CsIUX+UanCYAEySVDxDJe7 JYD/mxdb9uCDqy5H3w4L0+xGnjrfHGHlIr4QLO2fPJ3u7heyrEYeQf2lXKguBoUTPc 1uPW+z1oO532A== Date: Thu, 17 Oct 2024 12:10:12 -0700 Subject: [PATCH 2/4] xfs: use metadir for quota inodes From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072663.3454331.12662841704832459971.stgit@frogsfrogsfrogs> In-Reply-To: <172919072618.3454331.12971255439040173668.stgit@frogsfrogsfrogs> References: <172919072618.3454331.12971255439040173668.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 Store the quota inodes in the /quota metadata directory if metadir is enabled. This enables us to stop using the sb_[ugp]uotino fields in the superblock. From this point on, all metadata files will be children of the metadata directory tree root. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_dquot_buf.c | 190 +++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_quota_defs.h | 43 +++++++++ fs/xfs/libxfs/xfs_sb.c | 1 fs/xfs/xfs_qm.c | 197 +++++++++++++++++++++++++++++++++++----- 4 files changed, 407 insertions(+), 24 deletions(-) diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c index 15a362e2f5ea70..dceef2abd4e2a3 100644 --- a/fs/xfs/libxfs/xfs_dquot_buf.c +++ b/fs/xfs/libxfs/xfs_dquot_buf.c @@ -16,6 +16,9 @@ #include "xfs_trans.h" #include "xfs_qm.h" #include "xfs_error.h" +#include "xfs_health.h" +#include "xfs_metadir.h" +#include "xfs_metafile.h" int xfs_calc_dquots_per_chunk( @@ -323,3 +326,190 @@ xfs_dquot_to_disk_ts( return cpu_to_be32(t); } + +inline unsigned int +xfs_dqinode_sick_mask(xfs_dqtype_t type) +{ + switch (type) { + case XFS_DQTYPE_USER: + return XFS_SICK_FS_UQUOTA; + case XFS_DQTYPE_GROUP: + return XFS_SICK_FS_GQUOTA; + case XFS_DQTYPE_PROJ: + return XFS_SICK_FS_PQUOTA; + } + + ASSERT(0); + return 0; +} + +/* + * Load the inode for a given type of quota, assuming that the sb fields have + * been sorted out. This is not true when switching quota types on a V4 + * filesystem, so do not use this function for that. If metadir is enabled, + * @dp must be the /quota metadir. + * + * Returns -ENOENT if the quota inode field is NULLFSINO; 0 and an inode on + * success; or a negative errno. + */ +int +xfs_dqinode_load( + struct xfs_trans *tp, + struct xfs_inode *dp, + xfs_dqtype_t type, + struct xfs_inode **ipp) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_inode *ip; + enum xfs_metafile_type metafile_type = xfs_dqinode_metafile_type(type); + int error; + + if (!xfs_has_metadir(mp)) { + xfs_ino_t ino; + + switch (type) { + case XFS_DQTYPE_USER: + ino = mp->m_sb.sb_uquotino; + break; + case XFS_DQTYPE_GROUP: + ino = mp->m_sb.sb_gquotino; + break; + case XFS_DQTYPE_PROJ: + ino = mp->m_sb.sb_pquotino; + break; + default: + ASSERT(0); + return -EFSCORRUPTED; + } + + /* Should have set 0 to NULLFSINO when loading superblock */ + if (ino == NULLFSINO) + return -ENOENT; + + error = xfs_trans_metafile_iget(tp, ino, metafile_type, &ip); + } else { + error = xfs_metadir_load(tp, dp, xfs_dqinode_path(type), + metafile_type, &ip); + if (error == -ENOENT) + return error; + } + if (error) { + if (xfs_metadata_is_sick(error)) + xfs_fs_mark_sick(mp, xfs_dqinode_sick_mask(type)); + return error; + } + + if (XFS_IS_CORRUPT(mp, ip->i_df.if_format != XFS_DINODE_FMT_EXTENTS && + ip->i_df.if_format != XFS_DINODE_FMT_BTREE)) { + xfs_irele(ip); + xfs_fs_mark_sick(mp, xfs_dqinode_sick_mask(type)); + return -EFSCORRUPTED; + } + + if (XFS_IS_CORRUPT(mp, ip->i_projid != 0)) { + xfs_irele(ip); + xfs_fs_mark_sick(mp, xfs_dqinode_sick_mask(type)); + return -EFSCORRUPTED; + } + + *ipp = ip; + return 0; +} + +/* Create a metadata directory quota inode. */ +int +xfs_dqinode_metadir_create( + struct xfs_inode *dp, + xfs_dqtype_t type, + struct xfs_inode **ipp) +{ + struct xfs_metadir_update upd = { + .dp = dp, + .metafile_type = xfs_dqinode_metafile_type(type), + .path = xfs_dqinode_path(type), + }; + int error; + + error = xfs_metadir_start_create(&upd); + if (error) + return error; + + error = xfs_metadir_create(&upd, S_IFREG); + if (error) + return error; + + xfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE); + + error = xfs_metadir_commit(&upd); + if (error) + return error; + + xfs_finish_inode_setup(upd.ip); + *ipp = upd.ip; + return 0; +} + +#ifndef __KERNEL__ +/* Link a metadata directory quota inode. */ +int +xfs_dqinode_metadir_link( + struct xfs_inode *dp, + xfs_dqtype_t type, + struct xfs_inode *ip) +{ + struct xfs_metadir_update upd = { + .dp = dp, + .metafile_type = xfs_dqinode_metafile_type(type), + .path = xfs_dqinode_path(type), + .ip = ip, + }; + int error; + + error = xfs_metadir_start_link(&upd); + if (error) + return error; + + error = xfs_metadir_link(&upd); + if (error) + return error; + + xfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE); + + return xfs_metadir_commit(&upd); +} +#endif /* __KERNEL__ */ + +/* Create the parent directory for all quota inodes and load it. */ +int +xfs_dqinode_mkdir_parent( + struct xfs_mount *mp, + struct xfs_inode **dpp) +{ + if (!mp->m_metadirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); + return -EFSCORRUPTED; + } + + return xfs_metadir_mkdir(mp->m_metadirip, "quota", dpp); +} + +/* + * Load the parent directory of all quota inodes. Pass the inode to the caller + * because quota functions (e.g. QUOTARM) can be called on the quota files even + * if quotas are not enabled. + */ +int +xfs_dqinode_load_parent( + struct xfs_trans *tp, + struct xfs_inode **dpp) +{ + struct xfs_mount *mp = tp->t_mountp; + + if (!mp->m_metadirip) { + xfs_fs_mark_sick(mp, XFS_SICK_FS_METADIR); + return -EFSCORRUPTED; + } + + return xfs_metadir_load(tp, mp->m_metadirip, "quota", XFS_METAFILE_DIR, + dpp); +} diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h index fb05f44f6c754a..763d941a8420c5 100644 --- a/fs/xfs/libxfs/xfs_quota_defs.h +++ b/fs/xfs/libxfs/xfs_quota_defs.h @@ -143,4 +143,47 @@ time64_t xfs_dquot_from_disk_ts(struct xfs_disk_dquot *ddq, __be32 dtimer); __be32 xfs_dquot_to_disk_ts(struct xfs_dquot *ddq, time64_t timer); +static inline const char * +xfs_dqinode_path(xfs_dqtype_t type) +{ + switch (type) { + case XFS_DQTYPE_USER: + return "user"; + case XFS_DQTYPE_GROUP: + return "group"; + case XFS_DQTYPE_PROJ: + return "project"; + } + + ASSERT(0); + return NULL; +} + +static inline enum xfs_metafile_type +xfs_dqinode_metafile_type(xfs_dqtype_t type) +{ + switch (type) { + case XFS_DQTYPE_USER: + return XFS_METAFILE_USRQUOTA; + case XFS_DQTYPE_GROUP: + return XFS_METAFILE_GRPQUOTA; + case XFS_DQTYPE_PROJ: + return XFS_METAFILE_PRJQUOTA; + } + + ASSERT(0); + return XFS_METAFILE_UNKNOWN; +} + +unsigned int xfs_dqinode_sick_mask(xfs_dqtype_t type); + +int xfs_dqinode_load(struct xfs_trans *tp, struct xfs_inode *dp, + xfs_dqtype_t type, struct xfs_inode **ipp); +int xfs_dqinode_metadir_create(struct xfs_inode *dp, xfs_dqtype_t type, + struct xfs_inode **ipp); +int xfs_dqinode_metadir_link(struct xfs_inode *dp, xfs_dqtype_t type, + struct xfs_inode *ip); +int xfs_dqinode_mkdir_parent(struct xfs_mount *mp, struct xfs_inode **dpp); +int xfs_dqinode_load_parent(struct xfs_trans *tp, struct xfs_inode **dpp); + #endif /* __XFS_QUOTA_H__ */ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 6a31f48a2c5424..30c7c5238437bc 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -844,6 +844,7 @@ xfs_sb_quota_to_disk( if (xfs_sb_is_v5(from) && (from->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_METADIR)) { + to->sb_qflags = cpu_to_be16(from->sb_qflags); to->sb_uquotino = cpu_to_be64(0); to->sb_gquotino = cpu_to_be64(0); to->sb_pquotino = cpu_to_be64(0); diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index b37e80fe7e86a6..d9d09195eabb0d 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c @@ -645,6 +645,157 @@ xfs_qm_init_timelimits( xfs_qm_dqdestroy(dqp); } +static int +xfs_qm_load_metadir_qinos( + struct xfs_mount *mp, + struct xfs_quotainfo *qi, + struct xfs_inode **dpp) +{ + struct xfs_trans *tp; + int error; + + error = xfs_trans_alloc_empty(mp, &tp); + if (error) + return error; + + error = xfs_dqinode_load_parent(tp, dpp); + if (error == -ENOENT) { + /* no quota dir directory, but we'll create one later */ + error = 0; + goto out_trans; + } + if (error) + goto out_trans; + + if (XFS_IS_UQUOTA_ON(mp)) { + error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_USER, + &qi->qi_uquotaip); + if (error && error != -ENOENT) + goto out_trans; + } + + if (XFS_IS_GQUOTA_ON(mp)) { + error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_GROUP, + &qi->qi_gquotaip); + if (error && error != -ENOENT) + goto out_trans; + } + + if (XFS_IS_PQUOTA_ON(mp)) { + error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_PROJ, + &qi->qi_pquotaip); + if (error && error != -ENOENT) + goto out_trans; + } + + error = 0; +out_trans: + xfs_trans_cancel(tp); + return error; +} + +/* Create quota inodes in the metadata directory tree. */ +STATIC int +xfs_qm_create_metadir_qinos( + struct xfs_mount *mp, + struct xfs_quotainfo *qi, + struct xfs_inode **dpp) +{ + int error; + + if (!*dpp) { + error = xfs_dqinode_mkdir_parent(mp, dpp); + if (error && error != -EEXIST) + return error; + } + + if (XFS_IS_UQUOTA_ON(mp) && !qi->qi_uquotaip) { + error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_USER, + &qi->qi_uquotaip); + if (error) + return error; + } + + if (XFS_IS_GQUOTA_ON(mp) && !qi->qi_gquotaip) { + error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_GROUP, + &qi->qi_gquotaip); + if (error) + return error; + } + + if (XFS_IS_PQUOTA_ON(mp) && !qi->qi_pquotaip) { + error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_PROJ, + &qi->qi_pquotaip); + if (error) + return error; + } + + return 0; +} + +/* + * Add QUOTABIT to sb_versionnum and initialize qflags in preparation for + * creating quota files on a metadir filesystem. + */ +STATIC int +xfs_qm_prep_metadir_sb( + struct xfs_mount *mp) +{ + struct xfs_trans *tp; + int error; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp); + if (error) + return error; + + spin_lock(&mp->m_sb_lock); + + xfs_add_quota(mp); + + /* qflags will get updated fully _after_ quotacheck */ + mp->m_sb.sb_qflags = mp->m_qflags & XFS_ALL_QUOTA_ACCT; + + spin_unlock(&mp->m_sb_lock); + xfs_log_sb(tp); + + return xfs_trans_commit(tp); +} + +/* + * Load existing quota inodes or create them. Since this is a V5 filesystem, + * we don't have to deal with the grp/prjquota switcheroo thing from V4. + */ +STATIC int +xfs_qm_init_metadir_qinos( + struct xfs_mount *mp) +{ + struct xfs_quotainfo *qi = mp->m_quotainfo; + struct xfs_inode *dp = NULL; + int error; + + if (!xfs_has_quota(mp)) { + error = xfs_qm_prep_metadir_sb(mp); + if (error) + return error; + } + + error = xfs_qm_load_metadir_qinos(mp, qi, &dp); + if (error) + goto out_err; + + error = xfs_qm_create_metadir_qinos(mp, qi, &dp); + if (error) + goto out_err; + + xfs_irele(dp); + return 0; +out_err: + xfs_qm_destroy_quotainos(mp->m_quotainfo); + if (dp) + xfs_irele(dp); + return error; +} + /* * This initializes all the quota information that's kept in the * mount structure @@ -669,7 +820,10 @@ xfs_qm_init_quotainfo( * See if quotainodes are setup, and if not, allocate them, * and change the superblock accordingly. */ - error = xfs_qm_init_quotainos(mp); + if (xfs_has_metadir(mp)) + error = xfs_qm_init_metadir_qinos(mp); + else + error = xfs_qm_init_quotainos(mp); if (error) goto out_free_lru; @@ -1581,7 +1735,7 @@ xfs_qm_mount_quotas( } if (error) { - xfs_warn(mp, "Failed to initialize disk quotas."); + xfs_warn(mp, "Failed to initialize disk quotas, err %d.", error); return; } } @@ -1600,31 +1754,26 @@ xfs_qm_qino_load( xfs_dqtype_t type, struct xfs_inode **ipp) { - xfs_ino_t ino = NULLFSINO; - enum xfs_metafile_type metafile_type = XFS_METAFILE_UNKNOWN; + struct xfs_trans *tp; + struct xfs_inode *dp = NULL; + int error; - switch (type) { - case XFS_DQTYPE_USER: - ino = mp->m_sb.sb_uquotino; - metafile_type = XFS_METAFILE_USRQUOTA; - break; - case XFS_DQTYPE_GROUP: - ino = mp->m_sb.sb_gquotino; - metafile_type = XFS_METAFILE_GRPQUOTA; - break; - case XFS_DQTYPE_PROJ: - ino = mp->m_sb.sb_pquotino; - metafile_type = XFS_METAFILE_PRJQUOTA; - break; - default: - ASSERT(0); - return -EFSCORRUPTED; + error = xfs_trans_alloc_empty(mp, &tp); + if (error) + return error; + + if (xfs_has_metadir(mp)) { + error = xfs_dqinode_load_parent(tp, &dp); + if (error) + goto out_cancel; } - if (ino == NULLFSINO) - return -ENOENT; - - return xfs_metafile_iget(mp, ino, metafile_type, ipp); + error = xfs_dqinode_load(tp, dp, type, ipp); + if (dp) + xfs_irele(dp); +out_cancel: + xfs_trans_cancel(tp); + return error; } /* From patchwork Thu Oct 17 19:10:22 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: 13840743 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 C57511E0DC3 for ; Thu, 17 Oct 2024 19:10:24 +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=1729192224; cv=none; b=qIc71a8pEFXZnKAjzx6yqe2P9lWWm3CyIai99xhBwTg2E2hWyzmFnnrP+qTAMlaZ42Ovd9mrxRA+Tpg0+YKGwnvzwUdFlae9469qaJ965ufWZNlaxLCgjb5lwgrdrxgsKe7Gj8kEFQ6JFxo7oa134djx5qf9A0W6nRVnfiEONUc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192224; c=relaxed/simple; bh=7GfUwpdzc0U4wBIhJ3wcU6Chv/e1f+4uJQpDUZpPib8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fG+bCBw58JmxxyLNp8lioNU0EmDcN0DyLP8VNHgGbl2cuoejnE4KFpzyo/XEEPrN46cFFDfSJprderJ0c9NTc1i0L4A1BLU0ffgdSweF2g7EuAI2NCodvMEhVS+pFnO7BBqUQQ5QG8iLGwJAM6qLvUEwafgKHrlgRD6lzSbXPdg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pfJDsWAa; 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="pfJDsWAa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4F59BC4CEC3; Thu, 17 Oct 2024 19:10:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192224; bh=7GfUwpdzc0U4wBIhJ3wcU6Chv/e1f+4uJQpDUZpPib8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=pfJDsWAat4DMakqGmRCiPO9pi1iOO75h0haQO9R5DDCixwXRc/X7ehAODzFbONLiN jeNHqoH8gy4emh6WQCutl8ttydeuFfm9+XKxYnfFRd2r5bLro4/13PwC1RuozPS/Ie 3byEnQwbR/8ACHrrH3kAWpUlMx2OxYDdGsEZO3UlyPD0K0gKQu3D1UDb+Lth7znejc TSrxJNOR18ZS8mm4M2VeRVpdlLivrOqQIv0CoPURQJ2cx0hyhwsUljmklDE7rSbEuI ulEANtO5nLNZCn4o81Cl0Xcq9+8JOEwqAcxQdHdWwskCBbTGu99RTCuzEmXBE+weEK RUNoWRBe8oBfA== Date: Thu, 17 Oct 2024 12:10:22 -0700 Subject: [PATCH 3/4] xfs: scrub quota file metapaths From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072680.3454331.8597389388936694218.stgit@frogsfrogsfrogs> In-Reply-To: <172919072618.3454331.12971255439040173668.stgit@frogsfrogsfrogs> References: <172919072618.3454331.12971255439040173668.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 Enable online fsck for quota file metadata directory paths. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_fs.h | 6 +++- fs/xfs/scrub/metapath.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 96f7d3c95fb4bc..41ce4d3d650ec7 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -825,9 +825,13 @@ struct xfs_scrub_vec_head { #define XFS_SCRUB_METAPATH_RTDIR (1) /* rtrgroups metadir */ #define XFS_SCRUB_METAPATH_RTBITMAP (2) /* per-rtg bitmap */ #define XFS_SCRUB_METAPATH_RTSUMMARY (3) /* per-rtg summary */ +#define XFS_SCRUB_METAPATH_QUOTADIR (4) /* quota metadir */ +#define XFS_SCRUB_METAPATH_USRQUOTA (5) /* user quota */ +#define XFS_SCRUB_METAPATH_GRPQUOTA (6) /* group quota */ +#define XFS_SCRUB_METAPATH_PRJQUOTA (7) /* project quota */ /* Number of metapath sm_ino values */ -#define XFS_SCRUB_METAPATH_NR (4) +#define XFS_SCRUB_METAPATH_NR (8) /* * ioctl limits diff --git a/fs/xfs/scrub/metapath.c b/fs/xfs/scrub/metapath.c index b8e427fd7fa73e..b78db651346518 100644 --- a/fs/xfs/scrub/metapath.c +++ b/fs/xfs/scrub/metapath.c @@ -165,6 +165,74 @@ xchk_setup_metapath_rtginode( # define xchk_setup_metapath_rtginode(...) (-ENOENT) #endif /* CONFIG_XFS_RT */ +#ifdef CONFIG_XFS_QUOTA +/* Scan the /quota directory itself. */ +static int +xchk_setup_metapath_quotadir( + struct xfs_scrub *sc) +{ + struct xfs_trans *tp; + struct xfs_inode *dp = NULL; + int error; + + error = xfs_trans_alloc_empty(sc->mp, &tp); + if (error) + return error; + + error = xfs_dqinode_load_parent(tp, &dp); + xfs_trans_cancel(tp); + if (error) + return error; + + error = xchk_setup_metapath_scan(sc, sc->mp->m_metadirip, + kasprintf(GFP_KERNEL, "quota"), dp); + xfs_irele(dp); + return error; +} + +/* Scan a quota inode under the /quota directory. */ +static int +xchk_setup_metapath_dqinode( + struct xfs_scrub *sc, + xfs_dqtype_t type) +{ + struct xfs_trans *tp = NULL; + struct xfs_inode *dp = NULL; + struct xfs_inode *ip = NULL; + const char *path; + int error; + + error = xfs_trans_alloc_empty(sc->mp, &tp); + if (error) + return error; + + error = xfs_dqinode_load_parent(tp, &dp); + if (error) + goto out_cancel; + + error = xfs_dqinode_load(tp, dp, type, &ip); + if (error) + goto out_dp; + + xfs_trans_cancel(tp); + tp = NULL; + + path = kasprintf(GFP_KERNEL, "%s", xfs_dqinode_path(type)); + error = xchk_setup_metapath_scan(sc, dp, path, ip); + + xfs_irele(ip); +out_dp: + xfs_irele(dp); +out_cancel: + if (tp) + xfs_trans_cancel(tp); + return error; +} +#else +# define xchk_setup_metapath_quotadir(...) (-ENOENT) +# define xchk_setup_metapath_dqinode(...) (-ENOENT) +#endif /* CONFIG_XFS_QUOTA */ + int xchk_setup_metapath( struct xfs_scrub *sc) @@ -186,6 +254,14 @@ xchk_setup_metapath( return xchk_setup_metapath_rtginode(sc, XFS_RTGI_BITMAP); case XFS_SCRUB_METAPATH_RTSUMMARY: return xchk_setup_metapath_rtginode(sc, XFS_RTGI_SUMMARY); + case XFS_SCRUB_METAPATH_QUOTADIR: + return xchk_setup_metapath_quotadir(sc); + case XFS_SCRUB_METAPATH_USRQUOTA: + return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_USER); + case XFS_SCRUB_METAPATH_GRPQUOTA: + return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_GROUP); + case XFS_SCRUB_METAPATH_PRJQUOTA: + return xchk_setup_metapath_dqinode(sc, XFS_DQTYPE_PROJ); default: return -ENOENT; } From patchwork Thu Oct 17 19:10:34 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: 13840744 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 1403A1E0DC3 for ; Thu, 17 Oct 2024 19:10:35 +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=1729192235; cv=none; b=fMHcDvmlTYi45yi+sbOPyRPTCUsmkSrsK5rDJ+4vf3isTCQK9tjwxxG9jH+gGEEKxyrGWd/Hc4Lv/uVQLyW79qx83mfXiqdC+Sc6tnqq7cowqV50G1HVvlZF1EzRQIOauMwIOi7i5l86oybBf/Z9FkrSKMeyoBSolZc0eyhDw5o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729192235; c=relaxed/simple; bh=K3PsVHyL+ZTsTGoGcaiWvxcgfid7Tf0MoltYEC1WLpQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=qj9+dehHm0D2XaUlKCeBdVd2FYnxHv3sc6IArRRUonCugkHsFy51UianpJYp4eKiGzZ/r0LLof497LOkLbxSHNvpQ4VgQTAQ5l/qtSCu1yBID4FIHraBsGuNApnapvdYs/g5okr6IxiF5ZfjBOmqWrsUA1tRvuSK/oAsBrV4Ho0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pB8kEzmx; 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="pB8kEzmx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E8217C4CEC3; Thu, 17 Oct 2024 19:10:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1729192235; bh=K3PsVHyL+ZTsTGoGcaiWvxcgfid7Tf0MoltYEC1WLpQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=pB8kEzmxAkHPWQyFXOVE2lqmfEx8X8ce/HNeq3CPrZZq2V0D8SGCUPU8mQn9Jt/Z0 0WsD5qKmdkU5kCdWEVA4PwCP8gRc1Tq5qVcuB7pimVsASJXvKp8tNltxga54UFQTwu PIspOrLo2ccJin3Us3Vj/akCBLNpUlOGwh35n/xb06qVXxEEMiW2FqZg5XGBnmswwA qsFqJjCDLGtfDCbrGmqblGqm5zu9LaxpQ7lJ4MZVNGgBIe7lnplNT4ucGPwbSvTy6k qaVyxZGp/Vj6lv6ICTI94zxwp5ieIHYsNIKy7dWUwPfGdWSKg0d0GRSfZqGOLp7UpT JlZo+NaGjwu1Q== Date: Thu, 17 Oct 2024 12:10:34 -0700 Subject: [PATCH 4/4] xfs: persist quota flags with metadir From: "Darrick J. Wong" To: djwong@kernel.org Cc: linux-xfs@vger.kernel.org, hch@lst.de Message-ID: <172919072698.3454331.4867816075365961256.stgit@frogsfrogsfrogs> In-Reply-To: <172919072618.3454331.12971255439040173668.stgit@frogsfrogsfrogs> References: <172919072618.3454331.12971255439040173668.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 It's annoying that one has to keep reminding XFS about what quota options it should mount with, since the quota flags recording the previous state are sitting right there in the primary superblock. Even more strangely, there exists a noquota option to disable quotas completely, so it's odder still that providing no options is the same as noquota. Starting with metadir, let's change the behavior so that if the user does not specify any quota-related mount options at all, the ondisk quota flags will be used to bring up quota. In other words, the filesystem will mount in the same state and with the same functionality as it had during the last mount. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- fs/xfs/xfs_mount.c | 15 +++++++++++++++ fs/xfs/xfs_mount.h | 6 ++++++ fs/xfs/xfs_qm_bhv.c | 18 ++++++++++++++++++ fs/xfs/xfs_quota.h | 2 ++ fs/xfs/xfs_super.c | 22 ++++++++++++++++++++++ 5 files changed, 63 insertions(+) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index dba1f6fc688166..5918f433dba754 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -852,6 +852,13 @@ xfs_mountfs( if (error) goto out_fail_wait; + /* + * If we're resuming quota status, pick up the preliminary qflags from + * the ondisk superblock so that we know if we should recover dquots. + */ + if (xfs_is_resuming_quotaon(mp)) + xfs_qm_resume_quotaon(mp); + /* * Log's mount-time initialization. The first part of recovery can place * some items on the AIL, to be handled when recovery is finished or @@ -865,6 +872,14 @@ xfs_mountfs( goto out_inodegc_shrinker; } + /* + * If we're resuming quota status and recovered the log, re-sample the + * qflags from the ondisk superblock now that we've recovered it, just + * in case someone shut down enforcement just before a crash. + */ + if (xfs_clear_resuming_quotaon(mp) && xlog_recovery_needed(mp->m_log)) + xfs_qm_resume_quotaon(mp); + /* * If logged xattrs are still enabled after log recovery finishes, then * they'll be available until unmount. Otherwise, turn them off. diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index ba3dc583b68687..d4e0df1de0940c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -497,6 +497,8 @@ __XFS_HAS_FEAT(nouuid, NOUUID) #define XFS_OPSTATE_WARNED_PPTR 15 /* Kernel has logged a warning about metadata dirs being used on this fs. */ #define XFS_OPSTATE_WARNED_METADIR 16 +/* Filesystem should use qflags to determine quotaon status */ +#define XFS_OPSTATE_RESUMING_QUOTAON 17 #define __XFS_IS_OPSTATE(name, NAME) \ static inline bool xfs_is_ ## name (struct xfs_mount *mp) \ @@ -521,8 +523,12 @@ __XFS_IS_OPSTATE(inodegc_enabled, INODEGC_ENABLED) __XFS_IS_OPSTATE(blockgc_enabled, BLOCKGC_ENABLED) #ifdef CONFIG_XFS_QUOTA __XFS_IS_OPSTATE(quotacheck_running, QUOTACHECK_RUNNING) +__XFS_IS_OPSTATE(resuming_quotaon, RESUMING_QUOTAON) #else # define xfs_is_quotacheck_running(mp) (false) +# define xfs_is_resuming_quotaon(mp) (false) +# define xfs_set_resuming_quotaon(mp) (false) +# define xfs_clear_resuming_quotaon(mp) (false) #endif __XFS_IS_OPSTATE(done_with_log_incompat, UNSET_LOG_INCOMPAT) __XFS_IS_OPSTATE(using_logged_xattrs, USE_LARP) diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c index a11436579877d5..79a96558f739e3 100644 --- a/fs/xfs/xfs_qm_bhv.c +++ b/fs/xfs/xfs_qm_bhv.c @@ -135,3 +135,21 @@ xfs_qm_newmount( return 0; } + +/* + * If the sysadmin didn't provide any quota mount options, restore the quota + * accounting and enforcement state from the ondisk superblock. Only do this + * for metadir filesystems because this is a behavior change. + */ +void +xfs_qm_resume_quotaon( + struct xfs_mount *mp) +{ + if (!xfs_has_metadir(mp)) + return; + if (xfs_has_norecovery(mp)) + return; + + mp->m_qflags = mp->m_sb.sb_qflags & (XFS_ALL_QUOTA_ACCT | + XFS_ALL_QUOTA_ENFD); +} diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 645761997bf2d9..2d36d967380e7c 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -125,6 +125,7 @@ extern void xfs_qm_dqdetach(struct xfs_inode *); extern void xfs_qm_dqrele(struct xfs_dquot *); extern void xfs_qm_statvfs(struct xfs_inode *, struct kstatfs *); extern int xfs_qm_newmount(struct xfs_mount *, uint *, uint *); +void xfs_qm_resume_quotaon(struct xfs_mount *mp); extern void xfs_qm_mount_quotas(struct xfs_mount *); extern void xfs_qm_unmount(struct xfs_mount *); extern void xfs_qm_unmount_quotas(struct xfs_mount *); @@ -202,6 +203,7 @@ xfs_trans_reserve_quota_icreate(struct xfs_trans *tp, struct xfs_dquot *udqp, #define xfs_qm_dqrele(d) do { (d) = (d); } while(0) #define xfs_qm_statvfs(ip, s) do { } while(0) #define xfs_qm_newmount(mp, a, b) (0) +#define xfs_qm_resume_quotaon(mp) ((void)0) #define xfs_qm_mount_quotas(mp) #define xfs_qm_unmount(mp) #define xfs_qm_unmount_quotas(mp) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 3afeab6844680a..7a9cfdb66c0313 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -67,6 +67,9 @@ enum xfs_dax_mode { XFS_DAX_NEVER = 2, }; +/* Were quota mount options provided? Must use the upper 16 bits of qflags. */ +#define XFS_QFLAGS_MNTOPTS (1U << 31) + static void xfs_mount_set_dax_mode( struct xfs_mount *mp, @@ -1264,6 +1267,8 @@ xfs_fs_parse_param( int size = 0; int opt; + BUILD_BUG_ON(XFS_QFLAGS_MNTOPTS & XFS_MOUNT_QUOTA_ALL); + opt = fs_parse(fc, xfs_fs_parameters, param, &result); if (opt < 0) return opt; @@ -1341,32 +1346,39 @@ xfs_fs_parse_param( case Opt_noquota: parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT; parsing_mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD; + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_quota: case Opt_uquota: case Opt_usrquota: parsing_mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ENFD); + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_qnoenforce: case Opt_uqnoenforce: parsing_mp->m_qflags |= XFS_UQUOTA_ACCT; parsing_mp->m_qflags &= ~XFS_UQUOTA_ENFD; + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_pquota: case Opt_prjquota: parsing_mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ENFD); + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_pqnoenforce: parsing_mp->m_qflags |= XFS_PQUOTA_ACCT; parsing_mp->m_qflags &= ~XFS_PQUOTA_ENFD; + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_gquota: case Opt_grpquota: parsing_mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ENFD); + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_gqnoenforce: parsing_mp->m_qflags |= XFS_GQUOTA_ACCT; parsing_mp->m_qflags &= ~XFS_GQUOTA_ENFD; + parsing_mp->m_qflags |= XFS_QFLAGS_MNTOPTS; return 0; case Opt_discard: parsing_mp->m_features |= XFS_FEAT_DISCARD; @@ -1768,6 +1780,14 @@ xfs_fs_fill_super( if (xfs_has_parent(mp)) xfs_warn_experimental(mp, XFS_EXPERIMENTAL_PPTR); + /* + * If no quota mount options were provided, maybe we'll try to pick + * up the quota accounting and enforcement flags from the ondisk sb. + */ + if (!(mp->m_qflags & XFS_QFLAGS_MNTOPTS)) + xfs_set_resuming_quotaon(mp); + mp->m_qflags &= ~XFS_QFLAGS_MNTOPTS; + error = xfs_mountfs(mp); if (error) goto out_filestream_unmount; @@ -1954,6 +1974,8 @@ xfs_fs_reconfigure( int flags = fc->sb_flags; int error; + new_mp->m_qflags &= ~XFS_QFLAGS_MNTOPTS; + /* version 5 superblocks always support version counters. */ if (xfs_has_crc(mp)) fc->sb_flags |= SB_I_VERSION;