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

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/rtbitmap.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) 2017-2023 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_trans_resv.h"
 11 #include "xfs_mount.h"
 12 #include "xfs_log_format.h"
 13 #include "xfs_trans.h"
 14 #include "xfs_rtbitmap.h"
 15 #include "xfs_inode.h"
 16 #include "xfs_bmap.h"
 17 #include "xfs_bit.h"
 18 #include "xfs_sb.h"
 19 #include "scrub/scrub.h"
 20 #include "scrub/common.h"
 21 #include "scrub/repair.h"
 22 #include "scrub/rtbitmap.h"
 23 
 24 /* Set us up with the realtime metadata locked. */
 25 int
 26 xchk_setup_rtbitmap(
 27         struct xfs_scrub        *sc)
 28 {
 29         struct xfs_mount        *mp = sc->mp;
 30         struct xchk_rtbitmap    *rtb;
 31         int                     error;
 32 
 33         rtb = kzalloc(sizeof(struct xchk_rtbitmap), XCHK_GFP_FLAGS);
 34         if (!rtb)
 35                 return -ENOMEM;
 36         sc->buf = rtb;
 37 
 38         if (xchk_could_repair(sc)) {
 39                 error = xrep_setup_rtbitmap(sc, rtb);
 40                 if (error)
 41                         return error;
 42         }
 43 
 44         error = xchk_trans_alloc(sc, rtb->resblks);
 45         if (error)
 46                 return error;
 47 
 48         error = xchk_install_live_inode(sc, sc->mp->m_rbmip);
 49         if (error)
 50                 return error;
 51 
 52         error = xchk_ino_dqattach(sc);
 53         if (error)
 54                 return error;
 55 
 56         xchk_ilock(sc, XFS_ILOCK_EXCL | XFS_ILOCK_RTBITMAP);
 57 
 58         /*
 59          * Now that we've locked the rtbitmap, we can't race with growfsrt
 60          * trying to expand the bitmap or change the size of the rt volume.
 61          * Hence it is safe to compute and check the geometry values.
 62          */
 63         if (mp->m_sb.sb_rblocks) {
 64                 rtb->rextents = xfs_rtb_to_rtx(mp, mp->m_sb.sb_rblocks);
 65                 rtb->rextslog = xfs_compute_rextslog(rtb->rextents);
 66                 rtb->rbmblocks = xfs_rtbitmap_blockcount(mp, rtb->rextents);
 67         }
 68         return 0;
 69 }
 70 
 71 /* Realtime bitmap. */
 72 
 73 /* Scrub a free extent record from the realtime bitmap. */
 74 STATIC int
 75 xchk_rtbitmap_rec(
 76         struct xfs_mount        *mp,
 77         struct xfs_trans        *tp,
 78         const struct xfs_rtalloc_rec *rec,
 79         void                    *priv)
 80 {
 81         struct xfs_scrub        *sc = priv;
 82         xfs_rtblock_t           startblock;
 83         xfs_filblks_t           blockcount;
 84 
 85         startblock = xfs_rtx_to_rtb(mp, rec->ar_startext);
 86         blockcount = xfs_rtx_to_rtb(mp, rec->ar_extcount);
 87 
 88         if (!xfs_verify_rtbext(mp, startblock, blockcount))
 89                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
 90         return 0;
 91 }
 92 
 93 /* Make sure the entire rtbitmap file is mapped with written extents. */
 94 STATIC int
 95 xchk_rtbitmap_check_extents(
 96         struct xfs_scrub        *sc)
 97 {
 98         struct xfs_bmbt_irec    map;
 99         struct xfs_iext_cursor  icur;
100         struct xfs_mount        *mp = sc->mp;
101         struct xfs_inode        *ip = sc->ip;
102         xfs_fileoff_t           off = 0;
103         xfs_fileoff_t           endoff;
104         int                     error = 0;
105 
106         /* Mappings may not cross or lie beyond EOF. */
107         endoff = XFS_B_TO_FSB(mp, ip->i_disk_size);
108         if (xfs_iext_lookup_extent(ip, &ip->i_df, endoff, &icur, &map)) {
109                 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, endoff);
110                 return 0;
111         }
112 
113         while (off < endoff) {
114                 int             nmap = 1;
115 
116                 if (xchk_should_terminate(sc, &error) ||
117                     (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
118                         break;
119 
120                 /* Make sure we have a written extent. */
121                 error = xfs_bmapi_read(ip, off, endoff - off, &map, &nmap,
122                                 XFS_DATA_FORK);
123                 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, off, &error))
124                         break;
125 
126                 if (nmap != 1 || !xfs_bmap_is_written_extent(&map)) {
127                         xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, off);
128                         break;
129                 }
130 
131                 off += map.br_blockcount;
132         }
133 
134         return error;
135 }
136 
137 /* Scrub the realtime bitmap. */
138 int
139 xchk_rtbitmap(
140         struct xfs_scrub        *sc)
141 {
142         struct xfs_mount        *mp = sc->mp;
143         struct xchk_rtbitmap    *rtb = sc->buf;
144         int                     error;
145 
146         /* Is sb_rextents correct? */
147         if (mp->m_sb.sb_rextents != rtb->rextents) {
148                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
149                 return 0;
150         }
151 
152         /* Is sb_rextslog correct? */
153         if (mp->m_sb.sb_rextslog != rtb->rextslog) {
154                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
155                 return 0;
156         }
157 
158         /*
159          * Is sb_rbmblocks large enough to handle the current rt volume?  In no
160          * case can we exceed 4bn bitmap blocks since the super field is a u32.
161          */
162         if (rtb->rbmblocks > U32_MAX) {
163                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
164                 return 0;
165         }
166         if (mp->m_sb.sb_rbmblocks != rtb->rbmblocks) {
167                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
168                 return 0;
169         }
170 
171         /* The bitmap file length must be aligned to an fsblock. */
172         if (mp->m_rbmip->i_disk_size & mp->m_blockmask) {
173                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
174                 return 0;
175         }
176 
177         /*
178          * Is the bitmap file itself large enough to handle the rt volume?
179          * growfsrt expands the bitmap file before updating sb_rextents, so the
180          * file can be larger than sb_rbmblocks.
181          */
182         if (mp->m_rbmip->i_disk_size < XFS_FSB_TO_B(mp, rtb->rbmblocks)) {
183                 xchk_ino_set_corrupt(sc, mp->m_rbmip->i_ino);
184                 return 0;
185         }
186 
187         /* Invoke the fork scrubber. */
188         error = xchk_metadata_inode_forks(sc);
189         if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
190                 return error;
191 
192         error = xchk_rtbitmap_check_extents(sc);
193         if (error || (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
194                 return error;
195 
196         error = xfs_rtalloc_query_all(mp, sc->tp, xchk_rtbitmap_rec, sc);
197         if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
198                 return error;
199 
200         return 0;
201 }
202 
203 /* xref check that the extent is not free in the rtbitmap */
204 void
205 xchk_xref_is_used_rt_space(
206         struct xfs_scrub        *sc,
207         xfs_rtblock_t           rtbno,
208         xfs_extlen_t            len)
209 {
210         xfs_rtxnum_t            startext;
211         xfs_rtxnum_t            endext;
212         bool                    is_free;
213         int                     error;
214 
215         if (xchk_skip_xref(sc->sm))
216                 return;
217 
218         startext = xfs_rtb_to_rtx(sc->mp, rtbno);
219         endext = xfs_rtb_to_rtx(sc->mp, rtbno + len - 1);
220         xfs_ilock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
221         error = xfs_rtalloc_extent_is_free(sc->mp, sc->tp, startext,
222                         endext - startext + 1, &is_free);
223         if (!xchk_should_check_xref(sc, &error, NULL))
224                 goto out_unlock;
225         if (is_free)
226                 xchk_ino_xref_set_corrupt(sc, sc->mp->m_rbmip->i_ino);
227 out_unlock:
228         xfs_iunlock(sc->mp->m_rbmip, XFS_ILOCK_SHARED | XFS_ILOCK_RTBITMAP);
229 }
230 

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