~ [ 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.19.322)


** Warning: Cannot open xref database.

  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * Copyright (c) 2000-2005 Silicon Graphics, I    
  4  * All Rights Reserved.                           
  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_resv.h"                       
 12 #include "xfs_sb.h"                               
 13 #include "xfs_mount.h"                            
 14 #include "xfs_trans.h"                            
 15 #include "xfs_error.h"                            
 16 #include "xfs_alloc.h"                            
 17 #include "xfs_fsops.h"                            
 18 #include "xfs_trans_space.h"                      
 19 #include "xfs_log.h"                              
 20 #include "xfs_log_priv.h"                         
 21 #include "xfs_ag.h"                               
 22 #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                                                   
 82 /*                                                
 83  * growfs operations                              
 84  */                                               
 85 static int                                        
 86 xfs_growfs_data_private(                          
 87         struct xfs_mount        *mp,              
 88         struct xfs_growfs_data  *in)              
 89 {                                                 
 90         xfs_agnumber_t          oagcount = mp-    
 91         struct xfs_buf          *bp;              
 92         int                     error;            
 93         xfs_agnumber_t          nagcount;         
 94         xfs_agnumber_t          nagimax = 0;      
 95         xfs_rfsblock_t          nb, nb_div, nb    
 96         int64_t                 delta;            
 97         bool                    lastag_extende    
 98         struct xfs_trans        *tp;              
 99         struct aghdr_init_data  id = {};          
100         struct xfs_perag        *last_pag;        
101                                                   
102         nb = in->newblocks;                       
103         error = xfs_sb_validate_fsb_count(&mp-    
104         if (error)                                
105                 return error;                     
106                                                   
107         if (nb > mp->m_sb.sb_dblocks) {           
108                 error = xfs_buf_read_uncached(    
109                                 XFS_FSB_TO_BB(    
110                                 XFS_FSS_TO_BB(    
111                 if (error)                        
112                         return error;             
113                 xfs_buf_relse(bp);                
114         }                                         
115                                                   
116         nb_div = nb;                              
117         nb_mod = do_div(nb_div, mp->m_sb.sb_ag    
118         if (nb_mod && nb_mod >= XFS_MIN_AG_BLO    
119                 nb_div++;                         
120         else if (nb_mod)                          
121                 nb = nb_div * mp->m_sb.sb_agbl    
122                                                   
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         /*                                        
130          * Reject filesystems with a single AG    
131          * supported, and reject a shrink oper    
132          * filesystem to become unsupported.      
133          */                                       
134         if (delta < 0 && nagcount < 2)            
135                 return -EINVAL;                   
136                                                   
137         /* No work to do */                       
138         if (delta == 0)                           
139                 return 0;                         
140                                                   
141         /* TODO: shrinking the entire AGs hasn    
142         if (nagcount < oagcount)                  
143                 return -EINVAL;                   
144                                                   
145         /* allocate the new per-ag structures     
146         error = xfs_initialize_perag(mp, oagco    
147         if (error)                                
148                 return error;                     
149                                                   
150         if (delta > 0)                            
151                 error = xfs_trans_alloc(mp, &M    
152                                 XFS_GROWFS_SPA    
153                                 &tp);             
154         else                                      
155                 error = xfs_trans_alloc(mp, &M    
156                                 0, &tp);          
157         if (error)                                
158                 goto out_free_unused_perag;       
159                                                   
160         last_pag = xfs_perag_get(mp, oagcount     
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                                                   
168                 error = xfs_ag_shrink_space(la    
169         }                                         
170         xfs_perag_put(last_pag);                  
171         if (error)                                
172                 goto out_trans_cancel;            
173                                                   
174         /*                                        
175          * Update changed superblock fields tr    
176          * seen by the rest of the world until    
177          * them atomically to the superblock.     
178          */                                       
179         if (nagcount > oagcount)                  
180                 xfs_trans_mod_sb(tp, XFS_TRANS    
181         if (delta)                                
182                 xfs_trans_mod_sb(tp, XFS_TRANS    
183         if (id.nfree)                             
184                 xfs_trans_mod_sb(tp, XFS_TRANS    
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);                   
195         error = xfs_trans_commit(tp);             
196         if (error)                                
197                 return error;                     
198                                                   
199         /* New allocation groups fully initial    
200         if (nagimax)                              
201                 mp->m_maxagi = nagimax;           
202         xfs_set_low_space_thresholds(mp);         
203         mp->m_alloc_set_aside = xfs_alloc_set_    
204                                                   
205         if (delta > 0) {                          
206                 /*                                
207                  * If we expanded the last AG,    
208                  * so we can reinitialize it w    
209                  */                               
210                 if (lastag_extended) {            
211                         struct xfs_perag          
212                                                   
213                         pag = xfs_perag_get(mp    
214                         xfs_ag_resv_free(pag);    
215                         xfs_perag_put(pag);       
216                 }                                 
217                 /*                                
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         }                                         
226         return error;                             
227                                                   
228 out_trans_cancel:                                 
229         xfs_trans_cancel(tp);                     
230 out_free_unused_perag:                            
231         if (nagcount > oagcount)                  
232                 xfs_free_perag_range(mp, oagco    
233         return error;                             
234 }                                                 
235                                                   
236 static int                                        
237 xfs_growfs_log_private(                           
238         struct xfs_mount        *mp,    /* mou    
239         struct xfs_growfs_log   *in)    /* gro    
240 {                                                 
241         xfs_extlen_t            nb;               
242                                                   
243         nb = in->newblocks;                       
244         if (nb < XFS_MIN_LOG_BLOCKS || nb < XF    
245                 return -EINVAL;                   
246         if (nb == mp->m_sb.sb_logblocks &&        
247             in->isint == (mp->m_sb.sb_logstart    
248                 return -EINVAL;                   
249         /*                                        
250          * Moving the log is hard, need new in    
251          * the log first, hold off all activit    
252          * Can have shorter or longer log in t    
253          * or transform internal to external l    
254          */                                       
255         return -ENOSYS;                           
256 }                                                 
257                                                   
258 static int                                        
259 xfs_growfs_imaxpct(                               
260         struct xfs_mount        *mp,              
261         __u32                   imaxpct)          
262 {                                                 
263         struct xfs_trans        *tp;              
264         int                     dpct;             
265         int                     error;            
266                                                   
267         if (imaxpct > 100)                        
268                 return -EINVAL;                   
269                                                   
270         error = xfs_trans_alloc(mp, &M_RES(mp)    
271                         XFS_GROWFS_SPACE_RES(m    
272         if (error)                                
273                 return error;                     
274                                                   
275         dpct = imaxpct - mp->m_sb.sb_imax_pct;    
276         xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAX    
277         xfs_trans_set_sync(tp);                   
278         return xfs_trans_commit(tp);              
279 }                                                 
280                                                   
281 /*                                                
282  * protected versions of growfs function acqui    
283  * point - exported through ioctls: XFS_IOC_FS    
284  * XFS_IOC_FSGROWFSRT                             
285  */                                               
286 int                                               
287 xfs_growfs_data(                                  
288         struct xfs_mount        *mp,              
289         struct xfs_growfs_data  *in)              
290 {                                                 
291         int                     error = 0;        
292                                                   
293         if (!capable(CAP_SYS_ADMIN))              
294                 return -EPERM;                    
295         if (!mutex_trylock(&mp->m_growlock))      
296                 return -EWOULDBLOCK;              
297                                                   
298         /* update imaxpct separately to the ph    
299         if (in->imaxpct != mp->m_sb.sb_imax_pc    
300                 error = xfs_growfs_imaxpct(mp,    
301                 if (error)                        
302                         goto out_error;           
303         }                                         
304                                                   
305         if (in->newblocks != mp->m_sb.sb_dbloc    
306                 error = xfs_growfs_data_privat    
307                 if (error)                        
308                         goto out_error;           
309         }                                         
310                                                   
311         /* Post growfs calculations needed to     
312         if (mp->m_sb.sb_imax_pct) {               
313                 uint64_t icount = mp->m_sb.sb_    
314                 do_div(icount, 100);              
315                 M_IGEO(mp)->maxicount = XFS_FS    
316         } else                                    
317                 M_IGEO(mp)->maxicount = 0;        
318                                                   
319         /* Update secondary superblocks now th    
320         error = xfs_update_secondary_sbs(mp);     
321                                                   
322 out_error:                                        
323         /*                                        
324          * Increment the generation unconditio    
325          * updating the secondary superblocks,    
326          * is live already.                       
327          */                                       
328         mp->m_generation++;                       
329         mutex_unlock(&mp->m_growlock);            
330         return error;                             
331 }                                                 
332                                                   
333 int                                               
334 xfs_growfs_log(                                   
335         xfs_mount_t             *mp,              
336         struct xfs_growfs_log   *in)              
337 {                                                 
338         int error;                                
339                                                   
340         if (!capable(CAP_SYS_ADMIN))              
341                 return -EPERM;                    
342         if (!mutex_trylock(&mp->m_growlock))      
343                 return -EWOULDBLOCK;              
344         error = xfs_growfs_log_private(mp, in)    
345         mutex_unlock(&mp->m_growlock);            
346         return error;                             
347 }                                                 
348                                                   
349 /*                                                
350  * Reserve the requested number of blocks if a    
351  * as many as possible to satisfy the request.    
352  * reserved are returned in outval.               
353  */                                               
354 int                                               
355 xfs_reserve_blocks(                               
356         struct xfs_mount        *mp,              
357         uint64_t                request)          
358 {                                                 
359         int64_t                 lcounter, delt    
360         int64_t                 fdblks_delta =    
361         int64_t                 free;             
362         int                     error = 0;        
363                                                   
364         /*                                        
365          * With per-cpu counters, this becomes    
366          * to work out if we are freeing or al    
367          * do the modification as necessary.      
368          *                                        
369          * We do this under the m_sb_lock so t    
370          * hold out any changes while we work     
371          * the amount of free space can change    
372          * retry if we end up trying to reserv    
373          */                                       
374         spin_lock(&mp->m_sb_lock);                
375                                                   
376         /*                                        
377          * If our previous reservation was lar    
378          * then move any unused blocks back to    
379          * counters directly since we shouldn'    
380          * space.                                 
381          */                                       
382         if (mp->m_resblks > request) {            
383                 lcounter = mp->m_resblks_avail    
384                 if (lcounter > 0) {               
385                         fdblks_delta = lcounte    
386                         mp->m_resblks_avail -=    
387                 }                                 
388                 mp->m_resblks = request;          
389                 if (fdblks_delta) {               
390                         spin_unlock(&mp->m_sb_    
391                         xfs_add_fdblocks(mp, f    
392                         spin_lock(&mp->m_sb_lo    
393                 }                                 
394                                                   
395                 goto out;                         
396         }                                         
397                                                   
398         /*                                        
399          * If the request is larger than the c    
400          * blocks before we update the reserve    
401          * perform a partial reservation if th    
402          *                                        
403          * The code below estimates how many b    
404          * fdblocks to stash in the reserve po    
405          * race since fdblocks updates are not    
406          * m_sb_lock.  Set the reserve size ev    
407          * space to fill it because mod_fdbloc    
408          * reserve when it can.                   
409          */                                       
410         free = percpu_counter_sum(&mp->m_fdblo    
411                                                   
412         delta = request - mp->m_resblks;          
413         mp->m_resblks = request;                  
414         if (delta > 0 && free > 0) {              
415                 /*                                
416                  * We'll either succeed in get    
417                  * count or we'll get an ENOSP    
418                  * here - we don't want to res    
419                  * from the reserve.              
420                  *                                
421                  * The desired reserve size ca    
422                  * Use mod_fdblocks to put the    
423                  * fdblocks as appropriate.       
424                  */                               
425                 fdblks_delta = min(free, delta    
426                 spin_unlock(&mp->m_sb_lock);      
427                 error = xfs_dec_fdblocks(mp, f    
428                 if (!error)                       
429                         xfs_add_fdblocks(mp, f    
430                 spin_lock(&mp->m_sb_lock);        
431         }                                         
432 out:                                              
433         spin_unlock(&mp->m_sb_lock);              
434         return error;                             
435 }                                                 
436                                                   
437 int                                               
438 xfs_fs_goingdown(                                 
439         xfs_mount_t     *mp,                      
440         uint32_t        inflags)                  
441 {                                                 
442         switch (inflags) {                        
443         case XFS_FSOP_GOING_FLAGS_DEFAULT: {      
444                 if (!bdev_freeze(mp->m_super->    
445                         xfs_force_shutdown(mp,    
446                         bdev_thaw(mp->m_super-    
447                 }                                 
448                 break;                            
449         }                                         
450         case XFS_FSOP_GOING_FLAGS_LOGFLUSH:       
451                 xfs_force_shutdown(mp, SHUTDOW    
452                 break;                            
453         case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:     
454                 xfs_force_shutdown(mp,            
455                                 SHUTDOWN_FORCE    
456                 break;                            
457         default:                                  
458                 return -EINVAL;                   
459         }                                         
460                                                   
461         return 0;                                 
462 }                                                 
463                                                   
464 /*                                                
465  * Force a shutdown of the filesystem instantl    
466  * consistent. We don't do an unmount here; ju    
467  * that absolutely nothing persistent happens     
468  * 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  */                                               
475 void                                              
476 xfs_do_force_shutdown(                            
477         struct xfs_mount *mp,                     
478         uint32_t        flags,                    
479         char            *fname,                   
480         int             lnnum)                    
481 {                                                 
482         int             tag;                      
483         const char      *why;                     
484                                                   
485                                                   
486         if (xfs_set_shutdown(mp)) {               
487                 xlog_shutdown_wait(mp->m_log);    
488                 return;                           
489         }                                         
490         if (mp->m_sb_bp)                          
491                 mp->m_sb_bp->b_flags |= XBF_DO    
492                                                   
493         if (flags & SHUTDOWN_FORCE_UMOUNT)        
494                 xfs_alert(mp, "User initiated     
495                                                   
496         if (xlog_force_shutdown(mp->m_log, fla    
497                 tag = XFS_PTAG_SHUTDOWN_LOGERR    
498                 why = "Log I/O Error";            
499         } else if (flags & SHUTDOWN_CORRUPT_IN    
500                 tag = XFS_PTAG_SHUTDOWN_CORRUP    
501                 why = "Corruption of in-memory    
502         } else if (flags & SHUTDOWN_CORRUPT_ON    
503                 tag = XFS_PTAG_SHUTDOWN_CORRUP    
504                 why = "Corruption of on-disk m    
505         } else if (flags & SHUTDOWN_DEVICE_REM    
506                 tag = XFS_PTAG_SHUTDOWN_IOERRO    
507                 why = "Block device removal";     
508         } else {                                  
509                 tag = XFS_PTAG_SHUTDOWN_IOERRO    
510                 why = "Metadata I/O Error";       
511         }                                         
512                                                   
513         trace_xfs_force_shutdown(mp, tag, flag    
514                                                   
515         xfs_alert_tag(mp, tag,                    
516 "%s (0x%x) detected at %pS (%s:%d).  Shutting     
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                                                   
524 /*                                                
525  * Reserve free space for per-AG metadata.        
526  */                                               
527 int                                               
528 xfs_fs_reserve_ag_blocks(                         
529         struct xfs_mount        *mp)              
530 {                                                 
531         xfs_agnumber_t          agno;             
532         struct xfs_perag        *pag;             
533         int                     error = 0;        
534         int                     err2;             
535                                                   
536         mp->m_finobt_nores = false;               
537         for_each_perag(mp, agno, pag) {           
538                 err2 = xfs_ag_resv_init(pag, N    
539                 if (err2 && !error)               
540                         error = err2;             
541         }                                         
542                                                   
543         if (error && error != -ENOSPC) {          
544                 xfs_warn(mp,                      
545         "Error %d reserving per-AG metadata re    
546                 xfs_force_shutdown(mp, SHUTDOW    
547         }                                         
548                                                   
549         return error;                             
550 }                                                 
551                                                   
552 /*                                                
553  * Free space reserved for per-AG metadata.       
554  */                                               
555 void                                              
556 xfs_fs_unreserve_ag_blocks(                       
557         struct xfs_mount        *mp)              
558 {                                                 
559         xfs_agnumber_t          agno;             
560         struct xfs_perag        *pag;             
561                                                   
562         for_each_perag(mp, agno, pag)             
563                 xfs_ag_resv_free(pag);            
564 }                                                 
565                                                   

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