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

TOMOYO Linux Cross Reference
Linux/fs/xfs/xfs_fsops.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/xfs_fsops.c (Version linux-6.12-rc7) and /fs/xfs/xfs_fsops.c (Version linux-4.18.20)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                                  2 /*
  3  * Copyright (c) 2000-2005 Silicon Graphics, I      3  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4  * All Rights Reserved.                             4  * All Rights Reserved.
  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_format.h"                             9 #include "xfs_format.h"
 10 #include "xfs_log_format.h"                        10 #include "xfs_log_format.h"
 11 #include "xfs_trans_resv.h"                        11 #include "xfs_trans_resv.h"
 12 #include "xfs_sb.h"                                12 #include "xfs_sb.h"
 13 #include "xfs_mount.h"                             13 #include "xfs_mount.h"
                                                   >>  14 #include "xfs_defer.h"
 14 #include "xfs_trans.h"                             15 #include "xfs_trans.h"
 15 #include "xfs_error.h"                             16 #include "xfs_error.h"
                                                   >>  17 #include "xfs_btree.h"
 16 #include "xfs_alloc.h"                             18 #include "xfs_alloc.h"
 17 #include "xfs_fsops.h"                             19 #include "xfs_fsops.h"
 18 #include "xfs_trans_space.h"                       20 #include "xfs_trans_space.h"
                                                   >>  21 #include "xfs_rtalloc.h"
                                                   >>  22 #include "xfs_trace.h"
 19 #include "xfs_log.h"                               23 #include "xfs_log.h"
 20 #include "xfs_log_priv.h"                      << 
 21 #include "xfs_ag.h"                                24 #include "xfs_ag.h"
 22 #include "xfs_ag_resv.h"                           25 #include "xfs_ag_resv.h"
 23 #include "xfs_trace.h"                         << 
 24                                                << 
 25 /*                                             << 
 26  * Write new AG headers to disk. Non-transacti << 
 27  * written and completed prior to the growfs t << 
 28  * To do this, we use a delayed write buffer l << 
 29  * submission and IO completion of the list as << 
 30  * IO subsystem to merge all the AG headers in << 
 31  * IO and hide most of the latency of the IO f << 
 32  *                                             << 
 33  * This also means that if we get an error whi << 
 34  * list to write, we can cancel the entire lis << 
 35  * anything.                                   << 
 36  */                                            << 
 37 static int                                     << 
 38 xfs_resizefs_init_new_ags(                     << 
 39         struct xfs_trans        *tp,           << 
 40         struct aghdr_init_data  *id,           << 
 41         xfs_agnumber_t          oagcount,      << 
 42         xfs_agnumber_t          nagcount,      << 
 43         xfs_rfsblock_t          delta,         << 
 44         struct xfs_perag        *last_pag,     << 
 45         bool                    *lastag_extend << 
 46 {                                              << 
 47         struct xfs_mount        *mp = tp->t_mo << 
 48         xfs_rfsblock_t          nb = mp->m_sb. << 
 49         int                     error;         << 
 50                                                << 
 51         *lastag_extended = false;              << 
 52                                                << 
 53         INIT_LIST_HEAD(&id->buffer_list);      << 
 54         for (id->agno = nagcount - 1;          << 
 55              id->agno >= oagcount;             << 
 56              id->agno--, delta -= id->agsize)  << 
 57                                                << 
 58                 if (id->agno == nagcount - 1)  << 
 59                         id->agsize = nb - (id- << 
 60                                         (xfs_r << 
 61                 else                           << 
 62                         id->agsize = mp->m_sb. << 
 63                                                << 
 64                 error = xfs_ag_init_headers(mp << 
 65                 if (error) {                   << 
 66                         xfs_buf_delwri_cancel( << 
 67                         return error;          << 
 68                 }                              << 
 69         }                                      << 
 70                                                << 
 71         error = xfs_buf_delwri_submit(&id->buf << 
 72         if (error)                             << 
 73                 return error;                  << 
 74                                                << 
 75         if (delta) {                           << 
 76                 *lastag_extended = true;       << 
 77                 error = xfs_ag_extend_space(la << 
 78         }                                      << 
 79         return error;                          << 
 80 }                                              << 
 81                                                    26 
 82 /*                                                 27 /*
 83  * growfs operations                               28  * growfs operations
 84  */                                                29  */
 85 static int                                         30 static int
 86 xfs_growfs_data_private(                           31 xfs_growfs_data_private(
 87         struct xfs_mount        *mp,           !!  32         xfs_mount_t             *mp,            /* mount point for filesystem */
 88         struct xfs_growfs_data  *in)           !!  33         xfs_growfs_data_t       *in)            /* growfs data input struct */
 89 {                                                  34 {
 90         xfs_agnumber_t          oagcount = mp- !!  35         xfs_buf_t               *bp;
 91         struct xfs_buf          *bp;           << 
 92         int                     error;             36         int                     error;
 93         xfs_agnumber_t          nagcount;          37         xfs_agnumber_t          nagcount;
 94         xfs_agnumber_t          nagimax = 0;       38         xfs_agnumber_t          nagimax = 0;
 95         xfs_rfsblock_t          nb, nb_div, nb !!  39         xfs_rfsblock_t          nb, nb_mod;
 96         int64_t                 delta;         !!  40         xfs_rfsblock_t          new;
 97         bool                    lastag_extende !!  41         xfs_agnumber_t          oagcount;
 98         struct xfs_trans        *tp;           !!  42         xfs_trans_t             *tp;
                                                   >>  43         LIST_HEAD               (buffer_list);
 99         struct aghdr_init_data  id = {};           44         struct aghdr_init_data  id = {};
100         struct xfs_perag        *last_pag;     << 
101                                                    45 
102         nb = in->newblocks;                        46         nb = in->newblocks;
103         error = xfs_sb_validate_fsb_count(&mp- !!  47         if (nb < mp->m_sb.sb_dblocks)
104         if (error)                             !!  48                 return -EINVAL;
                                                   >>  49         if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
105                 return error;                      50                 return error;
106                                                !!  51         error = xfs_buf_read_uncached(mp->m_ddev_targp,
107         if (nb > mp->m_sb.sb_dblocks) {        << 
108                 error = xfs_buf_read_uncached( << 
109                                 XFS_FSB_TO_BB(     52                                 XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
110                                 XFS_FSS_TO_BB(     53                                 XFS_FSS_TO_BB(mp, 1), 0, &bp, NULL);
                                                   >>  54         if (error)
                                                   >>  55                 return error;
                                                   >>  56         xfs_buf_relse(bp);
                                                   >>  57 
                                                   >>  58         new = nb;       /* use new as a temporary here */
                                                   >>  59         nb_mod = do_div(new, mp->m_sb.sb_agblocks);
                                                   >>  60         nagcount = new + (nb_mod != 0);
                                                   >>  61         if (nb_mod && nb_mod < XFS_MIN_AG_BLOCKS) {
                                                   >>  62                 nagcount--;
                                                   >>  63                 nb = (xfs_rfsblock_t)nagcount * mp->m_sb.sb_agblocks;
                                                   >>  64                 if (nb < mp->m_sb.sb_dblocks)
                                                   >>  65                         return -EINVAL;
                                                   >>  66         }
                                                   >>  67         new = nb - mp->m_sb.sb_dblocks;
                                                   >>  68         oagcount = mp->m_sb.sb_agcount;
                                                   >>  69 
                                                   >>  70         /* allocate the new per-ag structures */
                                                   >>  71         if (nagcount > oagcount) {
                                                   >>  72                 error = xfs_initialize_perag(mp, nagcount, &nagimax);
111                 if (error)                         73                 if (error)
112                         return error;              74                         return error;
113                 xfs_buf_relse(bp);             << 
114         }                                          75         }
115                                                    76 
116         nb_div = nb;                           !!  77         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
117         nb_mod = do_div(nb_div, mp->m_sb.sb_ag !!  78                         XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
118         if (nb_mod && nb_mod >= XFS_MIN_AG_BLO !!  79         if (error)
119                 nb_div++;                      !!  80                 return error;
120         else if (nb_mod)                       << 
121                 nb = nb_div * mp->m_sb.sb_agbl << 
122                                                    81 
123         if (nb_div > XFS_MAX_AGNUMBER + 1) {   << 
124                 nb_div = XFS_MAX_AGNUMBER + 1; << 
125                 nb = nb_div * mp->m_sb.sb_agbl << 
126         }                                      << 
127         nagcount = nb_div;                     << 
128         delta = nb - mp->m_sb.sb_dblocks;      << 
129         /*                                         82         /*
130          * Reject filesystems with a single AG !!  83          * Write new AG headers to disk. Non-transactional, but need to be
131          * supported, and reject a shrink oper !!  84          * written and completed prior to the growfs transaction being logged.
132          * filesystem to become unsupported.   !!  85          * To do this, we use a delayed write buffer list and wait for
                                                   >>  86          * submission and IO completion of the list as a whole. This allows the
                                                   >>  87          * IO subsystem to merge all the AG headers in a single AG into a single
                                                   >>  88          * IO and hide most of the latency of the IO from us.
                                                   >>  89          *
                                                   >>  90          * This also means that if we get an error whilst building the buffer
                                                   >>  91          * list to write, we can cancel the entire list without having written
                                                   >>  92          * anything.
133          */                                        93          */
134         if (delta < 0 && nagcount < 2)         !!  94         INIT_LIST_HEAD(&id.buffer_list);
135                 return -EINVAL;                !!  95         for (id.agno = nagcount - 1;
136                                                !!  96              id.agno >= oagcount;
137         /* No work to do */                    !!  97              id.agno--, new -= id.agsize) {
138         if (delta == 0)                        !!  98 
139                 return 0;                      !!  99                 if (id.agno == nagcount - 1)
140                                                !! 100                         id.agsize = nb -
141         /* TODO: shrinking the entire AGs hasn !! 101                                 (id.agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
142         if (nagcount < oagcount)               !! 102                 else
143                 return -EINVAL;                !! 103                         id.agsize = mp->m_sb.sb_agblocks;
144                                                << 
145         /* allocate the new per-ag structures  << 
146         error = xfs_initialize_perag(mp, oagco << 
147         if (error)                             << 
148                 return error;                  << 
149                                                   104 
150         if (delta > 0)                         !! 105                 error = xfs_ag_init_headers(mp, &id);
151                 error = xfs_trans_alloc(mp, &M !! 106                 if (error) {
152                                 XFS_GROWFS_SPA !! 107                         xfs_buf_delwri_cancel(&id.buffer_list);
153                                 &tp);          !! 108                         goto out_trans_cancel;
154         else                                   !! 109                 }
155                 error = xfs_trans_alloc(mp, &M !! 110         }
156                                 0, &tp);       !! 111         error = xfs_buf_delwri_submit(&id.buffer_list);
157         if (error)                                112         if (error)
158                 goto out_free_unused_perag;    !! 113                 goto out_trans_cancel;
159                                                   114 
160         last_pag = xfs_perag_get(mp, oagcount  !! 115         xfs_trans_agblocks_delta(tp, id.nfree);
161         if (delta > 0) {                       << 
162                 error = xfs_resizefs_init_new_ << 
163                                 delta, last_pa << 
164         } else {                               << 
165                 xfs_warn_mount(mp, XFS_OPSTATE << 
166         "EXPERIMENTAL online shrink feature in << 
167                                                   116 
168                 error = xfs_ag_shrink_space(la !! 117         /* If there are new blocks in the old last AG, extend it. */
                                                   >> 118         if (new) {
                                                   >> 119                 error = xfs_ag_extend_space(mp, tp, &id, new);
                                                   >> 120                 if (error)
                                                   >> 121                         goto out_trans_cancel;
169         }                                         122         }
170         xfs_perag_put(last_pag);               << 
171         if (error)                             << 
172                 goto out_trans_cancel;         << 
173                                                   123 
174         /*                                        124         /*
175          * Update changed superblock fields tr    125          * Update changed superblock fields transactionally. These are not
176          * seen by the rest of the world until    126          * seen by the rest of the world until the transaction commit applies
177          * them atomically to the superblock.     127          * them atomically to the superblock.
178          */                                       128          */
179         if (nagcount > oagcount)                  129         if (nagcount > oagcount)
180                 xfs_trans_mod_sb(tp, XFS_TRANS    130                 xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount);
181         if (delta)                             !! 131         if (nb > mp->m_sb.sb_dblocks)
182                 xfs_trans_mod_sb(tp, XFS_TRANS !! 132                 xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS,
                                                   >> 133                                  nb - mp->m_sb.sb_dblocks);
183         if (id.nfree)                             134         if (id.nfree)
184                 xfs_trans_mod_sb(tp, XFS_TRANS    135                 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, id.nfree);
185                                                << 
186         /*                                     << 
187          * Sync sb counters now to reflect the << 
188          * particularly important for shrink b << 
189          * will fail if sb_fdblocks is ever la << 
190          */                                    << 
191         if (xfs_has_lazysbcount(mp))           << 
192                 xfs_log_sb(tp);                << 
193                                                << 
194         xfs_trans_set_sync(tp);                   136         xfs_trans_set_sync(tp);
195         error = xfs_trans_commit(tp);             137         error = xfs_trans_commit(tp);
196         if (error)                                138         if (error)
197                 return error;                     139                 return error;
198                                                   140 
199         /* New allocation groups fully initial    141         /* New allocation groups fully initialized, so update mount struct */
200         if (nagimax)                              142         if (nagimax)
201                 mp->m_maxagi = nagimax;           143                 mp->m_maxagi = nagimax;
202         xfs_set_low_space_thresholds(mp);         144         xfs_set_low_space_thresholds(mp);
203         mp->m_alloc_set_aside = xfs_alloc_set_    145         mp->m_alloc_set_aside = xfs_alloc_set_aside(mp);
204                                                   146 
205         if (delta > 0) {                       !! 147         /*
206                 /*                             !! 148          * If we expanded the last AG, free the per-AG reservation
207                  * If we expanded the last AG, !! 149          * so we can reinitialize it with the new size.
208                  * so we can reinitialize it w !! 150          */
209                  */                            !! 151         if (new) {
210                 if (lastag_extended) {         !! 152                 struct xfs_perag        *pag;
211                         struct xfs_perag       << 
212                                                   153 
213                         pag = xfs_perag_get(mp !! 154                 pag = xfs_perag_get(mp, id.agno);
214                         xfs_ag_resv_free(pag); !! 155                 error = xfs_ag_resv_free(pag);
215                         xfs_perag_put(pag);    !! 156                 xfs_perag_put(pag);
216                 }                              !! 157                 if (error)
217                 /*                             !! 158                         return error;
218                  * Reserve AG metadata blocks. << 
219                  * was a growfs failure, just  << 
220                  * new user data after the gro << 
221                  */                            << 
222                 error = xfs_fs_reserve_ag_bloc << 
223                 if (error == -ENOSPC)          << 
224                         error = 0;             << 
225         }                                         159         }
                                                   >> 160 
                                                   >> 161         /*
                                                   >> 162          * Reserve AG metadata blocks. ENOSPC here does not mean there was a
                                                   >> 163          * growfs failure, just that there still isn't space for new user data
                                                   >> 164          * after the grow has been run.
                                                   >> 165          */
                                                   >> 166         error = xfs_fs_reserve_ag_blocks(mp);
                                                   >> 167         if (error == -ENOSPC)
                                                   >> 168                 error = 0;
226         return error;                             169         return error;
227                                                   170 
228 out_trans_cancel:                                 171 out_trans_cancel:
229         xfs_trans_cancel(tp);                     172         xfs_trans_cancel(tp);
230 out_free_unused_perag:                         << 
231         if (nagcount > oagcount)               << 
232                 xfs_free_perag_range(mp, oagco << 
233         return error;                             173         return error;
234 }                                                 174 }
235                                                   175 
236 static int                                        176 static int
237 xfs_growfs_log_private(                           177 xfs_growfs_log_private(
238         struct xfs_mount        *mp,    /* mou !! 178         xfs_mount_t             *mp,    /* mount point for filesystem */
239         struct xfs_growfs_log   *in)    /* gro !! 179         xfs_growfs_log_t        *in)    /* growfs log input struct */
240 {                                                 180 {
241         xfs_extlen_t            nb;               181         xfs_extlen_t            nb;
242                                                   182 
243         nb = in->newblocks;                       183         nb = in->newblocks;
244         if (nb < XFS_MIN_LOG_BLOCKS || nb < XF    184         if (nb < XFS_MIN_LOG_BLOCKS || nb < XFS_B_TO_FSB(mp, XFS_MIN_LOG_BYTES))
245                 return -EINVAL;                   185                 return -EINVAL;
246         if (nb == mp->m_sb.sb_logblocks &&        186         if (nb == mp->m_sb.sb_logblocks &&
247             in->isint == (mp->m_sb.sb_logstart    187             in->isint == (mp->m_sb.sb_logstart != 0))
248                 return -EINVAL;                   188                 return -EINVAL;
249         /*                                        189         /*
250          * Moving the log is hard, need new in    190          * Moving the log is hard, need new interfaces to sync
251          * the log first, hold off all activit    191          * the log first, hold off all activity while moving it.
252          * Can have shorter or longer log in t    192          * Can have shorter or longer log in the same space,
253          * or transform internal to external l    193          * or transform internal to external log or vice versa.
254          */                                       194          */
255         return -ENOSYS;                           195         return -ENOSYS;
256 }                                                 196 }
257                                                   197 
258 static int                                        198 static int
259 xfs_growfs_imaxpct(                               199 xfs_growfs_imaxpct(
260         struct xfs_mount        *mp,              200         struct xfs_mount        *mp,
261         __u32                   imaxpct)          201         __u32                   imaxpct)
262 {                                                 202 {
263         struct xfs_trans        *tp;              203         struct xfs_trans        *tp;
264         int                     dpct;             204         int                     dpct;
265         int                     error;            205         int                     error;
266                                                   206 
267         if (imaxpct > 100)                        207         if (imaxpct > 100)
268                 return -EINVAL;                   208                 return -EINVAL;
269                                                   209 
270         error = xfs_trans_alloc(mp, &M_RES(mp)    210         error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
271                         XFS_GROWFS_SPACE_RES(m    211                         XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp);
272         if (error)                                212         if (error)
273                 return error;                     213                 return error;
274                                                   214 
275         dpct = imaxpct - mp->m_sb.sb_imax_pct;    215         dpct = imaxpct - mp->m_sb.sb_imax_pct;
276         xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAX    216         xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct);
277         xfs_trans_set_sync(tp);                   217         xfs_trans_set_sync(tp);
278         return xfs_trans_commit(tp);              218         return xfs_trans_commit(tp);
279 }                                                 219 }
280                                                   220 
281 /*                                                221 /*
282  * protected versions of growfs function acqui    222  * protected versions of growfs function acquire and release locks on the mount
283  * point - exported through ioctls: XFS_IOC_FS    223  * point - exported through ioctls: XFS_IOC_FSGROWFSDATA, XFS_IOC_FSGROWFSLOG,
284  * XFS_IOC_FSGROWFSRT                             224  * XFS_IOC_FSGROWFSRT
285  */                                               225  */
286 int                                               226 int
287 xfs_growfs_data(                                  227 xfs_growfs_data(
288         struct xfs_mount        *mp,              228         struct xfs_mount        *mp,
289         struct xfs_growfs_data  *in)              229         struct xfs_growfs_data  *in)
290 {                                                 230 {
291         int                     error = 0;        231         int                     error = 0;
292                                                   232 
293         if (!capable(CAP_SYS_ADMIN))              233         if (!capable(CAP_SYS_ADMIN))
294                 return -EPERM;                    234                 return -EPERM;
295         if (!mutex_trylock(&mp->m_growlock))      235         if (!mutex_trylock(&mp->m_growlock))
296                 return -EWOULDBLOCK;              236                 return -EWOULDBLOCK;
297                                                   237 
298         /* update imaxpct separately to the ph    238         /* update imaxpct separately to the physical grow of the filesystem */
299         if (in->imaxpct != mp->m_sb.sb_imax_pc    239         if (in->imaxpct != mp->m_sb.sb_imax_pct) {
300                 error = xfs_growfs_imaxpct(mp,    240                 error = xfs_growfs_imaxpct(mp, in->imaxpct);
301                 if (error)                        241                 if (error)
302                         goto out_error;           242                         goto out_error;
303         }                                         243         }
304                                                   244 
305         if (in->newblocks != mp->m_sb.sb_dbloc    245         if (in->newblocks != mp->m_sb.sb_dblocks) {
306                 error = xfs_growfs_data_privat    246                 error = xfs_growfs_data_private(mp, in);
307                 if (error)                        247                 if (error)
308                         goto out_error;           248                         goto out_error;
309         }                                         249         }
310                                                   250 
311         /* Post growfs calculations needed to     251         /* Post growfs calculations needed to reflect new state in operations */
312         if (mp->m_sb.sb_imax_pct) {               252         if (mp->m_sb.sb_imax_pct) {
313                 uint64_t icount = mp->m_sb.sb_    253                 uint64_t icount = mp->m_sb.sb_dblocks * mp->m_sb.sb_imax_pct;
314                 do_div(icount, 100);              254                 do_div(icount, 100);
315                 M_IGEO(mp)->maxicount = XFS_FS !! 255                 mp->m_maxicount = icount << mp->m_sb.sb_inopblog;
316         } else                                    256         } else
317                 M_IGEO(mp)->maxicount = 0;     !! 257                 mp->m_maxicount = 0;
318                                                   258 
319         /* Update secondary superblocks now th    259         /* Update secondary superblocks now the physical grow has completed */
320         error = xfs_update_secondary_sbs(mp);     260         error = xfs_update_secondary_sbs(mp);
321                                                   261 
322 out_error:                                        262 out_error:
323         /*                                        263         /*
324          * Increment the generation unconditio    264          * Increment the generation unconditionally, the error could be from
325          * updating the secondary superblocks,    265          * updating the secondary superblocks, in which case the new size
326          * is live already.                       266          * is live already.
327          */                                       267          */
328         mp->m_generation++;                       268         mp->m_generation++;
329         mutex_unlock(&mp->m_growlock);            269         mutex_unlock(&mp->m_growlock);
330         return error;                             270         return error;
331 }                                                 271 }
332                                                   272 
333 int                                               273 int
334 xfs_growfs_log(                                   274 xfs_growfs_log(
335         xfs_mount_t             *mp,              275         xfs_mount_t             *mp,
336         struct xfs_growfs_log   *in)           !! 276         xfs_growfs_log_t        *in)
337 {                                                 277 {
338         int error;                                278         int error;
339                                                   279 
340         if (!capable(CAP_SYS_ADMIN))              280         if (!capable(CAP_SYS_ADMIN))
341                 return -EPERM;                    281                 return -EPERM;
342         if (!mutex_trylock(&mp->m_growlock))      282         if (!mutex_trylock(&mp->m_growlock))
343                 return -EWOULDBLOCK;              283                 return -EWOULDBLOCK;
344         error = xfs_growfs_log_private(mp, in)    284         error = xfs_growfs_log_private(mp, in);
345         mutex_unlock(&mp->m_growlock);            285         mutex_unlock(&mp->m_growlock);
346         return error;                             286         return error;
347 }                                                 287 }
348                                                   288 
349 /*                                                289 /*
                                                   >> 290  * exported through ioctl XFS_IOC_FSCOUNTS
                                                   >> 291  */
                                                   >> 292 
                                                   >> 293 int
                                                   >> 294 xfs_fs_counts(
                                                   >> 295         xfs_mount_t             *mp,
                                                   >> 296         xfs_fsop_counts_t       *cnt)
                                                   >> 297 {
                                                   >> 298         cnt->allocino = percpu_counter_read_positive(&mp->m_icount);
                                                   >> 299         cnt->freeino = percpu_counter_read_positive(&mp->m_ifree);
                                                   >> 300         cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) -
                                                   >> 301                                                 mp->m_alloc_set_aside;
                                                   >> 302 
                                                   >> 303         spin_lock(&mp->m_sb_lock);
                                                   >> 304         cnt->freertx = mp->m_sb.sb_frextents;
                                                   >> 305         spin_unlock(&mp->m_sb_lock);
                                                   >> 306         return 0;
                                                   >> 307 }
                                                   >> 308 
                                                   >> 309 /*
                                                   >> 310  * exported through ioctl XFS_IOC_SET_RESBLKS & XFS_IOC_GET_RESBLKS
                                                   >> 311  *
                                                   >> 312  * xfs_reserve_blocks is called to set m_resblks
                                                   >> 313  * in the in-core mount table. The number of unused reserved blocks
                                                   >> 314  * is kept in m_resblks_avail.
                                                   >> 315  *
350  * Reserve the requested number of blocks if a    316  * Reserve the requested number of blocks if available. Otherwise return
351  * as many as possible to satisfy the request.    317  * as many as possible to satisfy the request. The actual number
352  * reserved are returned in outval.            !! 318  * reserved are returned in outval
                                                   >> 319  *
                                                   >> 320  * A null inval pointer indicates that only the current reserved blocks
                                                   >> 321  * available  should  be returned no settings are changed.
353  */                                               322  */
                                                   >> 323 
354 int                                               324 int
355 xfs_reserve_blocks(                               325 xfs_reserve_blocks(
356         struct xfs_mount        *mp,           !! 326         xfs_mount_t             *mp,
357         uint64_t                request)       !! 327         uint64_t              *inval,
                                                   >> 328         xfs_fsop_resblks_t      *outval)
358 {                                                 329 {
359         int64_t                 lcounter, delt    330         int64_t                 lcounter, delta;
360         int64_t                 fdblks_delta =    331         int64_t                 fdblks_delta = 0;
                                                   >> 332         uint64_t                request;
361         int64_t                 free;             333         int64_t                 free;
362         int                     error = 0;        334         int                     error = 0;
363                                                   335 
                                                   >> 336         /* If inval is null, report current values and return */
                                                   >> 337         if (inval == (uint64_t *)NULL) {
                                                   >> 338                 if (!outval)
                                                   >> 339                         return -EINVAL;
                                                   >> 340                 outval->resblks = mp->m_resblks;
                                                   >> 341                 outval->resblks_avail = mp->m_resblks_avail;
                                                   >> 342                 return 0;
                                                   >> 343         }
                                                   >> 344 
                                                   >> 345         request = *inval;
                                                   >> 346 
364         /*                                        347         /*
365          * With per-cpu counters, this becomes    348          * With per-cpu counters, this becomes an interesting problem. we need
366          * to work out if we are freeing or al    349          * to work out if we are freeing or allocation blocks first, then we can
367          * do the modification as necessary.      350          * do the modification as necessary.
368          *                                        351          *
369          * We do this under the m_sb_lock so t    352          * We do this under the m_sb_lock so that if we are near ENOSPC, we will
370          * hold out any changes while we work     353          * hold out any changes while we work out what to do. This means that
371          * the amount of free space can change    354          * the amount of free space can change while we do this, so we need to
372          * retry if we end up trying to reserv    355          * retry if we end up trying to reserve more space than is available.
373          */                                       356          */
374         spin_lock(&mp->m_sb_lock);                357         spin_lock(&mp->m_sb_lock);
375                                                   358 
376         /*                                        359         /*
377          * If our previous reservation was lar    360          * If our previous reservation was larger than the current value,
378          * then move any unused blocks back to    361          * then move any unused blocks back to the free pool. Modify the resblks
379          * counters directly since we shouldn'    362          * counters directly since we shouldn't have any problems unreserving
380          * space.                                 363          * space.
381          */                                       364          */
382         if (mp->m_resblks > request) {            365         if (mp->m_resblks > request) {
383                 lcounter = mp->m_resblks_avail    366                 lcounter = mp->m_resblks_avail - request;
384                 if (lcounter > 0) {            !! 367                 if (lcounter  > 0) {            /* release unused blocks */
385                         fdblks_delta = lcounte    368                         fdblks_delta = lcounter;
386                         mp->m_resblks_avail -=    369                         mp->m_resblks_avail -= lcounter;
387                 }                                 370                 }
388                 mp->m_resblks = request;          371                 mp->m_resblks = request;
389                 if (fdblks_delta) {               372                 if (fdblks_delta) {
390                         spin_unlock(&mp->m_sb_    373                         spin_unlock(&mp->m_sb_lock);
391                         xfs_add_fdblocks(mp, f !! 374                         error = xfs_mod_fdblocks(mp, fdblks_delta, 0);
392                         spin_lock(&mp->m_sb_lo    375                         spin_lock(&mp->m_sb_lock);
393                 }                                 376                 }
394                                                   377 
395                 goto out;                         378                 goto out;
396         }                                         379         }
397                                                   380 
398         /*                                        381         /*
399          * If the request is larger than the c    382          * If the request is larger than the current reservation, reserve the
400          * blocks before we update the reserve    383          * blocks before we update the reserve counters. Sample m_fdblocks and
401          * perform a partial reservation if th    384          * perform a partial reservation if the request exceeds free space.
402          *                                     !! 385          */
403          * The code below estimates how many b !! 386         error = -ENOSPC;
404          * fdblocks to stash in the reserve po !! 387         do {
405          * race since fdblocks updates are not !! 388                 free = percpu_counter_sum(&mp->m_fdblocks) -
406          * m_sb_lock.  Set the reserve size ev !! 389                                                 mp->m_alloc_set_aside;
407          * space to fill it because mod_fdbloc !! 390                 if (free <= 0)
408          * reserve when it can.                !! 391                         break;
409          */                                    !! 392 
410         free = percpu_counter_sum(&mp->m_fdblo !! 393                 delta = request - mp->m_resblks;
411                                                !! 394                 lcounter = free - delta;
412         delta = request - mp->m_resblks;       !! 395                 if (lcounter < 0)
413         mp->m_resblks = request;               !! 396                         /* We can't satisfy the request, just get what we can */
414         if (delta > 0 && free > 0) {           !! 397                         fdblks_delta = free;
                                                   >> 398                 else
                                                   >> 399                         fdblks_delta = delta;
                                                   >> 400 
415                 /*                                401                 /*
416                  * We'll either succeed in get    402                  * We'll either succeed in getting space from the free block
417                  * count or we'll get an ENOSP !! 403                  * count or we'll get an ENOSPC. If we get a ENOSPC, it means
418                  * here - we don't want to res !! 404                  * things changed while we were calculating fdblks_delta and so
419                  * from the reserve.           !! 405                  * we should try again to see if there is anything left to
                                                   >> 406                  * reserve.
420                  *                                407                  *
421                  * The desired reserve size ca !! 408                  * Don't set the reserved flag here - we don't want to reserve
422                  * Use mod_fdblocks to put the !! 409                  * the extra reserve blocks from the reserve.....
423                  * fdblocks as appropriate.    << 
424                  */                               410                  */
425                 fdblks_delta = min(free, delta << 
426                 spin_unlock(&mp->m_sb_lock);      411                 spin_unlock(&mp->m_sb_lock);
427                 error = xfs_dec_fdblocks(mp, f !! 412                 error = xfs_mod_fdblocks(mp, -fdblks_delta, 0);
428                 if (!error)                    << 
429                         xfs_add_fdblocks(mp, f << 
430                 spin_lock(&mp->m_sb_lock);        413                 spin_lock(&mp->m_sb_lock);
                                                   >> 414         } while (error == -ENOSPC);
                                                   >> 415 
                                                   >> 416         /*
                                                   >> 417          * Update the reserve counters if blocks have been successfully
                                                   >> 418          * allocated.
                                                   >> 419          */
                                                   >> 420         if (!error && fdblks_delta) {
                                                   >> 421                 mp->m_resblks += fdblks_delta;
                                                   >> 422                 mp->m_resblks_avail += fdblks_delta;
431         }                                         423         }
                                                   >> 424 
432 out:                                              425 out:
                                                   >> 426         if (outval) {
                                                   >> 427                 outval->resblks = mp->m_resblks;
                                                   >> 428                 outval->resblks_avail = mp->m_resblks_avail;
                                                   >> 429         }
                                                   >> 430 
433         spin_unlock(&mp->m_sb_lock);              431         spin_unlock(&mp->m_sb_lock);
434         return error;                             432         return error;
435 }                                                 433 }
436                                                   434 
437 int                                               435 int
438 xfs_fs_goingdown(                                 436 xfs_fs_goingdown(
439         xfs_mount_t     *mp,                      437         xfs_mount_t     *mp,
440         uint32_t        inflags)                  438         uint32_t        inflags)
441 {                                                 439 {
442         switch (inflags) {                        440         switch (inflags) {
443         case XFS_FSOP_GOING_FLAGS_DEFAULT: {      441         case XFS_FSOP_GOING_FLAGS_DEFAULT: {
444                 if (!bdev_freeze(mp->m_super-> !! 442                 struct super_block *sb = freeze_bdev(mp->m_super->s_bdev);
                                                   >> 443 
                                                   >> 444                 if (sb && !IS_ERR(sb)) {
445                         xfs_force_shutdown(mp,    445                         xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
446                         bdev_thaw(mp->m_super- !! 446                         thaw_bdev(sb->s_bdev, sb);
447                 }                                 447                 }
                                                   >> 448 
448                 break;                            449                 break;
449         }                                         450         }
450         case XFS_FSOP_GOING_FLAGS_LOGFLUSH:       451         case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
451                 xfs_force_shutdown(mp, SHUTDOW    452                 xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
452                 break;                            453                 break;
453         case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:     454         case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
454                 xfs_force_shutdown(mp,            455                 xfs_force_shutdown(mp,
455                                 SHUTDOWN_FORCE    456                                 SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR);
456                 break;                            457                 break;
457         default:                                  458         default:
458                 return -EINVAL;                   459                 return -EINVAL;
459         }                                         460         }
460                                                   461 
461         return 0;                                 462         return 0;
462 }                                                 463 }
463                                                   464 
464 /*                                                465 /*
465  * Force a shutdown of the filesystem instantl    466  * Force a shutdown of the filesystem instantly while keeping the filesystem
466  * consistent. We don't do an unmount here; ju    467  * consistent. We don't do an unmount here; just shutdown the shop, make sure
467  * that absolutely nothing persistent happens     468  * that absolutely nothing persistent happens to this filesystem after this
468  * point.                                         469  * point.
469  *                                             << 
470  * The shutdown state change is atomic, result << 
471  * first shutdown call processing the shutdown << 
472  * log once as it requires, and we don't spam  << 
473  * shutdowns race to set the shutdown flags.   << 
474  */                                               470  */
475 void                                              471 void
476 xfs_do_force_shutdown(                            472 xfs_do_force_shutdown(
477         struct xfs_mount *mp,                  !! 473         xfs_mount_t     *mp,
478         uint32_t        flags,                 !! 474         int             flags,
479         char            *fname,                   475         char            *fname,
480         int             lnnum)                    476         int             lnnum)
481 {                                                 477 {
482         int             tag;                   !! 478         int             logerror;
483         const char      *why;                  << 
484                                                   479 
                                                   >> 480         logerror = flags & SHUTDOWN_LOG_IO_ERROR;
485                                                   481 
486         if (xfs_set_shutdown(mp)) {            !! 482         if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
487                 xlog_shutdown_wait(mp->m_log); !! 483                 xfs_notice(mp,
488                 return;                        !! 484         "%s(0x%x) called from line %d of file %s.  Return address = "PTR_FMT,
                                                   >> 485                         __func__, flags, lnnum, fname, __return_address);
489         }                                         486         }
490         if (mp->m_sb_bp)                       !! 487         /*
491                 mp->m_sb_bp->b_flags |= XBF_DO !! 488          * No need to duplicate efforts.
                                                   >> 489          */
                                                   >> 490         if (XFS_FORCED_SHUTDOWN(mp) && !logerror)
                                                   >> 491                 return;
492                                                   492 
493         if (flags & SHUTDOWN_FORCE_UMOUNT)     !! 493         /*
494                 xfs_alert(mp, "User initiated  !! 494          * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
                                                   >> 495          * queue up anybody new on the log reservations, and wakes up
                                                   >> 496          * everybody who's sleeping on log reservations to tell them
                                                   >> 497          * the bad news.
                                                   >> 498          */
                                                   >> 499         if (xfs_log_force_umount(mp, logerror))
                                                   >> 500                 return;
495                                                   501 
496         if (xlog_force_shutdown(mp->m_log, fla !! 502         if (flags & SHUTDOWN_CORRUPT_INCORE) {
497                 tag = XFS_PTAG_SHUTDOWN_LOGERR !! 503                 xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT,
498                 why = "Log I/O Error";         !! 504     "Corruption of in-memory data detected.  Shutting down filesystem");
499         } else if (flags & SHUTDOWN_CORRUPT_IN !! 505                 if (XFS_ERRLEVEL_HIGH <= xfs_error_level)
500                 tag = XFS_PTAG_SHUTDOWN_CORRUP !! 506                         xfs_stack_trace();
501                 why = "Corruption of in-memory !! 507         } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
502         } else if (flags & SHUTDOWN_CORRUPT_ON !! 508                 if (logerror) {
503                 tag = XFS_PTAG_SHUTDOWN_CORRUP !! 509                         xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR,
504                 why = "Corruption of on-disk m !! 510                 "Log I/O Error Detected.  Shutting down filesystem");
505         } else if (flags & SHUTDOWN_DEVICE_REM !! 511                 } else if (flags & SHUTDOWN_DEVICE_REQ) {
506                 tag = XFS_PTAG_SHUTDOWN_IOERRO !! 512                         xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
507                 why = "Block device removal";  !! 513                 "All device paths lost.  Shutting down filesystem");
508         } else {                               !! 514                 } else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
509                 tag = XFS_PTAG_SHUTDOWN_IOERRO !! 515                         xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
510                 why = "Metadata I/O Error";    !! 516                 "I/O Error Detected. Shutting down filesystem");
511         }                                      !! 517                 }
512                                                !! 518         }
513         trace_xfs_force_shutdown(mp, tag, flag !! 519         if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
514                                                !! 520                 xfs_alert(mp,
515         xfs_alert_tag(mp, tag,                 !! 521         "Please umount the filesystem and rectify the problem(s)");
516 "%s (0x%x) detected at %pS (%s:%d).  Shutting  !! 522         }
517                         why, flags, __return_a << 
518         xfs_alert(mp,                          << 
519                 "Please unmount the filesystem << 
520         if (xfs_error_level >= XFS_ERRLEVEL_HI << 
521                 xfs_stack_trace();             << 
522 }                                                 523 }
523                                                   524 
524 /*                                                525 /*
525  * Reserve free space for per-AG metadata.        526  * Reserve free space for per-AG metadata.
526  */                                               527  */
527 int                                               528 int
528 xfs_fs_reserve_ag_blocks(                         529 xfs_fs_reserve_ag_blocks(
529         struct xfs_mount        *mp)              530         struct xfs_mount        *mp)
530 {                                                 531 {
531         xfs_agnumber_t          agno;             532         xfs_agnumber_t          agno;
532         struct xfs_perag        *pag;             533         struct xfs_perag        *pag;
533         int                     error = 0;        534         int                     error = 0;
534         int                     err2;             535         int                     err2;
535                                                   536 
536         mp->m_finobt_nores = false;            !! 537         for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
537         for_each_perag(mp, agno, pag) {        !! 538                 pag = xfs_perag_get(mp, agno);
538                 err2 = xfs_ag_resv_init(pag, N !! 539                 err2 = xfs_ag_resv_init(pag);
                                                   >> 540                 xfs_perag_put(pag);
539                 if (err2 && !error)               541                 if (err2 && !error)
540                         error = err2;             542                         error = err2;
541         }                                         543         }
542                                                   544 
543         if (error && error != -ENOSPC) {          545         if (error && error != -ENOSPC) {
544                 xfs_warn(mp,                      546                 xfs_warn(mp,
545         "Error %d reserving per-AG metadata re    547         "Error %d reserving per-AG metadata reserve pool.", error);
546                 xfs_force_shutdown(mp, SHUTDOW    548                 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
547         }                                         549         }
548                                                   550 
549         return error;                             551         return error;
550 }                                                 552 }
551                                                   553 
552 /*                                                554 /*
553  * Free space reserved for per-AG metadata.       555  * Free space reserved for per-AG metadata.
554  */                                               556  */
555 void                                           !! 557 int
556 xfs_fs_unreserve_ag_blocks(                       558 xfs_fs_unreserve_ag_blocks(
557         struct xfs_mount        *mp)              559         struct xfs_mount        *mp)
558 {                                                 560 {
559         xfs_agnumber_t          agno;             561         xfs_agnumber_t          agno;
560         struct xfs_perag        *pag;             562         struct xfs_perag        *pag;
                                                   >> 563         int                     error = 0;
                                                   >> 564         int                     err2;
561                                                   565 
562         for_each_perag(mp, agno, pag)          !! 566         for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
563                 xfs_ag_resv_free(pag);         !! 567                 pag = xfs_perag_get(mp, agno);
                                                   >> 568                 err2 = xfs_ag_resv_free(pag);
                                                   >> 569                 xfs_perag_put(pag);
                                                   >> 570                 if (err2 && !error)
                                                   >> 571                         error = err2;
                                                   >> 572         }
                                                   >> 573 
                                                   >> 574         if (error)
                                                   >> 575                 xfs_warn(mp,
                                                   >> 576         "Error %d freeing per-AG metadata reserve pool.", error);
                                                   >> 577 
                                                   >> 578         return error;
564 }                                                 579 }
565                                                   580 

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