1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_defer.h" 13 #include "xfs_btree.h" 14 #include "xfs_bit.h" 15 #include "xfs_log_format.h" 16 #include "xfs_trans.h" 17 #include "xfs_sb.h" 18 #include "xfs_inode.h" 19 #include "xfs_inode_fork.h" 20 #include "xfs_alloc.h" 21 #include "xfs_bmap.h" 22 #include "xfs_quota.h" 23 #include "xfs_qm.h" 24 #include "xfs_dquot.h" 25 #include "xfs_dquot_item.h" 26 #include "scrub/xfs_scrub.h" 27 #include "scrub/scrub.h" 28 #include "scrub/common.h" 29 #include "scrub/trace.h" 30 31 /* Convert a scrub type code to a DQ flag, or return 0 if error. */ 32 static inline uint 33 xchk_quota_to_dqtype( 34 struct xfs_scrub *sc) 35 { 36 switch (sc->sm->sm_type) { 37 case XFS_SCRUB_TYPE_UQUOTA: 38 return XFS_DQ_USER; 39 case XFS_SCRUB_TYPE_GQUOTA: 40 return XFS_DQ_GROUP; 41 case XFS_SCRUB_TYPE_PQUOTA: 42 return XFS_DQ_PROJ; 43 default: 44 return 0; 45 } 46 } 47 48 /* Set us up to scrub a quota. */ 49 int 50 xchk_setup_quota( 51 struct xfs_scrub *sc, 52 struct xfs_inode *ip) 53 { 54 uint dqtype; 55 int error; 56 57 if (!XFS_IS_QUOTA_RUNNING(sc->mp) || !XFS_IS_QUOTA_ON(sc->mp)) 58 return -ENOENT; 59 60 dqtype = xchk_quota_to_dqtype(sc); 61 if (dqtype == 0) 62 return -EINVAL; 63 sc->has_quotaofflock = true; 64 mutex_lock(&sc->mp->m_quotainfo->qi_quotaofflock); 65 if (!xfs_this_quota_on(sc->mp, dqtype)) 66 return -ENOENT; 67 error = xchk_setup_fs(sc, ip); 68 if (error) 69 return error; 70 sc->ip = xfs_quota_inode(sc->mp, dqtype); 71 xfs_ilock(sc->ip, XFS_ILOCK_EXCL); 72 sc->ilock_flags = XFS_ILOCK_EXCL; 73 return 0; 74 } 75 76 /* Quotas. */ 77 78 struct xchk_quota_info { 79 struct xfs_scrub *sc; 80 xfs_dqid_t last_id; 81 }; 82 83 /* Scrub the fields in an individual quota item. */ 84 STATIC int 85 xchk_quota_item( 86 struct xfs_dquot *dq, 87 uint dqtype, 88 void *priv) 89 { 90 struct xchk_quota_info *sqi = priv; 91 struct xfs_scrub *sc = sqi->sc; 92 struct xfs_mount *mp = sc->mp; 93 struct xfs_disk_dquot *d = &dq->q_core; 94 struct xfs_quotainfo *qi = mp->m_quotainfo; 95 xfs_fileoff_t offset; 96 unsigned long long bsoft; 97 unsigned long long isoft; 98 unsigned long long rsoft; 99 unsigned long long bhard; 100 unsigned long long ihard; 101 unsigned long long rhard; 102 unsigned long long bcount; 103 unsigned long long icount; 104 unsigned long long rcount; 105 xfs_ino_t fs_icount; 106 xfs_dqid_t id = be32_to_cpu(d->d_id); 107 108 /* 109 * Except for the root dquot, the actual dquot we got must either have 110 * the same or higher id as we saw before. 111 */ 112 offset = id / qi->qi_dqperchunk; 113 if (id && id <= sqi->last_id) 114 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 115 116 sqi->last_id = id; 117 118 /* Did we get the dquot type we wanted? */ 119 if (dqtype != (d->d_flags & XFS_DQ_ALLTYPES)) 120 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 121 122 if (d->d_pad0 != cpu_to_be32(0) || d->d_pad != cpu_to_be16(0)) 123 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 124 125 /* Check the limits. */ 126 bhard = be64_to_cpu(d->d_blk_hardlimit); 127 ihard = be64_to_cpu(d->d_ino_hardlimit); 128 rhard = be64_to_cpu(d->d_rtb_hardlimit); 129 130 bsoft = be64_to_cpu(d->d_blk_softlimit); 131 isoft = be64_to_cpu(d->d_ino_softlimit); 132 rsoft = be64_to_cpu(d->d_rtb_softlimit); 133 134 /* 135 * Warn if the hard limits are larger than the fs. 136 * Administrators can do this, though in production this seems 137 * suspect, which is why we flag it for review. 138 * 139 * Complain about corruption if the soft limit is greater than 140 * the hard limit. 141 */ 142 if (bhard > mp->m_sb.sb_dblocks) 143 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 144 if (bsoft > bhard) 145 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 146 147 if (ihard > mp->m_maxicount) 148 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 149 if (isoft > ihard) 150 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 151 152 if (rhard > mp->m_sb.sb_rblocks) 153 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 154 if (rsoft > rhard) 155 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 156 157 /* Check the resource counts. */ 158 bcount = be64_to_cpu(d->d_bcount); 159 icount = be64_to_cpu(d->d_icount); 160 rcount = be64_to_cpu(d->d_rtbcount); 161 fs_icount = percpu_counter_sum(&mp->m_icount); 162 163 /* 164 * Check that usage doesn't exceed physical limits. However, on 165 * a reflink filesystem we're allowed to exceed physical space 166 * if there are no quota limits. 167 */ 168 if (xfs_sb_version_hasreflink(&mp->m_sb)) { 169 if (mp->m_sb.sb_dblocks < bcount) 170 xchk_fblock_set_warning(sc, XFS_DATA_FORK, 171 offset); 172 } else { 173 if (mp->m_sb.sb_dblocks < bcount) 174 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 175 offset); 176 } 177 if (icount > fs_icount || rcount > mp->m_sb.sb_rblocks) 178 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 179 180 /* 181 * We can violate the hard limits if the admin suddenly sets a 182 * lower limit than the actual usage. However, we flag it for 183 * admin review. 184 */ 185 if (id != 0 && bhard != 0 && bcount > bhard) 186 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 187 if (id != 0 && ihard != 0 && icount > ihard) 188 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 189 if (id != 0 && rhard != 0 && rcount > rhard) 190 xchk_fblock_set_warning(sc, XFS_DATA_FORK, offset); 191 192 return 0; 193 } 194 195 /* Check the quota's data fork. */ 196 STATIC int 197 xchk_quota_data_fork( 198 struct xfs_scrub *sc) 199 { 200 struct xfs_bmbt_irec irec = { 0 }; 201 struct xfs_iext_cursor icur; 202 struct xfs_quotainfo *qi = sc->mp->m_quotainfo; 203 struct xfs_ifork *ifp; 204 xfs_fileoff_t max_dqid_off; 205 int error = 0; 206 207 /* Invoke the fork scrubber. */ 208 error = xchk_metadata_inode_forks(sc); 209 if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 210 return error; 211 212 /* Check for data fork problems that apply only to quota files. */ 213 max_dqid_off = ((xfs_dqid_t)-1) / qi->qi_dqperchunk; 214 ifp = XFS_IFORK_PTR(sc->ip, XFS_DATA_FORK); 215 for_each_xfs_iext(ifp, &icur, &irec) { 216 if (xchk_should_terminate(sc, &error)) 217 break; 218 /* 219 * delalloc extents or blocks mapped above the highest 220 * quota id shouldn't happen. 221 */ 222 if (isnullstartblock(irec.br_startblock) || 223 irec.br_startoff > max_dqid_off || 224 irec.br_startoff + irec.br_blockcount - 1 > max_dqid_off) { 225 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 226 irec.br_startoff); 227 break; 228 } 229 } 230 231 return error; 232 } 233 234 /* Scrub all of a quota type's items. */ 235 int 236 xchk_quota( 237 struct xfs_scrub *sc) 238 { 239 struct xchk_quota_info sqi; 240 struct xfs_mount *mp = sc->mp; 241 struct xfs_quotainfo *qi = mp->m_quotainfo; 242 uint dqtype; 243 int error = 0; 244 245 dqtype = xchk_quota_to_dqtype(sc); 246 247 /* Look for problem extents. */ 248 error = xchk_quota_data_fork(sc); 249 if (error) 250 goto out; 251 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 252 goto out; 253 254 /* 255 * Check all the quota items. Now that we've checked the quota inode 256 * data fork we have to drop ILOCK_EXCL to use the regular dquot 257 * functions. 258 */ 259 xfs_iunlock(sc->ip, sc->ilock_flags); 260 sc->ilock_flags = 0; 261 sqi.sc = sc; 262 sqi.last_id = 0; 263 error = xfs_qm_dqiterate(mp, dqtype, xchk_quota_item, &sqi); 264 sc->ilock_flags = XFS_ILOCK_EXCL; 265 xfs_ilock(sc->ip, sc->ilock_flags); 266 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 267 sqi.last_id * qi->qi_dqperchunk, &error)) 268 goto out; 269 270 out: 271 return error; 272 } 273