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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright (c) 2022-2024 Oracle.  All Rights Reserved.
  4  * Author: Darrick J. Wong <djwong@kernel.org>
  5  */
  6 #include "xfs.h"
  7 #include "xfs_fs.h"
  8 #include "xfs_shared.h"
  9 #include "xfs_format.h"
 10 #include "xfs_log_format.h"
 11 #include "xfs_trans.h"
 12 #include "xfs_trans_resv.h"
 13 #include "xfs_mount.h"
 14 #include "xfs_defer.h"
 15 #include "xfs_btree.h"
 16 #include "xfs_buf_mem.h"
 17 #include "xfs_btree_mem.h"
 18 #include "xfs_error.h"
 19 #include "scrub/scrub.h"
 20 #include "scrub/rcbag_btree.h"
 21 #include "scrub/rcbag.h"
 22 #include "scrub/trace.h"
 23 
 24 struct rcbag {
 25         struct xfs_mount        *mp;
 26         struct xfbtree          xfbtree;
 27         uint64_t                nr_items;
 28 };
 29 
 30 int
 31 rcbag_init(
 32         struct xfs_mount        *mp,
 33         struct xfs_buftarg      *btp,
 34         struct rcbag            **bagp)
 35 {
 36         struct rcbag            *bag;
 37         int                     error;
 38 
 39         bag = kzalloc(sizeof(struct rcbag), XCHK_GFP_FLAGS);
 40         if (!bag)
 41                 return -ENOMEM;
 42 
 43         bag->nr_items = 0;
 44         bag->mp = mp;
 45 
 46         error = rcbagbt_mem_init(mp, &bag->xfbtree, btp);
 47         if (error)
 48                 goto out_bag;
 49 
 50         *bagp = bag;
 51         return 0;
 52 
 53 out_bag:
 54         kfree(bag);
 55         return error;
 56 }
 57 
 58 void
 59 rcbag_free(
 60         struct rcbag            **bagp)
 61 {
 62         struct rcbag            *bag = *bagp;
 63 
 64         xfbtree_destroy(&bag->xfbtree);
 65         kfree(bag);
 66         *bagp = NULL;
 67 }
 68 
 69 /* Track an rmap in the refcount bag. */
 70 int
 71 rcbag_add(
 72         struct rcbag                    *bag,
 73         struct xfs_trans                *tp,
 74         const struct xfs_rmap_irec      *rmap)
 75 {
 76         struct rcbag_rec                bagrec;
 77         struct xfs_mount                *mp = bag->mp;
 78         struct xfs_btree_cur            *cur;
 79         int                             has;
 80         int                             error;
 81 
 82         cur = rcbagbt_mem_cursor(mp, tp, &bag->xfbtree);
 83         error = rcbagbt_lookup_eq(cur, rmap, &has);
 84         if (error)
 85                 goto out_cur;
 86 
 87         if (has) {
 88                 error = rcbagbt_get_rec(cur, &bagrec, &has);
 89                 if (error)
 90                         goto out_cur;
 91                 if (!has) {
 92                         error = -EFSCORRUPTED;
 93                         goto out_cur;
 94                 }
 95 
 96                 bagrec.rbg_refcount++;
 97                 error = rcbagbt_update(cur, &bagrec);
 98                 if (error)
 99                         goto out_cur;
100         } else {
101                 bagrec.rbg_startblock = rmap->rm_startblock;
102                 bagrec.rbg_blockcount = rmap->rm_blockcount;
103                 bagrec.rbg_refcount = 1;
104 
105                 error = rcbagbt_insert(cur, &bagrec, &has);
106                 if (error)
107                         goto out_cur;
108                 if (!has) {
109                         error = -EFSCORRUPTED;
110                         goto out_cur;
111                 }
112         }
113 
114         xfs_btree_del_cursor(cur, 0);
115 
116         error = xfbtree_trans_commit(&bag->xfbtree, tp);
117         if (error)
118                 return error;
119 
120         bag->nr_items++;
121         return 0;
122 
123 out_cur:
124         xfs_btree_del_cursor(cur, error);
125         xfbtree_trans_cancel(&bag->xfbtree, tp);
126         return error;
127 }
128 
129 /* Return the number of records in the bag. */
130 uint64_t
131 rcbag_count(
132         const struct rcbag      *rcbag)
133 {
134         return rcbag->nr_items;
135 }
136 
137 static inline uint32_t rcbag_rec_next_bno(const struct rcbag_rec *r)
138 {
139         return r->rbg_startblock + r->rbg_blockcount;
140 }
141 
142 /*
143  * Find the next block where the refcount changes, given the next rmap we
144  * looked at and the ones we're already tracking.
145  */
146 int
147 rcbag_next_edge(
148         struct rcbag                    *bag,
149         struct xfs_trans                *tp,
150         const struct xfs_rmap_irec      *next_rmap,
151         bool                            next_valid,
152         uint32_t                        *next_bnop)
153 {
154         struct rcbag_rec                bagrec;
155         struct xfs_mount                *mp = bag->mp;
156         struct xfs_btree_cur            *cur;
157         uint32_t                        next_bno = NULLAGBLOCK;
158         int                             has;
159         int                             error;
160 
161         if (next_valid)
162                 next_bno = next_rmap->rm_startblock;
163 
164         cur = rcbagbt_mem_cursor(mp, tp, &bag->xfbtree);
165         error = xfs_btree_goto_left_edge(cur);
166         if (error)
167                 goto out_cur;
168 
169         while (true) {
170                 error = xfs_btree_increment(cur, 0, &has);
171                 if (error)
172                         goto out_cur;
173                 if (!has)
174                         break;
175 
176                 error = rcbagbt_get_rec(cur, &bagrec, &has);
177                 if (error)
178                         goto out_cur;
179                 if (!has) {
180                         error = -EFSCORRUPTED;
181                         goto out_cur;
182                 }
183 
184                 next_bno = min(next_bno, rcbag_rec_next_bno(&bagrec));
185         }
186 
187         /*
188          * We should have found /something/ because either next_rrm is the next
189          * interesting rmap to look at after emitting this refcount extent, or
190          * there are other rmaps in rmap_bag contributing to the current
191          * sharing count.  But if something is seriously wrong, bail out.
192          */
193         if (next_bno == NULLAGBLOCK) {
194                 error = -EFSCORRUPTED;
195                 goto out_cur;
196         }
197 
198         xfs_btree_del_cursor(cur, 0);
199 
200         *next_bnop = next_bno;
201         return 0;
202 
203 out_cur:
204         xfs_btree_del_cursor(cur, error);
205         return error;
206 }
207 
208 /* Pop all refcount bag records that end at next_bno */
209 int
210 rcbag_remove_ending_at(
211         struct rcbag            *bag,
212         struct xfs_trans        *tp,
213         uint32_t                next_bno)
214 {
215         struct rcbag_rec        bagrec;
216         struct xfs_mount        *mp = bag->mp;
217         struct xfs_btree_cur    *cur;
218         int                     has;
219         int                     error;
220 
221         /* go to the right edge of the tree */
222         cur = rcbagbt_mem_cursor(mp, tp, &bag->xfbtree);
223         memset(&cur->bc_rec, 0xFF, sizeof(cur->bc_rec));
224         error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, &has);
225         if (error)
226                 goto out_cur;
227 
228         while (true) {
229                 error = xfs_btree_decrement(cur, 0, &has);
230                 if (error)
231                         goto out_cur;
232                 if (!has)
233                         break;
234 
235                 error = rcbagbt_get_rec(cur, &bagrec, &has);
236                 if (error)
237                         goto out_cur;
238                 if (!has) {
239                         error = -EFSCORRUPTED;
240                         goto out_cur;
241                 }
242 
243                 if (rcbag_rec_next_bno(&bagrec) != next_bno)
244                         continue;
245 
246                 error = xfs_btree_delete(cur, &has);
247                 if (error)
248                         goto out_cur;
249                 if (!has) {
250                         error = -EFSCORRUPTED;
251                         goto out_cur;
252                 }
253 
254                 bag->nr_items -= bagrec.rbg_refcount;
255         }
256 
257         xfs_btree_del_cursor(cur, 0);
258         return xfbtree_trans_commit(&bag->xfbtree, tp);
259 out_cur:
260         xfs_btree_del_cursor(cur, error);
261         xfbtree_trans_cancel(&bag->xfbtree, tp);
262         return error;
263 }
264 
265 /* Dump the rcbag. */
266 void
267 rcbag_dump(
268         struct rcbag                    *bag,
269         struct xfs_trans                *tp)
270 {
271         struct rcbag_rec                bagrec;
272         struct xfs_mount                *mp = bag->mp;
273         struct xfs_btree_cur            *cur;
274         unsigned long long              nr = 0;
275         int                             has;
276         int                             error;
277 
278         cur = rcbagbt_mem_cursor(mp, tp, &bag->xfbtree);
279         error = xfs_btree_goto_left_edge(cur);
280         if (error)
281                 goto out_cur;
282 
283         while (true) {
284                 error = xfs_btree_increment(cur, 0, &has);
285                 if (error)
286                         goto out_cur;
287                 if (!has)
288                         break;
289 
290                 error = rcbagbt_get_rec(cur, &bagrec, &has);
291                 if (error)
292                         goto out_cur;
293                 if (!has) {
294                         error = -EFSCORRUPTED;
295                         goto out_cur;
296                 }
297 
298                 xfs_err(bag->mp, "[%llu]: bno 0x%x fsbcount 0x%x refcount 0x%llx\n",
299                                 nr++,
300                                 (unsigned int)bagrec.rbg_startblock,
301                                 (unsigned int)bagrec.rbg_blockcount,
302                                 (unsigned long long)bagrec.rbg_refcount);
303         }
304 
305 out_cur:
306         xfs_btree_del_cursor(cur, error);
307 }
308 

~ [ 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