GNU Linux-libre 4.19.264-gnu1
[releases.git] / fs / xfs / scrub / quota.c
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 }