aboutsummaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_qm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2024-12-20 14:09:45 +0100
committerTakashi Iwai <tiwai@suse.de>2024-12-20 14:09:45 +0100
commit8cbd01ba9c38eb16f3a572300da486ac544519b7 (patch)
treee9a800bcb96bf8e937ddf0d420514dccbc6c1a75 /fs/xfs/xfs_qm.c
parent66a0a2b0473c39ae85c44628d14e4366fdc0aa0d (diff)
parent32c9c06adb5b157ef259233775a063a43746d699 (diff)
downloadlinux-8cbd01ba9c38eb16f3a572300da486ac544519b7.tar.gz
linux-8cbd01ba9c38eb16f3a572300da486ac544519b7.tar.bz2
linux-8cbd01ba9c38eb16f3a572300da486ac544519b7.zip
Merge tag 'asoc-fix-v6.13-rc3' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Fixes for v6.13 A mix of quirks and small fixes, nothing too major anywhere.
Diffstat (limited to 'fs/xfs/xfs_qm.c')
-rw-r--r--fs/xfs/xfs_qm.c102
1 files changed, 73 insertions, 29 deletions
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 61ee110b47d7..dc8b1010d4d3 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -148,17 +148,29 @@ xfs_qm_dqpurge(
* We don't care about getting disk errors here. We need
* to purge this dquot anyway, so we go ahead regardless.
*/
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
+ if (error == -EAGAIN) {
+ xfs_dqfunlock(dqp);
+ dqp->q_flags &= ~XFS_DQFLAG_FREEING;
+ goto out_unlock;
+ }
+ if (!bp)
+ goto out_funlock;
+
+ /*
+ * dqflush completes dqflock on error, and the bwrite ioend
+ * does it on success.
+ */
+ error = xfs_qm_dqflush(dqp, bp);
if (!error) {
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
- } else if (error == -EAGAIN) {
- dqp->q_flags &= ~XFS_DQFLAG_FREEING;
- goto out_unlock;
}
xfs_dqflock(dqp);
}
+ xfs_dquot_detach_buf(dqp);
+out_funlock:
ASSERT(atomic_read(&dqp->q_pincount) == 0);
ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
@@ -241,6 +253,10 @@ xfs_qm_destroy_quotainos(
xfs_irele(qi->qi_pquotaip);
qi->qi_pquotaip = NULL;
}
+ if (qi->qi_dirip) {
+ xfs_irele(qi->qi_dirip);
+ qi->qi_dirip = NULL;
+ }
}
/*
@@ -490,7 +506,17 @@ xfs_qm_dquot_isolate(
/* we have to drop the LRU lock to flush the dquot */
spin_unlock(&lru->lock);
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
+ if (!bp || error == -EAGAIN) {
+ xfs_dqfunlock(dqp);
+ goto out_unlock_dirty;
+ }
+
+ /*
+ * dqflush completes dqflock on error, and the delwri ioend
+ * does it on success.
+ */
+ error = xfs_qm_dqflush(dqp, bp);
if (error)
goto out_unlock_dirty;
@@ -498,6 +524,8 @@ xfs_qm_dquot_isolate(
xfs_buf_relse(bp);
goto out_unlock_dirty;
}
+
+ xfs_dquot_detach_buf(dqp);
xfs_dqfunlock(dqp);
/*
@@ -646,8 +674,7 @@ xfs_qm_init_timelimits(
static int
xfs_qm_load_metadir_qinos(
struct xfs_mount *mp,
- struct xfs_quotainfo *qi,
- struct xfs_inode **dpp)
+ struct xfs_quotainfo *qi)
{
struct xfs_trans *tp;
int error;
@@ -656,7 +683,7 @@ xfs_qm_load_metadir_qinos(
if (error)
return error;
- error = xfs_dqinode_load_parent(tp, dpp);
+ error = xfs_dqinode_load_parent(tp, &qi->qi_dirip);
if (error == -ENOENT) {
/* no quota dir directory, but we'll create one later */
error = 0;
@@ -666,21 +693,21 @@ xfs_qm_load_metadir_qinos(
goto out_trans;
if (XFS_IS_UQUOTA_ON(mp)) {
- error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_USER,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, 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,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, 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,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_PROJ,
&qi->qi_pquotaip);
if (error && error != -ENOENT)
goto out_trans;
@@ -696,34 +723,40 @@ out_trans:
STATIC int
xfs_qm_create_metadir_qinos(
struct xfs_mount *mp,
- struct xfs_quotainfo *qi,
- struct xfs_inode **dpp)
+ struct xfs_quotainfo *qi)
{
int error;
- if (!*dpp) {
- error = xfs_dqinode_mkdir_parent(mp, dpp);
+ if (!qi->qi_dirip) {
+ error = xfs_dqinode_mkdir_parent(mp, &qi->qi_dirip);
if (error && error != -EEXIST)
return error;
+ /*
+ * If the /quotas dirent points to an inode that isn't
+ * loadable, qi_dirip will be NULL but mkdir_parent will return
+ * -EEXIST. In this case the metadir is corrupt, so bail out.
+ */
+ if (XFS_IS_CORRUPT(mp, qi->qi_dirip == NULL))
+ return -EFSCORRUPTED;
}
if (XFS_IS_UQUOTA_ON(mp) && !qi->qi_uquotaip) {
- error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_USER,
- &qi->qi_uquotaip);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ 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);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ 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);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ XFS_DQTYPE_PROJ, &qi->qi_pquotaip);
if (error)
return error;
}
@@ -768,7 +801,6 @@ 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)) {
@@ -777,20 +809,22 @@ xfs_qm_init_metadir_qinos(
return error;
}
- error = xfs_qm_load_metadir_qinos(mp, qi, &dp);
+ error = xfs_qm_load_metadir_qinos(mp, qi);
if (error)
goto out_err;
- error = xfs_qm_create_metadir_qinos(mp, qi, &dp);
+ error = xfs_qm_create_metadir_qinos(mp, qi);
if (error)
goto out_err;
- xfs_irele(dp);
+ /* The only user of the quota dir inode is online fsck */
+#if !IS_ENABLED(CONFIG_XFS_ONLINE_SCRUB)
+ xfs_irele(qi->qi_dirip);
+ qi->qi_dirip = NULL;
+#endif
return 0;
out_err:
xfs_qm_destroy_quotainos(mp->m_quotainfo);
- if (dp)
- xfs_irele(dp);
return error;
}
@@ -1304,6 +1338,10 @@ xfs_qm_quotacheck_dqadjust(
return error;
}
+ error = xfs_dquot_attach_buf(NULL, dqp);
+ if (error)
+ return error;
+
trace_xfs_dqadjust(dqp);
/*
@@ -1486,11 +1524,17 @@ xfs_qm_flush_one(
goto out_unlock;
}
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
if (error)
goto out_unlock;
+ if (!bp) {
+ error = -EFSCORRUPTED;
+ goto out_unlock;
+ }
- xfs_buf_delwri_queue(bp, buffer_list);
+ error = xfs_qm_dqflush(dqp, bp);
+ if (!error)
+ xfs_buf_delwri_queue(bp, buffer_list);
xfs_buf_relse(bp);
out_unlock:
xfs_dqunlock(dqp);