From: Darrick J. Wong <djwong@xxxxxxxxxx> 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 <djwong@xxxxxxxxxx> --- 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 3cf93eacc83462..8a926b24d4b5aa 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 5dffa8edc87684..acd3051751a6e3 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3192,12 +3192,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"));