~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/dqiterate.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/xfs/scrub/dqiterate.c (Version linux-6.12-rc7) and /fs/xfs/scrub/dqiterate.c (Version linux-6.10.14)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*                                                  2 /*
  3  * Copyright (C) 2023 Oracle.  All Rights Rese      3  * Copyright (C) 2023 Oracle.  All Rights Reserved.
  4  * Author: Darrick J. Wong <djwong@kernel.org>      4  * Author: Darrick J. Wong <djwong@kernel.org>
  5  */                                                 5  */
  6 #include "xfs.h"                                    6 #include "xfs.h"
  7 #include "xfs_fs.h"                                 7 #include "xfs_fs.h"
  8 #include "xfs_shared.h"                             8 #include "xfs_shared.h"
  9 #include "xfs_bit.h"                                9 #include "xfs_bit.h"
 10 #include "xfs_format.h"                            10 #include "xfs_format.h"
 11 #include "xfs_trans_resv.h"                        11 #include "xfs_trans_resv.h"
 12 #include "xfs_mount.h"                             12 #include "xfs_mount.h"
 13 #include "xfs_log_format.h"                        13 #include "xfs_log_format.h"
 14 #include "xfs_trans.h"                             14 #include "xfs_trans.h"
 15 #include "xfs_inode.h"                             15 #include "xfs_inode.h"
 16 #include "xfs_quota.h"                             16 #include "xfs_quota.h"
 17 #include "xfs_qm.h"                                17 #include "xfs_qm.h"
 18 #include "xfs_bmap.h"                              18 #include "xfs_bmap.h"
 19 #include "scrub/scrub.h"                           19 #include "scrub/scrub.h"
 20 #include "scrub/common.h"                          20 #include "scrub/common.h"
 21 #include "scrub/quota.h"                           21 #include "scrub/quota.h"
 22 #include "scrub/trace.h"                           22 #include "scrub/trace.h"
 23                                                    23 
 24 /* Initialize a dquot iteration cursor. */         24 /* Initialize a dquot iteration cursor. */
 25 void                                               25 void
 26 xchk_dqiter_init(                                  26 xchk_dqiter_init(
 27         struct xchk_dqiter      *cursor,           27         struct xchk_dqiter      *cursor,
 28         struct xfs_scrub        *sc,               28         struct xfs_scrub        *sc,
 29         xfs_dqtype_t            dqtype)            29         xfs_dqtype_t            dqtype)
 30 {                                                  30 {
 31         cursor->sc = sc;                           31         cursor->sc = sc;
 32         cursor->bmap.br_startoff = NULLFILEOFF     32         cursor->bmap.br_startoff = NULLFILEOFF;
 33         cursor->dqtype = dqtype & XFS_DQTYPE_R     33         cursor->dqtype = dqtype & XFS_DQTYPE_REC_MASK;
 34         cursor->quota_ip = xfs_quota_inode(sc-     34         cursor->quota_ip = xfs_quota_inode(sc->mp, cursor->dqtype);
 35         cursor->id = 0;                            35         cursor->id = 0;
 36 }                                                  36 }
 37                                                    37 
 38 /*                                                 38 /*
 39  * Ensure that the cached data fork mapping fo     39  * Ensure that the cached data fork mapping for the dqiter cursor is fresh and
 40  * covers the dquot pointed to by the scan cur     40  * covers the dquot pointed to by the scan cursor.
 41  */                                                41  */
 42 STATIC int                                         42 STATIC int
 43 xchk_dquot_iter_revalidate_bmap(                   43 xchk_dquot_iter_revalidate_bmap(
 44         struct xchk_dqiter      *cursor)           44         struct xchk_dqiter      *cursor)
 45 {                                                  45 {
 46         struct xfs_quotainfo    *qi = cursor->     46         struct xfs_quotainfo    *qi = cursor->sc->mp->m_quotainfo;
 47         struct xfs_ifork        *ifp = xfs_ifo     47         struct xfs_ifork        *ifp = xfs_ifork_ptr(cursor->quota_ip,
 48                                                    48                                                                 XFS_DATA_FORK);
 49         xfs_fileoff_t           fileoff;           49         xfs_fileoff_t           fileoff;
 50         xfs_dqid_t              this_id = curs     50         xfs_dqid_t              this_id = cursor->id;
 51         int                     nmaps = 1;         51         int                     nmaps = 1;
 52         int                     error;             52         int                     error;
 53                                                    53 
 54         fileoff = this_id / qi->qi_dqperchunk;     54         fileoff = this_id / qi->qi_dqperchunk;
 55                                                    55 
 56         /*                                         56         /*
 57          * If we have a mapping for cursor->id     57          * If we have a mapping for cursor->id and it's still fresh, there's
 58          * no need to reread the bmbt.             58          * no need to reread the bmbt.
 59          */                                        59          */
 60         if (cursor->bmap.br_startoff != NULLFI     60         if (cursor->bmap.br_startoff != NULLFILEOFF &&
 61             cursor->if_seq == ifp->if_seq &&       61             cursor->if_seq == ifp->if_seq &&
 62             cursor->bmap.br_startoff + cursor-     62             cursor->bmap.br_startoff + cursor->bmap.br_blockcount > fileoff)
 63                 return 0;                          63                 return 0;
 64                                                    64 
 65         /* Look up the data fork mapping for t     65         /* Look up the data fork mapping for the dquot id of interest. */
 66         error = xfs_bmapi_read(cursor->quota_i     66         error = xfs_bmapi_read(cursor->quota_ip, fileoff,
 67                         XFS_MAX_FILEOFF - file     67                         XFS_MAX_FILEOFF - fileoff, &cursor->bmap, &nmaps, 0);
 68         if (error)                                 68         if (error)
 69                 return error;                      69                 return error;
 70         if (!nmaps) {                              70         if (!nmaps) {
 71                 ASSERT(nmaps > 0);                 71                 ASSERT(nmaps > 0);
 72                 return -EFSCORRUPTED;              72                 return -EFSCORRUPTED;
 73         }                                          73         }
 74         if (cursor->bmap.br_startoff > fileoff     74         if (cursor->bmap.br_startoff > fileoff) {
 75                 ASSERT(cursor->bmap.br_startof     75                 ASSERT(cursor->bmap.br_startoff == fileoff);
 76                 return -EFSCORRUPTED;              76                 return -EFSCORRUPTED;
 77         }                                          77         }
 78                                                    78 
 79         cursor->if_seq = ifp->if_seq;              79         cursor->if_seq = ifp->if_seq;
 80         trace_xchk_dquot_iter_revalidate_bmap(     80         trace_xchk_dquot_iter_revalidate_bmap(cursor, cursor->id);
 81         return 0;                                  81         return 0;
 82 }                                                  82 }
 83                                                    83 
 84 /* Advance the dqiter cursor to the next non-s     84 /* Advance the dqiter cursor to the next non-sparse region of the quota file. */
 85 STATIC int                                         85 STATIC int
 86 xchk_dquot_iter_advance_bmap(                      86 xchk_dquot_iter_advance_bmap(
 87         struct xchk_dqiter      *cursor,           87         struct xchk_dqiter      *cursor,
 88         uint64_t                *next_ondisk_i     88         uint64_t                *next_ondisk_id)
 89 {                                                  89 {
 90         struct xfs_quotainfo    *qi = cursor->     90         struct xfs_quotainfo    *qi = cursor->sc->mp->m_quotainfo;
 91         struct xfs_ifork        *ifp = xfs_ifo     91         struct xfs_ifork        *ifp = xfs_ifork_ptr(cursor->quota_ip,
 92                                                    92                                                                 XFS_DATA_FORK);
 93         xfs_fileoff_t           fileoff;           93         xfs_fileoff_t           fileoff;
 94         uint64_t                next_id;           94         uint64_t                next_id;
 95         int                     nmaps = 1;         95         int                     nmaps = 1;
 96         int                     error;             96         int                     error;
 97                                                    97 
 98         /* Find the dquot id for the next non-     98         /* Find the dquot id for the next non-hole mapping. */
 99         do {                                       99         do {
100                 fileoff = cursor->bmap.br_star    100                 fileoff = cursor->bmap.br_startoff + cursor->bmap.br_blockcount;
101                 if (fileoff > XFS_DQ_ID_MAX /     101                 if (fileoff > XFS_DQ_ID_MAX / qi->qi_dqperchunk) {
102                         /* The hole goes beyon    102                         /* The hole goes beyond the max dquot id, we're done */
103                         *next_ondisk_id = -1UL    103                         *next_ondisk_id = -1ULL;
104                         return 0;                 104                         return 0;
105                 }                                 105                 }
106                                                   106 
107                 error = xfs_bmapi_read(cursor-    107                 error = xfs_bmapi_read(cursor->quota_ip, fileoff,
108                                 XFS_MAX_FILEOF    108                                 XFS_MAX_FILEOFF - fileoff, &cursor->bmap,
109                                 &nmaps, 0);       109                                 &nmaps, 0);
110                 if (error)                        110                 if (error)
111                         return error;             111                         return error;
112                 if (!nmaps) {                     112                 if (!nmaps) {
113                         /* Must have reached t    113                         /* Must have reached the end of the mappings. */
114                         *next_ondisk_id = -1UL    114                         *next_ondisk_id = -1ULL;
115                         return 0;                 115                         return 0;
116                 }                                 116                 }
117                 if (cursor->bmap.br_startoff >    117                 if (cursor->bmap.br_startoff > fileoff) {
118                         ASSERT(cursor->bmap.br    118                         ASSERT(cursor->bmap.br_startoff == fileoff);
119                         return -EFSCORRUPTED;     119                         return -EFSCORRUPTED;
120                 }                                 120                 }
121         } while (!xfs_bmap_is_real_extent(&cur    121         } while (!xfs_bmap_is_real_extent(&cursor->bmap));
122                                                   122 
123         next_id = cursor->bmap.br_startoff * q    123         next_id = cursor->bmap.br_startoff * qi->qi_dqperchunk;
124         if (next_id > XFS_DQ_ID_MAX) {            124         if (next_id > XFS_DQ_ID_MAX) {
125                 /* The hole goes beyond the ma    125                 /* The hole goes beyond the max dquot id, we're done */
126                 *next_ondisk_id = -1ULL;          126                 *next_ondisk_id = -1ULL;
127                 return 0;                         127                 return 0;
128         }                                         128         }
129                                                   129 
130         /* Propose jumping forward to the dquo    130         /* Propose jumping forward to the dquot in the next allocated block. */
131         *next_ondisk_id = next_id;                131         *next_ondisk_id = next_id;
132         cursor->if_seq = ifp->if_seq;             132         cursor->if_seq = ifp->if_seq;
133         trace_xchk_dquot_iter_advance_bmap(cur    133         trace_xchk_dquot_iter_advance_bmap(cursor, *next_ondisk_id);
134         return 0;                                 134         return 0;
135 }                                                 135 }
136                                                   136 
137 /*                                                137 /*
138  * Find the id of the next highest incore dquo    138  * Find the id of the next highest incore dquot.  Normally this will correspond
139  * exactly with the quota file block mappings,    139  * exactly with the quota file block mappings, but repair might have erased a
140  * mapping because it was crosslinked; in that    140  * mapping because it was crosslinked; in that case, we need to re-allocate the
141  * space so that we can reset q_blkno.            141  * space so that we can reset q_blkno.
142  */                                               142  */
143 STATIC void                                       143 STATIC void
144 xchk_dquot_iter_advance_incore(                   144 xchk_dquot_iter_advance_incore(
145         struct xchk_dqiter      *cursor,          145         struct xchk_dqiter      *cursor,
146         uint64_t                *next_incore_i    146         uint64_t                *next_incore_id)
147 {                                                 147 {
148         struct xfs_quotainfo    *qi = cursor->    148         struct xfs_quotainfo    *qi = cursor->sc->mp->m_quotainfo;
149         struct radix_tree_root  *tree = xfs_dq    149         struct radix_tree_root  *tree = xfs_dquot_tree(qi, cursor->dqtype);
150         struct xfs_dquot        *dq;              150         struct xfs_dquot        *dq;
151         unsigned int            nr_found;         151         unsigned int            nr_found;
152                                                   152 
153         *next_incore_id = -1ULL;                  153         *next_incore_id = -1ULL;
154                                                   154 
155         mutex_lock(&qi->qi_tree_lock);            155         mutex_lock(&qi->qi_tree_lock);
156         nr_found = radix_tree_gang_lookup(tree    156         nr_found = radix_tree_gang_lookup(tree, (void **)&dq, cursor->id, 1);
157         if (nr_found)                             157         if (nr_found)
158                 *next_incore_id = dq->q_id;       158                 *next_incore_id = dq->q_id;
159         mutex_unlock(&qi->qi_tree_lock);          159         mutex_unlock(&qi->qi_tree_lock);
160                                                   160 
161         trace_xchk_dquot_iter_advance_incore(c    161         trace_xchk_dquot_iter_advance_incore(cursor, *next_incore_id);
162 }                                                 162 }
163                                                   163 
164 /*                                                164 /*
165  * Walk all incore dquots of this filesystem.     165  * Walk all incore dquots of this filesystem.  Caller must set *@cursorp to
166  * zero before the first call, and must not ho    166  * zero before the first call, and must not hold the quota file ILOCK.
167  * Returns 1 and a valid *@dqpp; 0 and *@dqpp     167  * Returns 1 and a valid *@dqpp; 0 and *@dqpp == NULL when there are no more
168  * dquots to iterate; or a negative errno.        168  * dquots to iterate; or a negative errno.
169  */                                               169  */
170 int                                               170 int
171 xchk_dquot_iter(                                  171 xchk_dquot_iter(
172         struct xchk_dqiter      *cursor,          172         struct xchk_dqiter      *cursor,
173         struct xfs_dquot        **dqpp)           173         struct xfs_dquot        **dqpp)
174 {                                                 174 {
175         struct xfs_mount        *mp = cursor->    175         struct xfs_mount        *mp = cursor->sc->mp;
176         struct xfs_dquot        *dq = NULL;       176         struct xfs_dquot        *dq = NULL;
177         uint64_t                next_ondisk, n    177         uint64_t                next_ondisk, next_incore = -1ULL;
178         unsigned int            lock_mode;        178         unsigned int            lock_mode;
179         int                     error = 0;        179         int                     error = 0;
180                                                   180 
181         if (cursor->id > XFS_DQ_ID_MAX)           181         if (cursor->id > XFS_DQ_ID_MAX)
182                 return 0;                         182                 return 0;
183         next_ondisk = cursor->id;                 183         next_ondisk = cursor->id;
184                                                   184 
185         /* Revalidate and/or advance the curso    185         /* Revalidate and/or advance the cursor. */
186         lock_mode = xfs_ilock_data_map_shared(    186         lock_mode = xfs_ilock_data_map_shared(cursor->quota_ip);
187         error = xchk_dquot_iter_revalidate_bma    187         error = xchk_dquot_iter_revalidate_bmap(cursor);
188         if (!error && !xfs_bmap_is_real_extent    188         if (!error && !xfs_bmap_is_real_extent(&cursor->bmap))
189                 error = xchk_dquot_iter_advanc    189                 error = xchk_dquot_iter_advance_bmap(cursor, &next_ondisk);
190         xfs_iunlock(cursor->quota_ip, lock_mod    190         xfs_iunlock(cursor->quota_ip, lock_mode);
191         if (error)                                191         if (error)
192                 return error;                     192                 return error;
193                                                   193 
194         if (next_ondisk > cursor->id)             194         if (next_ondisk > cursor->id)
195                 xchk_dquot_iter_advance_incore    195                 xchk_dquot_iter_advance_incore(cursor, &next_incore);
196                                                   196 
197         /* Pick the next dquot in the sequence    197         /* Pick the next dquot in the sequence and return it. */
198         cursor->id = min(next_ondisk, next_inc    198         cursor->id = min(next_ondisk, next_incore);
199         if (cursor->id > XFS_DQ_ID_MAX)           199         if (cursor->id > XFS_DQ_ID_MAX)
200                 return 0;                         200                 return 0;
201                                                   201 
202         trace_xchk_dquot_iter(cursor, cursor->    202         trace_xchk_dquot_iter(cursor, cursor->id);
203                                                   203 
204         error = xfs_qm_dqget(mp, cursor->id, c    204         error = xfs_qm_dqget(mp, cursor->id, cursor->dqtype, false, &dq);
205         if (error)                                205         if (error)
206                 return error;                     206                 return error;
207                                                   207 
208         cursor->id = dq->q_id + 1;                208         cursor->id = dq->q_id + 1;
209         *dqpp = dq;                               209         *dqpp = dq;
210         return 1;                                 210         return 1;
211 }                                                 211 }
212                                                   212 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php