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

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/rtbitmap_repair.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) 2020-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_btree.h"
 13 #include "xfs_log_format.h"
 14 #include "xfs_trans.h"
 15 #include "xfs_inode.h"
 16 #include "xfs_bit.h"
 17 #include "xfs_bmap.h"
 18 #include "xfs_bmap_btree.h"
 19 #include "scrub/scrub.h"
 20 #include "scrub/common.h"
 21 #include "scrub/trace.h"
 22 #include "scrub/repair.h"
 23 #include "scrub/xfile.h"
 24 #include "scrub/rtbitmap.h"
 25 
 26 /* Set up to repair the realtime bitmap file metadata. */
 27 int
 28 xrep_setup_rtbitmap(
 29         struct xfs_scrub        *sc,
 30         struct xchk_rtbitmap    *rtb)
 31 {
 32         struct xfs_mount        *mp = sc->mp;
 33         unsigned long long      blocks = 0;
 34 
 35         /*
 36          * Reserve enough blocks to write out a completely new bmbt for a
 37          * maximally fragmented bitmap file.  We do not hold the rtbitmap
 38          * ILOCK yet, so this is entirely speculative.
 39          */
 40         blocks = xfs_bmbt_calc_size(mp, mp->m_sb.sb_rbmblocks);
 41         if (blocks > UINT_MAX)
 42                 return -EOPNOTSUPP;
 43 
 44         rtb->resblks += blocks;
 45         return 0;
 46 }
 47 
 48 /*
 49  * Make sure that the given range of the data fork of the realtime file is
 50  * mapped to written blocks.  The caller must ensure that the inode is joined
 51  * to the transaction.
 52  */
 53 STATIC int
 54 xrep_rtbitmap_data_mappings(
 55         struct xfs_scrub        *sc,
 56         xfs_filblks_t           len)
 57 {
 58         struct xfs_bmbt_irec    map;
 59         xfs_fileoff_t           off = 0;
 60         int                     error;
 61 
 62         ASSERT(sc->ip != NULL);
 63 
 64         while (off < len) {
 65                 int             nmaps = 1;
 66 
 67                 /*
 68                  * If we have a real extent mapping this block then we're
 69                  * in ok shape.
 70                  */
 71                 error = xfs_bmapi_read(sc->ip, off, len - off, &map, &nmaps,
 72                                 XFS_DATA_FORK);
 73                 if (error)
 74                         return error;
 75                 if (nmaps == 0) {
 76                         ASSERT(nmaps != 0);
 77                         return -EFSCORRUPTED;
 78                 }
 79 
 80                 /*
 81                  * Written extents are ok.  Holes are not filled because we
 82                  * do not know the freespace information.
 83                  */
 84                 if (xfs_bmap_is_written_extent(&map) ||
 85                     map.br_startblock == HOLESTARTBLOCK) {
 86                         off = map.br_startoff + map.br_blockcount;
 87                         continue;
 88                 }
 89 
 90                 /*
 91                  * If we find a delalloc reservation then something is very
 92                  * very wrong.  Bail out.
 93                  */
 94                 if (map.br_startblock == DELAYSTARTBLOCK)
 95                         return -EFSCORRUPTED;
 96 
 97                 /* Make sure we're really converting an unwritten extent. */
 98                 if (map.br_state != XFS_EXT_UNWRITTEN) {
 99                         ASSERT(map.br_state == XFS_EXT_UNWRITTEN);
100                         return -EFSCORRUPTED;
101                 }
102 
103                 /* Make sure this block has a real zeroed extent mapped. */
104                 nmaps = 1;
105                 error = xfs_bmapi_write(sc->tp, sc->ip, map.br_startoff,
106                                 map.br_blockcount,
107                                 XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO,
108                                 0, &map, &nmaps);
109                 if (error)
110                         return error;
111 
112                 /* Commit new extent and all deferred work. */
113                 error = xrep_defer_finish(sc);
114                 if (error)
115                         return error;
116 
117                 off = map.br_startoff + map.br_blockcount;
118         }
119 
120         return 0;
121 }
122 
123 /* Fix broken rt volume geometry. */
124 STATIC int
125 xrep_rtbitmap_geometry(
126         struct xfs_scrub        *sc,
127         struct xchk_rtbitmap    *rtb)
128 {
129         struct xfs_mount        *mp = sc->mp;
130         struct xfs_trans        *tp = sc->tp;
131 
132         /* Superblock fields */
133         if (mp->m_sb.sb_rextents != rtb->rextents)
134                 xfs_trans_mod_sb(sc->tp, XFS_TRANS_SB_REXTENTS,
135                                 rtb->rextents - mp->m_sb.sb_rextents);
136 
137         if (mp->m_sb.sb_rbmblocks != rtb->rbmblocks)
138                 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
139                                 rtb->rbmblocks - mp->m_sb.sb_rbmblocks);
140 
141         if (mp->m_sb.sb_rextslog != rtb->rextslog)
142                 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
143                                 rtb->rextslog - mp->m_sb.sb_rextslog);
144 
145         /* Fix broken isize */
146         sc->ip->i_disk_size = roundup_64(sc->ip->i_disk_size,
147                                          mp->m_sb.sb_blocksize);
148 
149         if (sc->ip->i_disk_size < XFS_FSB_TO_B(mp, rtb->rbmblocks))
150                 sc->ip->i_disk_size = XFS_FSB_TO_B(mp, rtb->rbmblocks);
151 
152         xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
153         return xrep_roll_trans(sc);
154 }
155 
156 /* Repair the realtime bitmap file metadata. */
157 int
158 xrep_rtbitmap(
159         struct xfs_scrub        *sc)
160 {
161         struct xchk_rtbitmap    *rtb = sc->buf;
162         struct xfs_mount        *mp = sc->mp;
163         unsigned long long      blocks = 0;
164         int                     error;
165 
166         /* Impossibly large rtbitmap means we can't touch the filesystem. */
167         if (rtb->rbmblocks > U32_MAX)
168                 return 0;
169 
170         /*
171          * If the size of the rt bitmap file is larger than what we reserved,
172          * figure out if we need to adjust the block reservation in the
173          * transaction.
174          */
175         blocks = xfs_bmbt_calc_size(mp, rtb->rbmblocks);
176         if (blocks > UINT_MAX)
177                 return -EOPNOTSUPP;
178         if (blocks > rtb->resblks) {
179                 error = xfs_trans_reserve_more(sc->tp, blocks, 0);
180                 if (error)
181                         return error;
182 
183                 rtb->resblks += blocks;
184         }
185 
186         /* Fix inode core and forks. */
187         error = xrep_metadata_inode_forks(sc);
188         if (error)
189                 return error;
190 
191         xfs_trans_ijoin(sc->tp, sc->ip, 0);
192 
193         /* Ensure no unwritten extents. */
194         error = xrep_rtbitmap_data_mappings(sc, rtb->rbmblocks);
195         if (error)
196                 return error;
197 
198         /* Fix inconsistent bitmap geometry */
199         return xrep_rtbitmap_geometry(sc, rtb);
200 }
201 

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