11da177e4SLinus Torvalds /* 27b718769SNathan Scott * Copyright (c) 2000-2005 Silicon Graphics, Inc. 37b718769SNathan Scott * All Rights Reserved. 41da177e4SLinus Torvalds * 57b718769SNathan Scott * This program is free software; you can redistribute it and/or 67b718769SNathan Scott * modify it under the terms of the GNU General Public License as 71da177e4SLinus Torvalds * published by the Free Software Foundation. 81da177e4SLinus Torvalds * 97b718769SNathan Scott * This program is distributed in the hope that it would be useful, 107b718769SNathan Scott * but WITHOUT ANY WARRANTY; without even the implied warranty of 117b718769SNathan Scott * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 127b718769SNathan Scott * GNU General Public License for more details. 131da177e4SLinus Torvalds * 147b718769SNathan Scott * You should have received a copy of the GNU General Public License 157b718769SNathan Scott * along with this program; if not, write the Free Software Foundation, 167b718769SNathan Scott * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds #include "xfs.h" 19a844f451SNathan Scott #include "xfs_fs.h" 201da177e4SLinus Torvalds #include "xfs_types.h" 21a844f451SNathan Scott #include "xfs_bit.h" 221da177e4SLinus Torvalds #include "xfs_log.h" 23a844f451SNathan Scott #include "xfs_inum.h" 241da177e4SLinus Torvalds #include "xfs_trans.h" 25*211e4d43SChristoph Hellwig #include "xfs_trans_priv.h" 261da177e4SLinus Torvalds #include "xfs_sb.h" 271da177e4SLinus Torvalds #include "xfs_ag.h" 281da177e4SLinus Torvalds #include "xfs_dir2.h" 291da177e4SLinus Torvalds #include "xfs_mount.h" 301da177e4SLinus Torvalds #include "xfs_bmap_btree.h" 31a844f451SNathan Scott #include "xfs_alloc_btree.h" 321da177e4SLinus Torvalds #include "xfs_ialloc_btree.h" 331da177e4SLinus Torvalds #include "xfs_dinode.h" 341da177e4SLinus Torvalds #include "xfs_inode.h" 35a844f451SNathan Scott #include "xfs_btree.h" 36a844f451SNathan Scott #include "xfs_ialloc.h" 371da177e4SLinus Torvalds #include "xfs_alloc.h" 381da177e4SLinus Torvalds #include "xfs_rtalloc.h" 391da177e4SLinus Torvalds #include "xfs_bmap.h" 401da177e4SLinus Torvalds #include "xfs_error.h" 411da177e4SLinus Torvalds #include "xfs_rw.h" 421da177e4SLinus Torvalds #include "xfs_quota.h" 431da177e4SLinus Torvalds #include "xfs_fsops.h" 4443355099SChristoph Hellwig #include "xfs_utils.h" 450b1b213fSChristoph Hellwig #include "xfs_trace.h" 460b1b213fSChristoph Hellwig 471da177e4SLinus Torvalds 488d280b98SDavid Chinner #ifdef HAVE_PERCPU_SB 4920f4ebf2SDavid Chinner STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, 5045af6c6dSChristoph Hellwig int); 5145af6c6dSChristoph Hellwig STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t, 5245af6c6dSChristoph Hellwig int); 5336fbe6e6SDavid Chinner STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); 548d280b98SDavid Chinner #else 558d280b98SDavid Chinner 5645af6c6dSChristoph Hellwig #define xfs_icsb_balance_counter(mp, a, b) do { } while (0) 5745af6c6dSChristoph Hellwig #define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0) 588d280b98SDavid Chinner #endif 598d280b98SDavid Chinner 601df84c93SChristoph Hellwig static const struct { 611da177e4SLinus Torvalds short offset; 621da177e4SLinus Torvalds short type; /* 0 = integer 631da177e4SLinus Torvalds * 1 = binary / string (no translation) 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds } xfs_sb_info[] = { 661da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_magicnum), 0 }, 671da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_blocksize), 0 }, 681da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_dblocks), 0 }, 691da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rblocks), 0 }, 701da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rextents), 0 }, 711da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_uuid), 1 }, 721da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_logstart), 0 }, 731da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rootino), 0 }, 741da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rbmino), 0 }, 751da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rsumino), 0 }, 761da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rextsize), 0 }, 771da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_agblocks), 0 }, 781da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_agcount), 0 }, 791da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rbmblocks), 0 }, 801da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_logblocks), 0 }, 811da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_versionnum), 0 }, 821da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_sectsize), 0 }, 831da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inodesize), 0 }, 841da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inopblock), 0 }, 851da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_fname[0]), 1 }, 861da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_blocklog), 0 }, 871da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_sectlog), 0 }, 881da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inodelog), 0 }, 891da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inopblog), 0 }, 901da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_agblklog), 0 }, 911da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_rextslog), 0 }, 921da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inprogress), 0 }, 931da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_imax_pct), 0 }, 941da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_icount), 0 }, 951da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_ifree), 0 }, 961da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_fdblocks), 0 }, 971da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_frextents), 0 }, 981da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_uquotino), 0 }, 991da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_gquotino), 0 }, 1001da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_qflags), 0 }, 1011da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_flags), 0 }, 1021da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_shared_vn), 0 }, 1031da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_inoalignmt), 0 }, 1041da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_unit), 0 }, 1051da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_width), 0 }, 1061da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_dirblklog), 0 }, 1071da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_logsectlog), 0 }, 1081da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_logsectsize),0 }, 1091da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_logsunit), 0 }, 1101da177e4SLinus Torvalds { offsetof(xfs_sb_t, sb_features2), 0 }, 111ee1c0908SDavid Chinner { offsetof(xfs_sb_t, sb_bad_features2), 0 }, 1121da177e4SLinus Torvalds { sizeof(xfs_sb_t), 0 } 1131da177e4SLinus Torvalds }; 1141da177e4SLinus Torvalds 11527174203SChristoph Hellwig static DEFINE_MUTEX(xfs_uuid_table_mutex); 11627174203SChristoph Hellwig static int xfs_uuid_table_size; 11727174203SChristoph Hellwig static uuid_t *xfs_uuid_table; 11827174203SChristoph Hellwig 11927174203SChristoph Hellwig /* 12027174203SChristoph Hellwig * See if the UUID is unique among mounted XFS filesystems. 12127174203SChristoph Hellwig * Mount fails if UUID is nil or a FS with the same UUID is already mounted. 12227174203SChristoph Hellwig */ 12327174203SChristoph Hellwig STATIC int 12427174203SChristoph Hellwig xfs_uuid_mount( 12527174203SChristoph Hellwig struct xfs_mount *mp) 12627174203SChristoph Hellwig { 12727174203SChristoph Hellwig uuid_t *uuid = &mp->m_sb.sb_uuid; 12827174203SChristoph Hellwig int hole, i; 12927174203SChristoph Hellwig 13027174203SChristoph Hellwig if (mp->m_flags & XFS_MOUNT_NOUUID) 13127174203SChristoph Hellwig return 0; 13227174203SChristoph Hellwig 13327174203SChristoph Hellwig if (uuid_is_nil(uuid)) { 1340b932cccSDave Chinner xfs_warn(mp, "Filesystem has nil UUID - can't mount"); 13527174203SChristoph Hellwig return XFS_ERROR(EINVAL); 13627174203SChristoph Hellwig } 13727174203SChristoph Hellwig 13827174203SChristoph Hellwig mutex_lock(&xfs_uuid_table_mutex); 13927174203SChristoph Hellwig for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) { 14027174203SChristoph Hellwig if (uuid_is_nil(&xfs_uuid_table[i])) { 14127174203SChristoph Hellwig hole = i; 14227174203SChristoph Hellwig continue; 14327174203SChristoph Hellwig } 14427174203SChristoph Hellwig if (uuid_equal(uuid, &xfs_uuid_table[i])) 14527174203SChristoph Hellwig goto out_duplicate; 14627174203SChristoph Hellwig } 14727174203SChristoph Hellwig 14827174203SChristoph Hellwig if (hole < 0) { 14927174203SChristoph Hellwig xfs_uuid_table = kmem_realloc(xfs_uuid_table, 15027174203SChristoph Hellwig (xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table), 15127174203SChristoph Hellwig xfs_uuid_table_size * sizeof(*xfs_uuid_table), 15227174203SChristoph Hellwig KM_SLEEP); 15327174203SChristoph Hellwig hole = xfs_uuid_table_size++; 15427174203SChristoph Hellwig } 15527174203SChristoph Hellwig xfs_uuid_table[hole] = *uuid; 15627174203SChristoph Hellwig mutex_unlock(&xfs_uuid_table_mutex); 15727174203SChristoph Hellwig 15827174203SChristoph Hellwig return 0; 15927174203SChristoph Hellwig 16027174203SChristoph Hellwig out_duplicate: 16127174203SChristoph Hellwig mutex_unlock(&xfs_uuid_table_mutex); 162021000e5SMitsuo Hayasaka xfs_warn(mp, "Filesystem has duplicate UUID %pU - can't mount", uuid); 16327174203SChristoph Hellwig return XFS_ERROR(EINVAL); 16427174203SChristoph Hellwig } 16527174203SChristoph Hellwig 16627174203SChristoph Hellwig STATIC void 16727174203SChristoph Hellwig xfs_uuid_unmount( 16827174203SChristoph Hellwig struct xfs_mount *mp) 16927174203SChristoph Hellwig { 17027174203SChristoph Hellwig uuid_t *uuid = &mp->m_sb.sb_uuid; 17127174203SChristoph Hellwig int i; 17227174203SChristoph Hellwig 17327174203SChristoph Hellwig if (mp->m_flags & XFS_MOUNT_NOUUID) 17427174203SChristoph Hellwig return; 17527174203SChristoph Hellwig 17627174203SChristoph Hellwig mutex_lock(&xfs_uuid_table_mutex); 17727174203SChristoph Hellwig for (i = 0; i < xfs_uuid_table_size; i++) { 17827174203SChristoph Hellwig if (uuid_is_nil(&xfs_uuid_table[i])) 17927174203SChristoph Hellwig continue; 18027174203SChristoph Hellwig if (!uuid_equal(uuid, &xfs_uuid_table[i])) 18127174203SChristoph Hellwig continue; 18227174203SChristoph Hellwig memset(&xfs_uuid_table[i], 0, sizeof(uuid_t)); 18327174203SChristoph Hellwig break; 18427174203SChristoph Hellwig } 18527174203SChristoph Hellwig ASSERT(i < xfs_uuid_table_size); 18627174203SChristoph Hellwig mutex_unlock(&xfs_uuid_table_mutex); 18727174203SChristoph Hellwig } 18827174203SChristoph Hellwig 18927174203SChristoph Hellwig 1901da177e4SLinus Torvalds /* 1910fa800fbSDave Chinner * Reference counting access wrappers to the perag structures. 192e176579eSDave Chinner * Because we never free per-ag structures, the only thing we 193e176579eSDave Chinner * have to protect against changes is the tree structure itself. 1940fa800fbSDave Chinner */ 1950fa800fbSDave Chinner struct xfs_perag * 1960fa800fbSDave Chinner xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) 1970fa800fbSDave Chinner { 1980fa800fbSDave Chinner struct xfs_perag *pag; 1990fa800fbSDave Chinner int ref = 0; 2000fa800fbSDave Chinner 201e176579eSDave Chinner rcu_read_lock(); 2020fa800fbSDave Chinner pag = radix_tree_lookup(&mp->m_perag_tree, agno); 2030fa800fbSDave Chinner if (pag) { 2040fa800fbSDave Chinner ASSERT(atomic_read(&pag->pag_ref) >= 0); 2050fa800fbSDave Chinner ref = atomic_inc_return(&pag->pag_ref); 2060fa800fbSDave Chinner } 207e176579eSDave Chinner rcu_read_unlock(); 2080fa800fbSDave Chinner trace_xfs_perag_get(mp, agno, ref, _RET_IP_); 2090fa800fbSDave Chinner return pag; 2100fa800fbSDave Chinner } 2110fa800fbSDave Chinner 21265d0f205SDave Chinner /* 21365d0f205SDave Chinner * search from @first to find the next perag with the given tag set. 21465d0f205SDave Chinner */ 21565d0f205SDave Chinner struct xfs_perag * 21665d0f205SDave Chinner xfs_perag_get_tag( 21765d0f205SDave Chinner struct xfs_mount *mp, 21865d0f205SDave Chinner xfs_agnumber_t first, 21965d0f205SDave Chinner int tag) 22065d0f205SDave Chinner { 22165d0f205SDave Chinner struct xfs_perag *pag; 22265d0f205SDave Chinner int found; 22365d0f205SDave Chinner int ref; 22465d0f205SDave Chinner 22565d0f205SDave Chinner rcu_read_lock(); 22665d0f205SDave Chinner found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, 22765d0f205SDave Chinner (void **)&pag, first, 1, tag); 22865d0f205SDave Chinner if (found <= 0) { 22965d0f205SDave Chinner rcu_read_unlock(); 23065d0f205SDave Chinner return NULL; 23165d0f205SDave Chinner } 23265d0f205SDave Chinner ref = atomic_inc_return(&pag->pag_ref); 23365d0f205SDave Chinner rcu_read_unlock(); 23465d0f205SDave Chinner trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_); 23565d0f205SDave Chinner return pag; 23665d0f205SDave Chinner } 23765d0f205SDave Chinner 2380fa800fbSDave Chinner void 2390fa800fbSDave Chinner xfs_perag_put(struct xfs_perag *pag) 2400fa800fbSDave Chinner { 2410fa800fbSDave Chinner int ref; 2420fa800fbSDave Chinner 2430fa800fbSDave Chinner ASSERT(atomic_read(&pag->pag_ref) > 0); 2440fa800fbSDave Chinner ref = atomic_dec_return(&pag->pag_ref); 2450fa800fbSDave Chinner trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); 2460fa800fbSDave Chinner } 2470fa800fbSDave Chinner 248e176579eSDave Chinner STATIC void 249e176579eSDave Chinner __xfs_free_perag( 250e176579eSDave Chinner struct rcu_head *head) 251e176579eSDave Chinner { 252e176579eSDave Chinner struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head); 253e176579eSDave Chinner 254e176579eSDave Chinner ASSERT(atomic_read(&pag->pag_ref) == 0); 255e176579eSDave Chinner kmem_free(pag); 256e176579eSDave Chinner } 257e176579eSDave Chinner 2580fa800fbSDave Chinner /* 259e176579eSDave Chinner * Free up the per-ag resources associated with the mount structure. 2601da177e4SLinus Torvalds */ 261c962fb79SChristoph Hellwig STATIC void 262ff4f038cSChristoph Hellwig xfs_free_perag( 263745f6919SChristoph Hellwig xfs_mount_t *mp) 2641da177e4SLinus Torvalds { 2651c1c6ebcSDave Chinner xfs_agnumber_t agno; 2661c1c6ebcSDave Chinner struct xfs_perag *pag; 2671da177e4SLinus Torvalds 2681c1c6ebcSDave Chinner for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { 2691c1c6ebcSDave Chinner spin_lock(&mp->m_perag_lock); 2701c1c6ebcSDave Chinner pag = radix_tree_delete(&mp->m_perag_tree, agno); 2711c1c6ebcSDave Chinner spin_unlock(&mp->m_perag_lock); 272e176579eSDave Chinner ASSERT(pag); 273f83282a8SDave Chinner ASSERT(atomic_read(&pag->pag_ref) == 0); 274e176579eSDave Chinner call_rcu(&pag->rcu_head, __xfs_free_perag); 2751da177e4SLinus Torvalds } 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 2784cc929eeSNathan Scott /* 2794cc929eeSNathan Scott * Check size of device based on the (data/realtime) block count. 2804cc929eeSNathan Scott * Note: this check is used by the growfs code as well as mount. 2814cc929eeSNathan Scott */ 2824cc929eeSNathan Scott int 2834cc929eeSNathan Scott xfs_sb_validate_fsb_count( 2844cc929eeSNathan Scott xfs_sb_t *sbp, 2854cc929eeSNathan Scott __uint64_t nblocks) 2864cc929eeSNathan Scott { 2874cc929eeSNathan Scott ASSERT(PAGE_SHIFT >= sbp->sb_blocklog); 2884cc929eeSNathan Scott ASSERT(sbp->sb_blocklog >= BBSHIFT); 2894cc929eeSNathan Scott 2904cc929eeSNathan Scott #if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ 2914cc929eeSNathan Scott if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX) 292657a4cffSEric Sandeen return EFBIG; 2934cc929eeSNathan Scott #else /* Limited by UINT_MAX of sectors */ 2944cc929eeSNathan Scott if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX) 295657a4cffSEric Sandeen return EFBIG; 2964cc929eeSNathan Scott #endif 2974cc929eeSNathan Scott return 0; 2984cc929eeSNathan Scott } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds /* 3011da177e4SLinus Torvalds * Check the validity of the SB found. 3021da177e4SLinus Torvalds */ 3031da177e4SLinus Torvalds STATIC int 3041da177e4SLinus Torvalds xfs_mount_validate_sb( 3051da177e4SLinus Torvalds xfs_mount_t *mp, 306764d1f89SNathan Scott xfs_sb_t *sbp, 307764d1f89SNathan Scott int flags) 3081da177e4SLinus Torvalds { 309af34e09dSDave Chinner int loud = !(flags & XFS_MFSI_QUIET); 310af34e09dSDave Chinner 3111da177e4SLinus Torvalds /* 3121da177e4SLinus Torvalds * If the log device and data device have the 3131da177e4SLinus Torvalds * same device number, the log is internal. 3141da177e4SLinus Torvalds * Consequently, the sb_logstart should be non-zero. If 3151da177e4SLinus Torvalds * we have a zero sb_logstart in this case, we may be trying to mount 3161da177e4SLinus Torvalds * a volume filesystem in a non-volume manner. 3171da177e4SLinus Torvalds */ 3181da177e4SLinus Torvalds if (sbp->sb_magicnum != XFS_SB_MAGIC) { 319af34e09dSDave Chinner if (loud) 320af34e09dSDave Chinner xfs_warn(mp, "bad magic number"); 3211da177e4SLinus Torvalds return XFS_ERROR(EWRONGFS); 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds 32462118709SEric Sandeen if (!xfs_sb_good_version(sbp)) { 325af34e09dSDave Chinner if (loud) 326af34e09dSDave Chinner xfs_warn(mp, "bad version"); 3271da177e4SLinus Torvalds return XFS_ERROR(EWRONGFS); 3281da177e4SLinus Torvalds } 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds if (unlikely( 3311da177e4SLinus Torvalds sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { 332af34e09dSDave Chinner if (loud) 333af34e09dSDave Chinner xfs_warn(mp, 334764d1f89SNathan Scott "filesystem is marked as having an external log; " 335af34e09dSDave Chinner "specify logdev on the mount command line."); 336764d1f89SNathan Scott return XFS_ERROR(EINVAL); 3371da177e4SLinus Torvalds } 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds if (unlikely( 3401da177e4SLinus Torvalds sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { 341af34e09dSDave Chinner if (loud) 342af34e09dSDave Chinner xfs_warn(mp, 343764d1f89SNathan Scott "filesystem is marked as having an internal log; " 344af34e09dSDave Chinner "do not specify logdev on the mount command line."); 345764d1f89SNathan Scott return XFS_ERROR(EINVAL); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds 3481da177e4SLinus Torvalds /* 349c0e090ceSEric Sandeen * More sanity checking. Most of these were stolen directly from 3501da177e4SLinus Torvalds * xfs_repair. 3511da177e4SLinus Torvalds */ 3521da177e4SLinus Torvalds if (unlikely( 3531da177e4SLinus Torvalds sbp->sb_agcount <= 0 || 3541da177e4SLinus Torvalds sbp->sb_sectsize < XFS_MIN_SECTORSIZE || 3551da177e4SLinus Torvalds sbp->sb_sectsize > XFS_MAX_SECTORSIZE || 3561da177e4SLinus Torvalds sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || 3571da177e4SLinus Torvalds sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || 3582ac00af7SOlaf Weber sbp->sb_sectsize != (1 << sbp->sb_sectlog) || 3591da177e4SLinus Torvalds sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || 3601da177e4SLinus Torvalds sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || 3611da177e4SLinus Torvalds sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || 3621da177e4SLinus Torvalds sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || 3632ac00af7SOlaf Weber sbp->sb_blocksize != (1 << sbp->sb_blocklog) || 3641da177e4SLinus Torvalds sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || 3651da177e4SLinus Torvalds sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || 3669f989c94SNathan Scott sbp->sb_inodelog < XFS_DINODE_MIN_LOG || 3679f989c94SNathan Scott sbp->sb_inodelog > XFS_DINODE_MAX_LOG || 3682ac00af7SOlaf Weber sbp->sb_inodesize != (1 << sbp->sb_inodelog) || 3699f989c94SNathan Scott (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || 3701da177e4SLinus Torvalds (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || 3711da177e4SLinus Torvalds (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || 372c0e090ceSEric Sandeen (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || 3731da177e4SLinus Torvalds sbp->sb_dblocks == 0 || 374c0e090ceSEric Sandeen sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || 375c0e090ceSEric Sandeen sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) { 376af34e09dSDave Chinner if (loud) 377c0e090ceSEric Sandeen XFS_CORRUPTION_ERROR("SB sanity check failed", 378c0e090ceSEric Sandeen XFS_ERRLEVEL_LOW, mp, sbp); 3791da177e4SLinus Torvalds return XFS_ERROR(EFSCORRUPTED); 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds 3822edbddd5SLachlan McIlroy /* 3832edbddd5SLachlan McIlroy * Until this is fixed only page-sized or smaller data blocks work. 3842edbddd5SLachlan McIlroy */ 3852edbddd5SLachlan McIlroy if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { 386af34e09dSDave Chinner if (loud) { 387af34e09dSDave Chinner xfs_warn(mp, 388af34e09dSDave Chinner "File system with blocksize %d bytes. " 389af34e09dSDave Chinner "Only pagesize (%ld) or less will currently work.", 390af34e09dSDave Chinner sbp->sb_blocksize, PAGE_SIZE); 391af34e09dSDave Chinner } 3922edbddd5SLachlan McIlroy return XFS_ERROR(ENOSYS); 3932edbddd5SLachlan McIlroy } 3942edbddd5SLachlan McIlroy 3951a5902c5SChristoph Hellwig /* 3961a5902c5SChristoph Hellwig * Currently only very few inode sizes are supported. 3971a5902c5SChristoph Hellwig */ 3981a5902c5SChristoph Hellwig switch (sbp->sb_inodesize) { 3991a5902c5SChristoph Hellwig case 256: 4001a5902c5SChristoph Hellwig case 512: 4011a5902c5SChristoph Hellwig case 1024: 4021a5902c5SChristoph Hellwig case 2048: 4031a5902c5SChristoph Hellwig break; 4041a5902c5SChristoph Hellwig default: 405af34e09dSDave Chinner if (loud) 406af34e09dSDave Chinner xfs_warn(mp, "inode size of %d bytes not supported", 4071a5902c5SChristoph Hellwig sbp->sb_inodesize); 4081a5902c5SChristoph Hellwig return XFS_ERROR(ENOSYS); 4091a5902c5SChristoph Hellwig } 4101a5902c5SChristoph Hellwig 4114cc929eeSNathan Scott if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || 4124cc929eeSNathan Scott xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { 413af34e09dSDave Chinner if (loud) 414af34e09dSDave Chinner xfs_warn(mp, 415764d1f89SNathan Scott "file system too large to be mounted on this system."); 416657a4cffSEric Sandeen return XFS_ERROR(EFBIG); 4171da177e4SLinus Torvalds } 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds if (unlikely(sbp->sb_inprogress)) { 420af34e09dSDave Chinner if (loud) 421af34e09dSDave Chinner xfs_warn(mp, "file system busy"); 4221da177e4SLinus Torvalds return XFS_ERROR(EFSCORRUPTED); 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds 4251da177e4SLinus Torvalds /* 426de20614bSNathan Scott * Version 1 directory format has never worked on Linux. 427de20614bSNathan Scott */ 42862118709SEric Sandeen if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { 429af34e09dSDave Chinner if (loud) 430af34e09dSDave Chinner xfs_warn(mp, 431764d1f89SNathan Scott "file system using version 1 directory format"); 432de20614bSNathan Scott return XFS_ERROR(ENOSYS); 433de20614bSNathan Scott } 434de20614bSNathan Scott 4351da177e4SLinus Torvalds return 0; 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds 4381c1c6ebcSDave Chinner int 439c11e2c36SNathan Scott xfs_initialize_perag( 440c11e2c36SNathan Scott xfs_mount_t *mp, 4411c1c6ebcSDave Chinner xfs_agnumber_t agcount, 4421c1c6ebcSDave Chinner xfs_agnumber_t *maxagi) 4431da177e4SLinus Torvalds { 4441da177e4SLinus Torvalds xfs_agnumber_t index, max_metadata; 4458b26c582SDave Chinner xfs_agnumber_t first_initialised = 0; 4461da177e4SLinus Torvalds xfs_perag_t *pag; 4471da177e4SLinus Torvalds xfs_agino_t agino; 4481da177e4SLinus Torvalds xfs_ino_t ino; 4491da177e4SLinus Torvalds xfs_sb_t *sbp = &mp->m_sb; 4508b26c582SDave Chinner int error = -ENOMEM; 4511da177e4SLinus Torvalds 4521c1c6ebcSDave Chinner /* 4531c1c6ebcSDave Chinner * Walk the current per-ag tree so we don't try to initialise AGs 4541c1c6ebcSDave Chinner * that already exist (growfs case). Allocate and insert all the 4551c1c6ebcSDave Chinner * AGs we don't find ready for initialisation. 4561c1c6ebcSDave Chinner */ 4571c1c6ebcSDave Chinner for (index = 0; index < agcount; index++) { 4581c1c6ebcSDave Chinner pag = xfs_perag_get(mp, index); 4591c1c6ebcSDave Chinner if (pag) { 4601c1c6ebcSDave Chinner xfs_perag_put(pag); 4611c1c6ebcSDave Chinner continue; 4621c1c6ebcSDave Chinner } 4638b26c582SDave Chinner if (!first_initialised) 4648b26c582SDave Chinner first_initialised = index; 465fb3b504aSChristoph Hellwig 4661c1c6ebcSDave Chinner pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); 4671c1c6ebcSDave Chinner if (!pag) 4688b26c582SDave Chinner goto out_unwind; 469fb3b504aSChristoph Hellwig pag->pag_agno = index; 470fb3b504aSChristoph Hellwig pag->pag_mount = mp; 4711a427ab0SDave Chinner spin_lock_init(&pag->pag_ici_lock); 47269b491c2SDave Chinner mutex_init(&pag->pag_ici_reclaim_lock); 473fb3b504aSChristoph Hellwig INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); 47474f75a0cSDave Chinner spin_lock_init(&pag->pag_buf_lock); 47574f75a0cSDave Chinner pag->pag_buf_tree = RB_ROOT; 476fb3b504aSChristoph Hellwig 4771c1c6ebcSDave Chinner if (radix_tree_preload(GFP_NOFS)) 4788b26c582SDave Chinner goto out_unwind; 479fb3b504aSChristoph Hellwig 4801c1c6ebcSDave Chinner spin_lock(&mp->m_perag_lock); 4811c1c6ebcSDave Chinner if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { 4821c1c6ebcSDave Chinner BUG(); 4831c1c6ebcSDave Chinner spin_unlock(&mp->m_perag_lock); 4848b26c582SDave Chinner radix_tree_preload_end(); 4858b26c582SDave Chinner error = -EEXIST; 4868b26c582SDave Chinner goto out_unwind; 4871c1c6ebcSDave Chinner } 4881c1c6ebcSDave Chinner spin_unlock(&mp->m_perag_lock); 4891c1c6ebcSDave Chinner radix_tree_preload_end(); 4901c1c6ebcSDave Chinner } 4911c1c6ebcSDave Chinner 492fb3b504aSChristoph Hellwig /* 493fb3b504aSChristoph Hellwig * If we mount with the inode64 option, or no inode overflows 494fb3b504aSChristoph Hellwig * the legacy 32-bit address space clear the inode32 option. 4951da177e4SLinus Torvalds */ 496fb3b504aSChristoph Hellwig agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); 497fb3b504aSChristoph Hellwig ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); 4981da177e4SLinus Torvalds 499fb3b504aSChristoph Hellwig if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32) 500fb3b504aSChristoph Hellwig mp->m_flags |= XFS_MOUNT_32BITINODES; 501fb3b504aSChristoph Hellwig else 502fb3b504aSChristoph Hellwig mp->m_flags &= ~XFS_MOUNT_32BITINODES; 503fb3b504aSChristoph Hellwig 5041da177e4SLinus Torvalds if (mp->m_flags & XFS_MOUNT_32BITINODES) { 505fb3b504aSChristoph Hellwig /* 506fb3b504aSChristoph Hellwig * Calculate how much should be reserved for inodes to meet 507fb3b504aSChristoph Hellwig * the max inode percentage. 5081da177e4SLinus Torvalds */ 5091da177e4SLinus Torvalds if (mp->m_maxicount) { 5101da177e4SLinus Torvalds __uint64_t icount; 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds icount = sbp->sb_dblocks * sbp->sb_imax_pct; 5131da177e4SLinus Torvalds do_div(icount, 100); 5141da177e4SLinus Torvalds icount += sbp->sb_agblocks - 1; 515a749ee86SEric Sandeen do_div(icount, sbp->sb_agblocks); 5161da177e4SLinus Torvalds max_metadata = icount; 5171da177e4SLinus Torvalds } else { 5181da177e4SLinus Torvalds max_metadata = agcount; 5191da177e4SLinus Torvalds } 520fb3b504aSChristoph Hellwig 5211da177e4SLinus Torvalds for (index = 0; index < agcount; index++) { 5221da177e4SLinus Torvalds ino = XFS_AGINO_TO_INO(mp, index, agino); 523fb3b504aSChristoph Hellwig if (ino > XFS_MAXINUMBER_32) { 5241da177e4SLinus Torvalds index++; 5251da177e4SLinus Torvalds break; 5261da177e4SLinus Torvalds } 5271da177e4SLinus Torvalds 52844b56e0aSDave Chinner pag = xfs_perag_get(mp, index); 5291da177e4SLinus Torvalds pag->pagi_inodeok = 1; 5301da177e4SLinus Torvalds if (index < max_metadata) 5311da177e4SLinus Torvalds pag->pagf_metadata = 1; 53244b56e0aSDave Chinner xfs_perag_put(pag); 5331da177e4SLinus Torvalds } 5341da177e4SLinus Torvalds } else { 5351da177e4SLinus Torvalds for (index = 0; index < agcount; index++) { 53644b56e0aSDave Chinner pag = xfs_perag_get(mp, index); 5371da177e4SLinus Torvalds pag->pagi_inodeok = 1; 53844b56e0aSDave Chinner xfs_perag_put(pag); 5391da177e4SLinus Torvalds } 5401da177e4SLinus Torvalds } 541fb3b504aSChristoph Hellwig 5421c1c6ebcSDave Chinner if (maxagi) 5431c1c6ebcSDave Chinner *maxagi = index; 5441c1c6ebcSDave Chinner return 0; 5458b26c582SDave Chinner 5468b26c582SDave Chinner out_unwind: 5478b26c582SDave Chinner kmem_free(pag); 5488b26c582SDave Chinner for (; index > first_initialised; index--) { 5498b26c582SDave Chinner pag = radix_tree_delete(&mp->m_perag_tree, index); 5508b26c582SDave Chinner kmem_free(pag); 5518b26c582SDave Chinner } 5528b26c582SDave Chinner return error; 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds 5552bdf7cd0SChristoph Hellwig void 5562bdf7cd0SChristoph Hellwig xfs_sb_from_disk( 5576bd92a23SChandra Seetharaman struct xfs_mount *mp, 5582bdf7cd0SChristoph Hellwig xfs_dsb_t *from) 5592bdf7cd0SChristoph Hellwig { 5606bd92a23SChandra Seetharaman struct xfs_sb *to = &mp->m_sb; 5616bd92a23SChandra Seetharaman 5622bdf7cd0SChristoph Hellwig to->sb_magicnum = be32_to_cpu(from->sb_magicnum); 5632bdf7cd0SChristoph Hellwig to->sb_blocksize = be32_to_cpu(from->sb_blocksize); 5642bdf7cd0SChristoph Hellwig to->sb_dblocks = be64_to_cpu(from->sb_dblocks); 5652bdf7cd0SChristoph Hellwig to->sb_rblocks = be64_to_cpu(from->sb_rblocks); 5662bdf7cd0SChristoph Hellwig to->sb_rextents = be64_to_cpu(from->sb_rextents); 5672bdf7cd0SChristoph Hellwig memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid)); 5682bdf7cd0SChristoph Hellwig to->sb_logstart = be64_to_cpu(from->sb_logstart); 5692bdf7cd0SChristoph Hellwig to->sb_rootino = be64_to_cpu(from->sb_rootino); 5702bdf7cd0SChristoph Hellwig to->sb_rbmino = be64_to_cpu(from->sb_rbmino); 5712bdf7cd0SChristoph Hellwig to->sb_rsumino = be64_to_cpu(from->sb_rsumino); 5722bdf7cd0SChristoph Hellwig to->sb_rextsize = be32_to_cpu(from->sb_rextsize); 5732bdf7cd0SChristoph Hellwig to->sb_agblocks = be32_to_cpu(from->sb_agblocks); 5742bdf7cd0SChristoph Hellwig to->sb_agcount = be32_to_cpu(from->sb_agcount); 5752bdf7cd0SChristoph Hellwig to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); 5762bdf7cd0SChristoph Hellwig to->sb_logblocks = be32_to_cpu(from->sb_logblocks); 5772bdf7cd0SChristoph Hellwig to->sb_versionnum = be16_to_cpu(from->sb_versionnum); 5782bdf7cd0SChristoph Hellwig to->sb_sectsize = be16_to_cpu(from->sb_sectsize); 5792bdf7cd0SChristoph Hellwig to->sb_inodesize = be16_to_cpu(from->sb_inodesize); 5802bdf7cd0SChristoph Hellwig to->sb_inopblock = be16_to_cpu(from->sb_inopblock); 5812bdf7cd0SChristoph Hellwig memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname)); 5822bdf7cd0SChristoph Hellwig to->sb_blocklog = from->sb_blocklog; 5832bdf7cd0SChristoph Hellwig to->sb_sectlog = from->sb_sectlog; 5842bdf7cd0SChristoph Hellwig to->sb_inodelog = from->sb_inodelog; 5852bdf7cd0SChristoph Hellwig to->sb_inopblog = from->sb_inopblog; 5862bdf7cd0SChristoph Hellwig to->sb_agblklog = from->sb_agblklog; 5872bdf7cd0SChristoph Hellwig to->sb_rextslog = from->sb_rextslog; 5882bdf7cd0SChristoph Hellwig to->sb_inprogress = from->sb_inprogress; 5892bdf7cd0SChristoph Hellwig to->sb_imax_pct = from->sb_imax_pct; 5902bdf7cd0SChristoph Hellwig to->sb_icount = be64_to_cpu(from->sb_icount); 5912bdf7cd0SChristoph Hellwig to->sb_ifree = be64_to_cpu(from->sb_ifree); 5922bdf7cd0SChristoph Hellwig to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); 5932bdf7cd0SChristoph Hellwig to->sb_frextents = be64_to_cpu(from->sb_frextents); 5942bdf7cd0SChristoph Hellwig to->sb_uquotino = be64_to_cpu(from->sb_uquotino); 5952bdf7cd0SChristoph Hellwig to->sb_gquotino = be64_to_cpu(from->sb_gquotino); 5962bdf7cd0SChristoph Hellwig to->sb_qflags = be16_to_cpu(from->sb_qflags); 5972bdf7cd0SChristoph Hellwig to->sb_flags = from->sb_flags; 5982bdf7cd0SChristoph Hellwig to->sb_shared_vn = from->sb_shared_vn; 5992bdf7cd0SChristoph Hellwig to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt); 6002bdf7cd0SChristoph Hellwig to->sb_unit = be32_to_cpu(from->sb_unit); 6012bdf7cd0SChristoph Hellwig to->sb_width = be32_to_cpu(from->sb_width); 6022bdf7cd0SChristoph Hellwig to->sb_dirblklog = from->sb_dirblklog; 6032bdf7cd0SChristoph Hellwig to->sb_logsectlog = from->sb_logsectlog; 6042bdf7cd0SChristoph Hellwig to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); 6052bdf7cd0SChristoph Hellwig to->sb_logsunit = be32_to_cpu(from->sb_logsunit); 6062bdf7cd0SChristoph Hellwig to->sb_features2 = be32_to_cpu(from->sb_features2); 607ee1c0908SDavid Chinner to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); 6082bdf7cd0SChristoph Hellwig } 6092bdf7cd0SChristoph Hellwig 6101da177e4SLinus Torvalds /* 6112bdf7cd0SChristoph Hellwig * Copy in core superblock to ondisk one. 6121da177e4SLinus Torvalds * 6132bdf7cd0SChristoph Hellwig * The fields argument is mask of superblock fields to copy. 6141da177e4SLinus Torvalds */ 6151da177e4SLinus Torvalds void 6162bdf7cd0SChristoph Hellwig xfs_sb_to_disk( 6172bdf7cd0SChristoph Hellwig xfs_dsb_t *to, 6182bdf7cd0SChristoph Hellwig xfs_sb_t *from, 6191da177e4SLinus Torvalds __int64_t fields) 6201da177e4SLinus Torvalds { 6212bdf7cd0SChristoph Hellwig xfs_caddr_t to_ptr = (xfs_caddr_t)to; 6222bdf7cd0SChristoph Hellwig xfs_caddr_t from_ptr = (xfs_caddr_t)from; 6231da177e4SLinus Torvalds xfs_sb_field_t f; 6241da177e4SLinus Torvalds int first; 6251da177e4SLinus Torvalds int size; 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvalds ASSERT(fields); 6281da177e4SLinus Torvalds if (!fields) 6291da177e4SLinus Torvalds return; 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds while (fields) { 6321da177e4SLinus Torvalds f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); 6331da177e4SLinus Torvalds first = xfs_sb_info[f].offset; 6341da177e4SLinus Torvalds size = xfs_sb_info[f + 1].offset - first; 6351da177e4SLinus Torvalds 6361da177e4SLinus Torvalds ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1); 6371da177e4SLinus Torvalds 6381da177e4SLinus Torvalds if (size == 1 || xfs_sb_info[f].type == 1) { 6392bdf7cd0SChristoph Hellwig memcpy(to_ptr + first, from_ptr + first, size); 6401da177e4SLinus Torvalds } else { 6411da177e4SLinus Torvalds switch (size) { 6421da177e4SLinus Torvalds case 2: 6432bdf7cd0SChristoph Hellwig *(__be16 *)(to_ptr + first) = 6442bdf7cd0SChristoph Hellwig cpu_to_be16(*(__u16 *)(from_ptr + first)); 6451da177e4SLinus Torvalds break; 6461da177e4SLinus Torvalds case 4: 6472bdf7cd0SChristoph Hellwig *(__be32 *)(to_ptr + first) = 6482bdf7cd0SChristoph Hellwig cpu_to_be32(*(__u32 *)(from_ptr + first)); 6491da177e4SLinus Torvalds break; 6501da177e4SLinus Torvalds case 8: 6512bdf7cd0SChristoph Hellwig *(__be64 *)(to_ptr + first) = 6522bdf7cd0SChristoph Hellwig cpu_to_be64(*(__u64 *)(from_ptr + first)); 6531da177e4SLinus Torvalds break; 6541da177e4SLinus Torvalds default: 6551da177e4SLinus Torvalds ASSERT(0); 6561da177e4SLinus Torvalds } 6571da177e4SLinus Torvalds } 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds fields &= ~(1LL << f); 6601da177e4SLinus Torvalds } 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds /* 6641da177e4SLinus Torvalds * xfs_readsb 6651da177e4SLinus Torvalds * 6661da177e4SLinus Torvalds * Does the initial read of the superblock. 6671da177e4SLinus Torvalds */ 6681da177e4SLinus Torvalds int 669764d1f89SNathan Scott xfs_readsb(xfs_mount_t *mp, int flags) 6701da177e4SLinus Torvalds { 6711da177e4SLinus Torvalds unsigned int sector_size; 6721da177e4SLinus Torvalds xfs_buf_t *bp; 6731da177e4SLinus Torvalds int error; 674af34e09dSDave Chinner int loud = !(flags & XFS_MFSI_QUIET); 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds ASSERT(mp->m_sb_bp == NULL); 6771da177e4SLinus Torvalds ASSERT(mp->m_ddev_targp != NULL); 6781da177e4SLinus Torvalds 6791da177e4SLinus Torvalds /* 6801da177e4SLinus Torvalds * Allocate a (locked) buffer to hold the superblock. 6811da177e4SLinus Torvalds * This will be kept around at all times to optimize 6821da177e4SLinus Torvalds * access to the superblock. 6831da177e4SLinus Torvalds */ 6841da177e4SLinus Torvalds sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); 6851da177e4SLinus Torvalds 68626af6552SDave Chinner reread: 68726af6552SDave Chinner bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, 68826af6552SDave Chinner XFS_SB_DADDR, sector_size, 0); 68926af6552SDave Chinner if (!bp) { 690af34e09dSDave Chinner if (loud) 691af34e09dSDave Chinner xfs_warn(mp, "SB buffer read failed"); 69226af6552SDave Chinner return EIO; 6931da177e4SLinus Torvalds } 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds /* 6961da177e4SLinus Torvalds * Initialize the mount structure from the superblock. 6971da177e4SLinus Torvalds * But first do some basic consistency checking. 6981da177e4SLinus Torvalds */ 6996bd92a23SChandra Seetharaman xfs_sb_from_disk(mp, XFS_BUF_TO_SBP(bp)); 700764d1f89SNathan Scott error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); 7011da177e4SLinus Torvalds if (error) { 702af34e09dSDave Chinner if (loud) 703af34e09dSDave Chinner xfs_warn(mp, "SB validate failed"); 70426af6552SDave Chinner goto release_buf; 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 7071da177e4SLinus Torvalds /* 7081da177e4SLinus Torvalds * We must be able to do sector-sized and sector-aligned IO. 7091da177e4SLinus Torvalds */ 7101da177e4SLinus Torvalds if (sector_size > mp->m_sb.sb_sectsize) { 711af34e09dSDave Chinner if (loud) 712af34e09dSDave Chinner xfs_warn(mp, "device supports %u byte sectors (not %u)", 7131da177e4SLinus Torvalds sector_size, mp->m_sb.sb_sectsize); 7141da177e4SLinus Torvalds error = ENOSYS; 71526af6552SDave Chinner goto release_buf; 7161da177e4SLinus Torvalds } 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds /* 7191da177e4SLinus Torvalds * If device sector size is smaller than the superblock size, 7201da177e4SLinus Torvalds * re-read the superblock so the buffer is correctly sized. 7211da177e4SLinus Torvalds */ 7221da177e4SLinus Torvalds if (sector_size < mp->m_sb.sb_sectsize) { 7231da177e4SLinus Torvalds xfs_buf_relse(bp); 7241da177e4SLinus Torvalds sector_size = mp->m_sb.sb_sectsize; 72526af6552SDave Chinner goto reread; 7261da177e4SLinus Torvalds } 7271da177e4SLinus Torvalds 7285478eeadSLachlan McIlroy /* Initialize per-cpu counters */ 7295478eeadSLachlan McIlroy xfs_icsb_reinit_counters(mp); 7308d280b98SDavid Chinner 7311da177e4SLinus Torvalds mp->m_sb_bp = bp; 73226af6552SDave Chinner xfs_buf_unlock(bp); 7331da177e4SLinus Torvalds return 0; 7341da177e4SLinus Torvalds 73526af6552SDave Chinner release_buf: 7361da177e4SLinus Torvalds xfs_buf_relse(bp); 7371da177e4SLinus Torvalds return error; 7381da177e4SLinus Torvalds } 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds 7411da177e4SLinus Torvalds /* 7421da177e4SLinus Torvalds * xfs_mount_common 7431da177e4SLinus Torvalds * 7441da177e4SLinus Torvalds * Mount initialization code establishing various mount 7451da177e4SLinus Torvalds * fields from the superblock associated with the given 7461da177e4SLinus Torvalds * mount structure 7471da177e4SLinus Torvalds */ 748ba0f32d4SChristoph Hellwig STATIC void 7491da177e4SLinus Torvalds xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) 7501da177e4SLinus Torvalds { 7511da177e4SLinus Torvalds mp->m_agfrotor = mp->m_agirotor = 0; 752007c61c6SEric Sandeen spin_lock_init(&mp->m_agirotor_lock); 7531da177e4SLinus Torvalds mp->m_maxagi = mp->m_sb.sb_agcount; 7541da177e4SLinus Torvalds mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG; 7551da177e4SLinus Torvalds mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; 7561da177e4SLinus Torvalds mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; 7571da177e4SLinus Torvalds mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; 7581da177e4SLinus Torvalds mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; 7591da177e4SLinus Torvalds mp->m_blockmask = sbp->sb_blocksize - 1; 7601da177e4SLinus Torvalds mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; 7611da177e4SLinus Torvalds mp->m_blockwmask = mp->m_blockwsize - 1; 7621da177e4SLinus Torvalds 76360197e8dSChristoph Hellwig mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); 76460197e8dSChristoph Hellwig mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); 76560197e8dSChristoph Hellwig mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; 76660197e8dSChristoph Hellwig mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2; 76760197e8dSChristoph Hellwig 76860197e8dSChristoph Hellwig mp->m_inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1); 76960197e8dSChristoph Hellwig mp->m_inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0); 77060197e8dSChristoph Hellwig mp->m_inobt_mnr[0] = mp->m_inobt_mxr[0] / 2; 77160197e8dSChristoph Hellwig mp->m_inobt_mnr[1] = mp->m_inobt_mxr[1] / 2; 77260197e8dSChristoph Hellwig 77360197e8dSChristoph Hellwig mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1); 77460197e8dSChristoph Hellwig mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0); 77560197e8dSChristoph Hellwig mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; 77660197e8dSChristoph Hellwig mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; 7771da177e4SLinus Torvalds 7781da177e4SLinus Torvalds mp->m_bsize = XFS_FSB_TO_BB(mp, 1); 7791da177e4SLinus Torvalds mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, 7801da177e4SLinus Torvalds sbp->sb_inopblock); 7811da177e4SLinus Torvalds mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog; 7821da177e4SLinus Torvalds } 78392821e2bSDavid Chinner 78492821e2bSDavid Chinner /* 78592821e2bSDavid Chinner * xfs_initialize_perag_data 78692821e2bSDavid Chinner * 78792821e2bSDavid Chinner * Read in each per-ag structure so we can count up the number of 78892821e2bSDavid Chinner * allocated inodes, free inodes and used filesystem blocks as this 78992821e2bSDavid Chinner * information is no longer persistent in the superblock. Once we have 79092821e2bSDavid Chinner * this information, write it into the in-core superblock structure. 79192821e2bSDavid Chinner */ 79292821e2bSDavid Chinner STATIC int 79392821e2bSDavid Chinner xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) 79492821e2bSDavid Chinner { 79592821e2bSDavid Chinner xfs_agnumber_t index; 79692821e2bSDavid Chinner xfs_perag_t *pag; 79792821e2bSDavid Chinner xfs_sb_t *sbp = &mp->m_sb; 79892821e2bSDavid Chinner uint64_t ifree = 0; 79992821e2bSDavid Chinner uint64_t ialloc = 0; 80092821e2bSDavid Chinner uint64_t bfree = 0; 80192821e2bSDavid Chinner uint64_t bfreelst = 0; 80292821e2bSDavid Chinner uint64_t btree = 0; 80392821e2bSDavid Chinner int error; 80492821e2bSDavid Chinner 80592821e2bSDavid Chinner for (index = 0; index < agcount; index++) { 80692821e2bSDavid Chinner /* 80792821e2bSDavid Chinner * read the agf, then the agi. This gets us 8089da096fdSMalcolm Parsons * all the information we need and populates the 80992821e2bSDavid Chinner * per-ag structures for us. 81092821e2bSDavid Chinner */ 81192821e2bSDavid Chinner error = xfs_alloc_pagf_init(mp, NULL, index, 0); 81292821e2bSDavid Chinner if (error) 81392821e2bSDavid Chinner return error; 81492821e2bSDavid Chinner 81592821e2bSDavid Chinner error = xfs_ialloc_pagi_init(mp, NULL, index); 81692821e2bSDavid Chinner if (error) 81792821e2bSDavid Chinner return error; 81844b56e0aSDave Chinner pag = xfs_perag_get(mp, index); 81992821e2bSDavid Chinner ifree += pag->pagi_freecount; 82092821e2bSDavid Chinner ialloc += pag->pagi_count; 82192821e2bSDavid Chinner bfree += pag->pagf_freeblks; 82292821e2bSDavid Chinner bfreelst += pag->pagf_flcount; 82392821e2bSDavid Chinner btree += pag->pagf_btreeblks; 82444b56e0aSDave Chinner xfs_perag_put(pag); 82592821e2bSDavid Chinner } 82692821e2bSDavid Chinner /* 82792821e2bSDavid Chinner * Overwrite incore superblock counters with just-read data 82892821e2bSDavid Chinner */ 8293685c2a1SEric Sandeen spin_lock(&mp->m_sb_lock); 83092821e2bSDavid Chinner sbp->sb_ifree = ifree; 83192821e2bSDavid Chinner sbp->sb_icount = ialloc; 83292821e2bSDavid Chinner sbp->sb_fdblocks = bfree + bfreelst + btree; 8333685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 83492821e2bSDavid Chinner 83592821e2bSDavid Chinner /* Fixup the per-cpu counters as well. */ 83692821e2bSDavid Chinner xfs_icsb_reinit_counters(mp); 83792821e2bSDavid Chinner 83892821e2bSDavid Chinner return 0; 83992821e2bSDavid Chinner } 84092821e2bSDavid Chinner 8411da177e4SLinus Torvalds /* 8420771fb45SEric Sandeen * Update alignment values based on mount options and sb values 8431da177e4SLinus Torvalds */ 8440771fb45SEric Sandeen STATIC int 8457884bc86SChristoph Hellwig xfs_update_alignment(xfs_mount_t *mp) 8461da177e4SLinus Torvalds { 8471da177e4SLinus Torvalds xfs_sb_t *sbp = &(mp->m_sb); 8481da177e4SLinus Torvalds 8494249023aSChristoph Hellwig if (mp->m_dalign) { 8501da177e4SLinus Torvalds /* 8511da177e4SLinus Torvalds * If stripe unit and stripe width are not multiples 8521da177e4SLinus Torvalds * of the fs blocksize turn off alignment. 8531da177e4SLinus Torvalds */ 8541da177e4SLinus Torvalds if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || 8551da177e4SLinus Torvalds (BBTOB(mp->m_swidth) & mp->m_blockmask)) { 8561da177e4SLinus Torvalds if (mp->m_flags & XFS_MOUNT_RETERR) { 857c0e090ceSEric Sandeen xfs_warn(mp, "alignment check failed: " 858c0e090ceSEric Sandeen "(sunit/swidth vs. blocksize)"); 8590771fb45SEric Sandeen return XFS_ERROR(EINVAL); 8601da177e4SLinus Torvalds } 8611da177e4SLinus Torvalds mp->m_dalign = mp->m_swidth = 0; 8621da177e4SLinus Torvalds } else { 8631da177e4SLinus Torvalds /* 8641da177e4SLinus Torvalds * Convert the stripe unit and width to FSBs. 8651da177e4SLinus Torvalds */ 8661da177e4SLinus Torvalds mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign); 8671da177e4SLinus Torvalds if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) { 8681da177e4SLinus Torvalds if (mp->m_flags & XFS_MOUNT_RETERR) { 869c0e090ceSEric Sandeen xfs_warn(mp, "alignment check failed: " 870c0e090ceSEric Sandeen "(sunit/swidth vs. ag size)"); 8710771fb45SEric Sandeen return XFS_ERROR(EINVAL); 8721da177e4SLinus Torvalds } 87353487786SDave Chinner xfs_warn(mp, 87453487786SDave Chinner "stripe alignment turned off: sunit(%d)/swidth(%d) " 87553487786SDave Chinner "incompatible with agsize(%d)", 8761da177e4SLinus Torvalds mp->m_dalign, mp->m_swidth, 8771da177e4SLinus Torvalds sbp->sb_agblocks); 8781da177e4SLinus Torvalds 8791da177e4SLinus Torvalds mp->m_dalign = 0; 8801da177e4SLinus Torvalds mp->m_swidth = 0; 8811da177e4SLinus Torvalds } else if (mp->m_dalign) { 8821da177e4SLinus Torvalds mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); 8831da177e4SLinus Torvalds } else { 8841da177e4SLinus Torvalds if (mp->m_flags & XFS_MOUNT_RETERR) { 885c0e090ceSEric Sandeen xfs_warn(mp, "alignment check failed: " 886c0e090ceSEric Sandeen "sunit(%d) less than bsize(%d)", 8871da177e4SLinus Torvalds mp->m_dalign, 8881da177e4SLinus Torvalds mp->m_blockmask +1); 8890771fb45SEric Sandeen return XFS_ERROR(EINVAL); 8901da177e4SLinus Torvalds } 8911da177e4SLinus Torvalds mp->m_swidth = 0; 8921da177e4SLinus Torvalds } 8931da177e4SLinus Torvalds } 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds /* 8961da177e4SLinus Torvalds * Update superblock with new values 8971da177e4SLinus Torvalds * and log changes 8981da177e4SLinus Torvalds */ 89962118709SEric Sandeen if (xfs_sb_version_hasdalign(sbp)) { 9001da177e4SLinus Torvalds if (sbp->sb_unit != mp->m_dalign) { 9011da177e4SLinus Torvalds sbp->sb_unit = mp->m_dalign; 9027884bc86SChristoph Hellwig mp->m_update_flags |= XFS_SB_UNIT; 9031da177e4SLinus Torvalds } 9041da177e4SLinus Torvalds if (sbp->sb_width != mp->m_swidth) { 9051da177e4SLinus Torvalds sbp->sb_width = mp->m_swidth; 9067884bc86SChristoph Hellwig mp->m_update_flags |= XFS_SB_WIDTH; 9071da177e4SLinus Torvalds } 9081da177e4SLinus Torvalds } 9091da177e4SLinus Torvalds } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && 91062118709SEric Sandeen xfs_sb_version_hasdalign(&mp->m_sb)) { 9111da177e4SLinus Torvalds mp->m_dalign = sbp->sb_unit; 9121da177e4SLinus Torvalds mp->m_swidth = sbp->sb_width; 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds 9150771fb45SEric Sandeen return 0; 9160771fb45SEric Sandeen } 9171da177e4SLinus Torvalds 9180771fb45SEric Sandeen /* 9190771fb45SEric Sandeen * Set the maximum inode count for this filesystem 9200771fb45SEric Sandeen */ 9210771fb45SEric Sandeen STATIC void 9220771fb45SEric Sandeen xfs_set_maxicount(xfs_mount_t *mp) 9230771fb45SEric Sandeen { 9240771fb45SEric Sandeen xfs_sb_t *sbp = &(mp->m_sb); 9251da177e4SLinus Torvalds __uint64_t icount; 9261da177e4SLinus Torvalds 9270771fb45SEric Sandeen if (sbp->sb_imax_pct) { 9280771fb45SEric Sandeen /* 9290771fb45SEric Sandeen * Make sure the maximum inode count is a multiple 9300771fb45SEric Sandeen * of the units we allocate inodes in. 9311da177e4SLinus Torvalds */ 9321da177e4SLinus Torvalds icount = sbp->sb_dblocks * sbp->sb_imax_pct; 9331da177e4SLinus Torvalds do_div(icount, 100); 9341da177e4SLinus Torvalds do_div(icount, mp->m_ialloc_blks); 9351da177e4SLinus Torvalds mp->m_maxicount = (icount * mp->m_ialloc_blks) << 9361da177e4SLinus Torvalds sbp->sb_inopblog; 9370771fb45SEric Sandeen } else { 9381da177e4SLinus Torvalds mp->m_maxicount = 0; 9391da177e4SLinus Torvalds } 9401da177e4SLinus Torvalds } 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds /* 9431da177e4SLinus Torvalds * Set the default minimum read and write sizes unless 9441da177e4SLinus Torvalds * already specified in a mount option. 9451da177e4SLinus Torvalds * We use smaller I/O sizes when the file system 9461da177e4SLinus Torvalds * is being used for NFS service (wsync mount option). 9471da177e4SLinus Torvalds */ 9480771fb45SEric Sandeen STATIC void 9490771fb45SEric Sandeen xfs_set_rw_sizes(xfs_mount_t *mp) 9500771fb45SEric Sandeen { 9510771fb45SEric Sandeen xfs_sb_t *sbp = &(mp->m_sb); 9520771fb45SEric Sandeen int readio_log, writeio_log; 9530771fb45SEric Sandeen 9541da177e4SLinus Torvalds if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) { 9551da177e4SLinus Torvalds if (mp->m_flags & XFS_MOUNT_WSYNC) { 9561da177e4SLinus Torvalds readio_log = XFS_WSYNC_READIO_LOG; 9571da177e4SLinus Torvalds writeio_log = XFS_WSYNC_WRITEIO_LOG; 9581da177e4SLinus Torvalds } else { 9591da177e4SLinus Torvalds readio_log = XFS_READIO_LOG_LARGE; 9601da177e4SLinus Torvalds writeio_log = XFS_WRITEIO_LOG_LARGE; 9611da177e4SLinus Torvalds } 9621da177e4SLinus Torvalds } else { 9631da177e4SLinus Torvalds readio_log = mp->m_readio_log; 9641da177e4SLinus Torvalds writeio_log = mp->m_writeio_log; 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds if (sbp->sb_blocklog > readio_log) { 9681da177e4SLinus Torvalds mp->m_readio_log = sbp->sb_blocklog; 9691da177e4SLinus Torvalds } else { 9701da177e4SLinus Torvalds mp->m_readio_log = readio_log; 9711da177e4SLinus Torvalds } 9721da177e4SLinus Torvalds mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog); 9731da177e4SLinus Torvalds if (sbp->sb_blocklog > writeio_log) { 9741da177e4SLinus Torvalds mp->m_writeio_log = sbp->sb_blocklog; 9751da177e4SLinus Torvalds } else { 9761da177e4SLinus Torvalds mp->m_writeio_log = writeio_log; 9771da177e4SLinus Torvalds } 9781da177e4SLinus Torvalds mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog); 9790771fb45SEric Sandeen } 980425f9dddSEric Sandeen 9811da177e4SLinus Torvalds /* 982055388a3SDave Chinner * precalculate the low space thresholds for dynamic speculative preallocation. 983055388a3SDave Chinner */ 984055388a3SDave Chinner void 985055388a3SDave Chinner xfs_set_low_space_thresholds( 986055388a3SDave Chinner struct xfs_mount *mp) 987055388a3SDave Chinner { 988055388a3SDave Chinner int i; 989055388a3SDave Chinner 990055388a3SDave Chinner for (i = 0; i < XFS_LOWSP_MAX; i++) { 991055388a3SDave Chinner __uint64_t space = mp->m_sb.sb_dblocks; 992055388a3SDave Chinner 993055388a3SDave Chinner do_div(space, 100); 994055388a3SDave Chinner mp->m_low_space[i] = space * (i + 1); 995055388a3SDave Chinner } 996055388a3SDave Chinner } 997055388a3SDave Chinner 998055388a3SDave Chinner 999055388a3SDave Chinner /* 10001da177e4SLinus Torvalds * Set whether we're using inode alignment. 10011da177e4SLinus Torvalds */ 10020771fb45SEric Sandeen STATIC void 10030771fb45SEric Sandeen xfs_set_inoalignment(xfs_mount_t *mp) 10040771fb45SEric Sandeen { 100562118709SEric Sandeen if (xfs_sb_version_hasalign(&mp->m_sb) && 10061da177e4SLinus Torvalds mp->m_sb.sb_inoalignmt >= 10071da177e4SLinus Torvalds XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) 10081da177e4SLinus Torvalds mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; 10091da177e4SLinus Torvalds else 10101da177e4SLinus Torvalds mp->m_inoalign_mask = 0; 10111da177e4SLinus Torvalds /* 10121da177e4SLinus Torvalds * If we are using stripe alignment, check whether 10131da177e4SLinus Torvalds * the stripe unit is a multiple of the inode alignment 10141da177e4SLinus Torvalds */ 10151da177e4SLinus Torvalds if (mp->m_dalign && mp->m_inoalign_mask && 10161da177e4SLinus Torvalds !(mp->m_dalign & mp->m_inoalign_mask)) 10171da177e4SLinus Torvalds mp->m_sinoalign = mp->m_dalign; 10181da177e4SLinus Torvalds else 10191da177e4SLinus Torvalds mp->m_sinoalign = 0; 10200771fb45SEric Sandeen } 10210771fb45SEric Sandeen 10221da177e4SLinus Torvalds /* 10231da177e4SLinus Torvalds * Check that the data (and log if separate) are an ok size. 10241da177e4SLinus Torvalds */ 10250771fb45SEric Sandeen STATIC int 10264249023aSChristoph Hellwig xfs_check_sizes(xfs_mount_t *mp) 10270771fb45SEric Sandeen { 10280771fb45SEric Sandeen xfs_buf_t *bp; 10290771fb45SEric Sandeen xfs_daddr_t d; 10300771fb45SEric Sandeen 10311da177e4SLinus Torvalds d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); 10321da177e4SLinus Torvalds if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { 10330b932cccSDave Chinner xfs_warn(mp, "filesystem size mismatch detected"); 1034657a4cffSEric Sandeen return XFS_ERROR(EFBIG); 10351da177e4SLinus Torvalds } 10361922c949SDave Chinner bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, 10371da177e4SLinus Torvalds d - XFS_FSS_TO_BB(mp, 1), 10381922c949SDave Chinner BBTOB(XFS_FSS_TO_BB(mp, 1)), 0); 10391922c949SDave Chinner if (!bp) { 10400b932cccSDave Chinner xfs_warn(mp, "last sector read failed"); 10411922c949SDave Chinner return EIO; 10421da177e4SLinus Torvalds } 10431922c949SDave Chinner xfs_buf_relse(bp); 10441da177e4SLinus Torvalds 10454249023aSChristoph Hellwig if (mp->m_logdev_targp != mp->m_ddev_targp) { 10461da177e4SLinus Torvalds d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); 10471da177e4SLinus Torvalds if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { 10480b932cccSDave Chinner xfs_warn(mp, "log size mismatch detected"); 1049657a4cffSEric Sandeen return XFS_ERROR(EFBIG); 10501da177e4SLinus Torvalds } 10511922c949SDave Chinner bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp, 10521da177e4SLinus Torvalds d - XFS_FSB_TO_BB(mp, 1), 10531922c949SDave Chinner XFS_FSB_TO_B(mp, 1), 0); 10541922c949SDave Chinner if (!bp) { 10550b932cccSDave Chinner xfs_warn(mp, "log device read failed"); 10561922c949SDave Chinner return EIO; 10571da177e4SLinus Torvalds } 10581922c949SDave Chinner xfs_buf_relse(bp); 10590771fb45SEric Sandeen } 10600771fb45SEric Sandeen return 0; 10610771fb45SEric Sandeen } 10620771fb45SEric Sandeen 10630771fb45SEric Sandeen /* 10647d095257SChristoph Hellwig * Clear the quotaflags in memory and in the superblock. 10657d095257SChristoph Hellwig */ 10667d095257SChristoph Hellwig int 10677d095257SChristoph Hellwig xfs_mount_reset_sbqflags( 10687d095257SChristoph Hellwig struct xfs_mount *mp) 10697d095257SChristoph Hellwig { 10707d095257SChristoph Hellwig int error; 10717d095257SChristoph Hellwig struct xfs_trans *tp; 10727d095257SChristoph Hellwig 10737d095257SChristoph Hellwig mp->m_qflags = 0; 10747d095257SChristoph Hellwig 10757d095257SChristoph Hellwig /* 10767d095257SChristoph Hellwig * It is OK to look at sb_qflags here in mount path, 10777d095257SChristoph Hellwig * without m_sb_lock. 10787d095257SChristoph Hellwig */ 10797d095257SChristoph Hellwig if (mp->m_sb.sb_qflags == 0) 10807d095257SChristoph Hellwig return 0; 10817d095257SChristoph Hellwig spin_lock(&mp->m_sb_lock); 10827d095257SChristoph Hellwig mp->m_sb.sb_qflags = 0; 10837d095257SChristoph Hellwig spin_unlock(&mp->m_sb_lock); 10847d095257SChristoph Hellwig 10857d095257SChristoph Hellwig /* 10867d095257SChristoph Hellwig * If the fs is readonly, let the incore superblock run 10877d095257SChristoph Hellwig * with quotas off but don't flush the update out to disk 10887d095257SChristoph Hellwig */ 10897d095257SChristoph Hellwig if (mp->m_flags & XFS_MOUNT_RDONLY) 10907d095257SChristoph Hellwig return 0; 10917d095257SChristoph Hellwig 10927d095257SChristoph Hellwig tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); 10937d095257SChristoph Hellwig error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 10947d095257SChristoph Hellwig XFS_DEFAULT_LOG_COUNT); 10957d095257SChristoph Hellwig if (error) { 10967d095257SChristoph Hellwig xfs_trans_cancel(tp, 0); 109753487786SDave Chinner xfs_alert(mp, "%s: Superblock update failed!", __func__); 10987d095257SChristoph Hellwig return error; 10997d095257SChristoph Hellwig } 11007d095257SChristoph Hellwig 11017d095257SChristoph Hellwig xfs_mod_sb(tp, XFS_SB_QFLAGS); 11027d095257SChristoph Hellwig return xfs_trans_commit(tp, 0); 11037d095257SChristoph Hellwig } 11047d095257SChristoph Hellwig 1105d5db0f97SEric Sandeen __uint64_t 1106d5db0f97SEric Sandeen xfs_default_resblks(xfs_mount_t *mp) 1107d5db0f97SEric Sandeen { 1108d5db0f97SEric Sandeen __uint64_t resblks; 1109d5db0f97SEric Sandeen 1110d5db0f97SEric Sandeen /* 11118babd8a2SDave Chinner * We default to 5% or 8192 fsbs of space reserved, whichever is 11128babd8a2SDave Chinner * smaller. This is intended to cover concurrent allocation 11138babd8a2SDave Chinner * transactions when we initially hit enospc. These each require a 4 11148babd8a2SDave Chinner * block reservation. Hence by default we cover roughly 2000 concurrent 11158babd8a2SDave Chinner * allocation reservations. 1116d5db0f97SEric Sandeen */ 1117d5db0f97SEric Sandeen resblks = mp->m_sb.sb_dblocks; 1118d5db0f97SEric Sandeen do_div(resblks, 20); 11198babd8a2SDave Chinner resblks = min_t(__uint64_t, resblks, 8192); 1120d5db0f97SEric Sandeen return resblks; 1121d5db0f97SEric Sandeen } 1122d5db0f97SEric Sandeen 11237d095257SChristoph Hellwig /* 11240771fb45SEric Sandeen * This function does the following on an initial mount of a file system: 11250771fb45SEric Sandeen * - reads the superblock from disk and init the mount struct 11260771fb45SEric Sandeen * - if we're a 32-bit kernel, do a size check on the superblock 11270771fb45SEric Sandeen * so we don't mount terabyte filesystems 11280771fb45SEric Sandeen * - init mount struct realtime fields 11290771fb45SEric Sandeen * - allocate inode hash table for fs 11300771fb45SEric Sandeen * - init directory manager 11310771fb45SEric Sandeen * - perform recovery and init the log manager 11320771fb45SEric Sandeen */ 11330771fb45SEric Sandeen int 11340771fb45SEric Sandeen xfs_mountfs( 11354249023aSChristoph Hellwig xfs_mount_t *mp) 11360771fb45SEric Sandeen { 11370771fb45SEric Sandeen xfs_sb_t *sbp = &(mp->m_sb); 11380771fb45SEric Sandeen xfs_inode_t *rip; 11390771fb45SEric Sandeen __uint64_t resblks; 11407d095257SChristoph Hellwig uint quotamount = 0; 11417d095257SChristoph Hellwig uint quotaflags = 0; 11420771fb45SEric Sandeen int error = 0; 11430771fb45SEric Sandeen 11440771fb45SEric Sandeen xfs_mount_common(mp, sbp); 11450771fb45SEric Sandeen 11460771fb45SEric Sandeen /* 1147e6957ea4SEric Sandeen * Check for a mismatched features2 values. Older kernels 1148e6957ea4SEric Sandeen * read & wrote into the wrong sb offset for sb_features2 1149e6957ea4SEric Sandeen * on some platforms due to xfs_sb_t not being 64bit size aligned 1150e6957ea4SEric Sandeen * when sb_features2 was added, which made older superblock 1151e6957ea4SEric Sandeen * reading/writing routines swap it as a 64-bit value. 1152ee1c0908SDavid Chinner * 1153e6957ea4SEric Sandeen * For backwards compatibility, we make both slots equal. 1154e6957ea4SEric Sandeen * 1155e6957ea4SEric Sandeen * If we detect a mismatched field, we OR the set bits into the 1156e6957ea4SEric Sandeen * existing features2 field in case it has already been modified; we 1157e6957ea4SEric Sandeen * don't want to lose any features. We then update the bad location 1158e6957ea4SEric Sandeen * with the ORed value so that older kernels will see any features2 1159e6957ea4SEric Sandeen * flags, and mark the two fields as needing updates once the 1160e6957ea4SEric Sandeen * transaction subsystem is online. 1161ee1c0908SDavid Chinner */ 1162e6957ea4SEric Sandeen if (xfs_sb_has_mismatched_features2(sbp)) { 11630b932cccSDave Chinner xfs_warn(mp, "correcting sb_features alignment problem"); 1164ee1c0908SDavid Chinner sbp->sb_features2 |= sbp->sb_bad_features2; 1165e6957ea4SEric Sandeen sbp->sb_bad_features2 = sbp->sb_features2; 11667884bc86SChristoph Hellwig mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; 1167e6957ea4SEric Sandeen 1168e6957ea4SEric Sandeen /* 1169e6957ea4SEric Sandeen * Re-check for ATTR2 in case it was found in bad_features2 1170e6957ea4SEric Sandeen * slot. 1171e6957ea4SEric Sandeen */ 11727c12f296STim Shimmin if (xfs_sb_version_hasattr2(&mp->m_sb) && 11737c12f296STim Shimmin !(mp->m_flags & XFS_MOUNT_NOATTR2)) 1174e6957ea4SEric Sandeen mp->m_flags |= XFS_MOUNT_ATTR2; 11757c12f296STim Shimmin } 1176e6957ea4SEric Sandeen 11777c12f296STim Shimmin if (xfs_sb_version_hasattr2(&mp->m_sb) && 11787c12f296STim Shimmin (mp->m_flags & XFS_MOUNT_NOATTR2)) { 11797c12f296STim Shimmin xfs_sb_version_removeattr2(&mp->m_sb); 11807884bc86SChristoph Hellwig mp->m_update_flags |= XFS_SB_FEATURES2; 11817c12f296STim Shimmin 11827c12f296STim Shimmin /* update sb_versionnum for the clearing of the morebits */ 11837c12f296STim Shimmin if (!sbp->sb_features2) 11847884bc86SChristoph Hellwig mp->m_update_flags |= XFS_SB_VERSIONNUM; 1185ee1c0908SDavid Chinner } 1186ee1c0908SDavid Chinner 1187ee1c0908SDavid Chinner /* 11880771fb45SEric Sandeen * Check if sb_agblocks is aligned at stripe boundary 11890771fb45SEric Sandeen * If sb_agblocks is NOT aligned turn off m_dalign since 11900771fb45SEric Sandeen * allocator alignment is within an ag, therefore ag has 11910771fb45SEric Sandeen * to be aligned at stripe boundary. 11920771fb45SEric Sandeen */ 11937884bc86SChristoph Hellwig error = xfs_update_alignment(mp); 11940771fb45SEric Sandeen if (error) 1195f9057e3dSChristoph Hellwig goto out; 11960771fb45SEric Sandeen 11970771fb45SEric Sandeen xfs_alloc_compute_maxlevels(mp); 11980771fb45SEric Sandeen xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); 11990771fb45SEric Sandeen xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); 12000771fb45SEric Sandeen xfs_ialloc_compute_maxlevels(mp); 12010771fb45SEric Sandeen 12020771fb45SEric Sandeen xfs_set_maxicount(mp); 12030771fb45SEric Sandeen 12040771fb45SEric Sandeen mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); 12050771fb45SEric Sandeen 120627174203SChristoph Hellwig error = xfs_uuid_mount(mp); 120727174203SChristoph Hellwig if (error) 1208f9057e3dSChristoph Hellwig goto out; 12091da177e4SLinus Torvalds 12101da177e4SLinus Torvalds /* 12110771fb45SEric Sandeen * Set the minimum read and write sizes 12120771fb45SEric Sandeen */ 12130771fb45SEric Sandeen xfs_set_rw_sizes(mp); 12140771fb45SEric Sandeen 1215055388a3SDave Chinner /* set the low space thresholds for dynamic preallocation */ 1216055388a3SDave Chinner xfs_set_low_space_thresholds(mp); 1217055388a3SDave Chinner 12180771fb45SEric Sandeen /* 12190771fb45SEric Sandeen * Set the inode cluster size. 12200771fb45SEric Sandeen * This may still be overridden by the file system 12210771fb45SEric Sandeen * block size if it is larger than the chosen cluster size. 12220771fb45SEric Sandeen */ 12230771fb45SEric Sandeen mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; 12240771fb45SEric Sandeen 12250771fb45SEric Sandeen /* 12260771fb45SEric Sandeen * Set inode alignment fields 12270771fb45SEric Sandeen */ 12280771fb45SEric Sandeen xfs_set_inoalignment(mp); 12290771fb45SEric Sandeen 12300771fb45SEric Sandeen /* 12310771fb45SEric Sandeen * Check that the data (and log if separate) are an ok size. 12320771fb45SEric Sandeen */ 12334249023aSChristoph Hellwig error = xfs_check_sizes(mp); 12340771fb45SEric Sandeen if (error) 1235f9057e3dSChristoph Hellwig goto out_remove_uuid; 12360771fb45SEric Sandeen 12370771fb45SEric Sandeen /* 12381da177e4SLinus Torvalds * Initialize realtime fields in the mount structure 12391da177e4SLinus Torvalds */ 12400771fb45SEric Sandeen error = xfs_rtmount_init(mp); 12410771fb45SEric Sandeen if (error) { 12420b932cccSDave Chinner xfs_warn(mp, "RT mount failed"); 1243f9057e3dSChristoph Hellwig goto out_remove_uuid; 12441da177e4SLinus Torvalds } 12451da177e4SLinus Torvalds 12461da177e4SLinus Torvalds /* 12471da177e4SLinus Torvalds * Copies the low order bits of the timestamp and the randomly 12481da177e4SLinus Torvalds * set "sequence" number out of a UUID. 12491da177e4SLinus Torvalds */ 12501da177e4SLinus Torvalds uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid); 12511da177e4SLinus Torvalds 12521da177e4SLinus Torvalds mp->m_dmevmask = 0; /* not persistent; set after each mount */ 12531da177e4SLinus Torvalds 1254f6c2d1faSNathan Scott xfs_dir_mount(mp); 12551da177e4SLinus Torvalds 12561da177e4SLinus Torvalds /* 12571da177e4SLinus Torvalds * Initialize the attribute manager's entries. 12581da177e4SLinus Torvalds */ 12591da177e4SLinus Torvalds mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100; 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds /* 12621da177e4SLinus Torvalds * Initialize the precomputed transaction reservations values. 12631da177e4SLinus Torvalds */ 12641da177e4SLinus Torvalds xfs_trans_init(mp); 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds /* 12671da177e4SLinus Torvalds * Allocate and initialize the per-ag data. 12681da177e4SLinus Torvalds */ 12691c1c6ebcSDave Chinner spin_lock_init(&mp->m_perag_lock); 12709b98b6f3SDave Chinner INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); 12711c1c6ebcSDave Chinner error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); 12721c1c6ebcSDave Chinner if (error) { 12730b932cccSDave Chinner xfs_warn(mp, "Failed per-ag init: %d", error); 1274f9057e3dSChristoph Hellwig goto out_remove_uuid; 12751c1c6ebcSDave Chinner } 12761da177e4SLinus Torvalds 1277f9057e3dSChristoph Hellwig if (!sbp->sb_logblocks) { 12780b932cccSDave Chinner xfs_warn(mp, "no log defined"); 1279f9057e3dSChristoph Hellwig XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); 1280f9057e3dSChristoph Hellwig error = XFS_ERROR(EFSCORRUPTED); 1281f9057e3dSChristoph Hellwig goto out_free_perag; 1282f9057e3dSChristoph Hellwig } 1283f9057e3dSChristoph Hellwig 12841da177e4SLinus Torvalds /* 12851da177e4SLinus Torvalds * log's mount-time initialization. Perform 1st part recovery if needed 12861da177e4SLinus Torvalds */ 12871da177e4SLinus Torvalds error = xfs_log_mount(mp, mp->m_logdev_targp, 12881da177e4SLinus Torvalds XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), 12891da177e4SLinus Torvalds XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); 12901da177e4SLinus Torvalds if (error) { 12910b932cccSDave Chinner xfs_warn(mp, "log mount failed"); 1292f9057e3dSChristoph Hellwig goto out_free_perag; 12931da177e4SLinus Torvalds } 12941da177e4SLinus Torvalds 12951da177e4SLinus Torvalds /* 129692821e2bSDavid Chinner * Now the log is mounted, we know if it was an unclean shutdown or 129792821e2bSDavid Chinner * not. If it was, with the first phase of recovery has completed, we 129892821e2bSDavid Chinner * have consistent AG blocks on disk. We have not recovered EFIs yet, 129992821e2bSDavid Chinner * but they are recovered transactionally in the second recovery phase 130092821e2bSDavid Chinner * later. 130192821e2bSDavid Chinner * 130292821e2bSDavid Chinner * Hence we can safely re-initialise incore superblock counters from 130392821e2bSDavid Chinner * the per-ag data. These may not be correct if the filesystem was not 130492821e2bSDavid Chinner * cleanly unmounted, so we need to wait for recovery to finish before 130592821e2bSDavid Chinner * doing this. 130692821e2bSDavid Chinner * 130792821e2bSDavid Chinner * If the filesystem was cleanly unmounted, then we can trust the 130892821e2bSDavid Chinner * values in the superblock to be correct and we don't need to do 130992821e2bSDavid Chinner * anything here. 131092821e2bSDavid Chinner * 131192821e2bSDavid Chinner * If we are currently making the filesystem, the initialisation will 131292821e2bSDavid Chinner * fail as the perag data is in an undefined state. 131392821e2bSDavid Chinner */ 131492821e2bSDavid Chinner if (xfs_sb_version_haslazysbcount(&mp->m_sb) && 131592821e2bSDavid Chinner !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && 131692821e2bSDavid Chinner !mp->m_sb.sb_inprogress) { 131792821e2bSDavid Chinner error = xfs_initialize_perag_data(mp, sbp->sb_agcount); 1318f9057e3dSChristoph Hellwig if (error) 1319f9057e3dSChristoph Hellwig goto out_free_perag; 132092821e2bSDavid Chinner } 1321f9057e3dSChristoph Hellwig 132292821e2bSDavid Chinner /* 13231da177e4SLinus Torvalds * Get and sanity-check the root inode. 13241da177e4SLinus Torvalds * Save the pointer to it in the mount structure. 13251da177e4SLinus Torvalds */ 13267b6259e7SDave Chinner error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); 13271da177e4SLinus Torvalds if (error) { 13280b932cccSDave Chinner xfs_warn(mp, "failed to read root inode"); 1329f9057e3dSChristoph Hellwig goto out_log_dealloc; 13301da177e4SLinus Torvalds } 13311da177e4SLinus Torvalds 13321da177e4SLinus Torvalds ASSERT(rip != NULL); 13331da177e4SLinus Torvalds 1334abbede1bSAl Viro if (unlikely(!S_ISDIR(rip->i_d.di_mode))) { 13350b932cccSDave Chinner xfs_warn(mp, "corrupted root inode %llu: not a directory", 1336b6574520SNathan Scott (unsigned long long)rip->i_ino); 13371da177e4SLinus Torvalds xfs_iunlock(rip, XFS_ILOCK_EXCL); 13381da177e4SLinus Torvalds XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, 13391da177e4SLinus Torvalds mp); 13401da177e4SLinus Torvalds error = XFS_ERROR(EFSCORRUPTED); 1341f9057e3dSChristoph Hellwig goto out_rele_rip; 13421da177e4SLinus Torvalds } 13431da177e4SLinus Torvalds mp->m_rootip = rip; /* save it */ 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds xfs_iunlock(rip, XFS_ILOCK_EXCL); 13461da177e4SLinus Torvalds 13471da177e4SLinus Torvalds /* 13481da177e4SLinus Torvalds * Initialize realtime inode pointers in the mount structure 13491da177e4SLinus Torvalds */ 13500771fb45SEric Sandeen error = xfs_rtmount_inodes(mp); 13510771fb45SEric Sandeen if (error) { 13521da177e4SLinus Torvalds /* 13531da177e4SLinus Torvalds * Free up the root inode. 13541da177e4SLinus Torvalds */ 13550b932cccSDave Chinner xfs_warn(mp, "failed to read RT inodes"); 1356f9057e3dSChristoph Hellwig goto out_rele_rip; 13571da177e4SLinus Torvalds } 13581da177e4SLinus Torvalds 13591da177e4SLinus Torvalds /* 13607884bc86SChristoph Hellwig * If this is a read-only mount defer the superblock updates until 13617884bc86SChristoph Hellwig * the next remount into writeable mode. Otherwise we would never 13627884bc86SChristoph Hellwig * perform the update e.g. for the root filesystem. 13631da177e4SLinus Torvalds */ 13647884bc86SChristoph Hellwig if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { 13657884bc86SChristoph Hellwig error = xfs_mount_log_sb(mp, mp->m_update_flags); 1366e5720eecSDavid Chinner if (error) { 13670b932cccSDave Chinner xfs_warn(mp, "failed to write sb changes"); 1368b93b6e43SChristoph Hellwig goto out_rtunmount; 1369e5720eecSDavid Chinner } 1370e5720eecSDavid Chinner } 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds /* 13731da177e4SLinus Torvalds * Initialise the XFS quota management subsystem for this mount 13741da177e4SLinus Torvalds */ 13757d095257SChristoph Hellwig if (XFS_IS_QUOTA_RUNNING(mp)) { 13767d095257SChristoph Hellwig error = xfs_qm_newmount(mp, "amount, "aflags); 13770771fb45SEric Sandeen if (error) 1378b93b6e43SChristoph Hellwig goto out_rtunmount; 13797d095257SChristoph Hellwig } else { 13807d095257SChristoph Hellwig ASSERT(!XFS_IS_QUOTA_ON(mp)); 13817d095257SChristoph Hellwig 13827d095257SChristoph Hellwig /* 13837d095257SChristoph Hellwig * If a file system had quotas running earlier, but decided to 13847d095257SChristoph Hellwig * mount without -o uquota/pquota/gquota options, revoke the 13857d095257SChristoph Hellwig * quotachecked license. 13867d095257SChristoph Hellwig */ 13877d095257SChristoph Hellwig if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { 13880b932cccSDave Chinner xfs_notice(mp, "resetting quota flags"); 13897d095257SChristoph Hellwig error = xfs_mount_reset_sbqflags(mp); 13907d095257SChristoph Hellwig if (error) 13917d095257SChristoph Hellwig return error; 13927d095257SChristoph Hellwig } 13937d095257SChristoph Hellwig } 13941da177e4SLinus Torvalds 13951da177e4SLinus Torvalds /* 13961da177e4SLinus Torvalds * Finish recovering the file system. This part needed to be 13971da177e4SLinus Torvalds * delayed until after the root and real-time bitmap inodes 13981da177e4SLinus Torvalds * were consistently read in. 13991da177e4SLinus Torvalds */ 14004249023aSChristoph Hellwig error = xfs_log_mount_finish(mp); 14011da177e4SLinus Torvalds if (error) { 14020b932cccSDave Chinner xfs_warn(mp, "log mount finish failed"); 1403b93b6e43SChristoph Hellwig goto out_rtunmount; 14041da177e4SLinus Torvalds } 14051da177e4SLinus Torvalds 14061da177e4SLinus Torvalds /* 14071da177e4SLinus Torvalds * Complete the quota initialisation, post-log-replay component. 14081da177e4SLinus Torvalds */ 14097d095257SChristoph Hellwig if (quotamount) { 14107d095257SChristoph Hellwig ASSERT(mp->m_qflags == 0); 14117d095257SChristoph Hellwig mp->m_qflags = quotaflags; 14127d095257SChristoph Hellwig 14137d095257SChristoph Hellwig xfs_qm_mount_quotas(mp); 14147d095257SChristoph Hellwig } 14157d095257SChristoph Hellwig 141684e1e99fSDavid Chinner /* 141784e1e99fSDavid Chinner * Now we are mounted, reserve a small amount of unused space for 141884e1e99fSDavid Chinner * privileged transactions. This is needed so that transaction 141984e1e99fSDavid Chinner * space required for critical operations can dip into this pool 142084e1e99fSDavid Chinner * when at ENOSPC. This is needed for operations like create with 142184e1e99fSDavid Chinner * attr, unwritten extent conversion at ENOSPC, etc. Data allocations 142284e1e99fSDavid Chinner * are not allowed to use this reserved space. 14238babd8a2SDave Chinner * 14248babd8a2SDave Chinner * This may drive us straight to ENOSPC on mount, but that implies 14258babd8a2SDave Chinner * we were already there on the last unmount. Warn if this occurs. 142684e1e99fSDavid Chinner */ 1427d5db0f97SEric Sandeen if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { 1428d5db0f97SEric Sandeen resblks = xfs_default_resblks(mp); 1429714082bcSDavid Chinner error = xfs_reserve_blocks(mp, &resblks, NULL); 1430714082bcSDavid Chinner if (error) 14310b932cccSDave Chinner xfs_warn(mp, 14320b932cccSDave Chinner "Unable to allocate reserve blocks. Continuing without reserve pool."); 1433d5db0f97SEric Sandeen } 143484e1e99fSDavid Chinner 14351da177e4SLinus Torvalds return 0; 14361da177e4SLinus Torvalds 1437b93b6e43SChristoph Hellwig out_rtunmount: 1438b93b6e43SChristoph Hellwig xfs_rtunmount_inodes(mp); 1439f9057e3dSChristoph Hellwig out_rele_rip: 144043355099SChristoph Hellwig IRELE(rip); 1441f9057e3dSChristoph Hellwig out_log_dealloc: 144221b699c8SChristoph Hellwig xfs_log_unmount(mp); 1443f9057e3dSChristoph Hellwig out_free_perag: 1444ff4f038cSChristoph Hellwig xfs_free_perag(mp); 1445f9057e3dSChristoph Hellwig out_remove_uuid: 144627174203SChristoph Hellwig xfs_uuid_unmount(mp); 1447f9057e3dSChristoph Hellwig out: 14481da177e4SLinus Torvalds return error; 14491da177e4SLinus Torvalds } 14501da177e4SLinus Torvalds 14511da177e4SLinus Torvalds /* 14521da177e4SLinus Torvalds * This flushes out the inodes,dquots and the superblock, unmounts the 14531da177e4SLinus Torvalds * log and makes sure that incore structures are freed. 14541da177e4SLinus Torvalds */ 145541b5c2e7SChristoph Hellwig void 145641b5c2e7SChristoph Hellwig xfs_unmountfs( 145741b5c2e7SChristoph Hellwig struct xfs_mount *mp) 14581da177e4SLinus Torvalds { 145984e1e99fSDavid Chinner __uint64_t resblks; 146041b5c2e7SChristoph Hellwig int error; 14611da177e4SLinus Torvalds 14627d095257SChristoph Hellwig xfs_qm_unmount_quotas(mp); 1463b93b6e43SChristoph Hellwig xfs_rtunmount_inodes(mp); 146477508ec8SChristoph Hellwig IRELE(mp->m_rootip); 146577508ec8SChristoph Hellwig 1466641c56fbSDavid Chinner /* 1467641c56fbSDavid Chinner * We can potentially deadlock here if we have an inode cluster 14689da096fdSMalcolm Parsons * that has been freed has its buffer still pinned in memory because 1469641c56fbSDavid Chinner * the transaction is still sitting in a iclog. The stale inodes 1470641c56fbSDavid Chinner * on that buffer will have their flush locks held until the 1471641c56fbSDavid Chinner * transaction hits the disk and the callbacks run. the inode 1472641c56fbSDavid Chinner * flush takes the flush lock unconditionally and with nothing to 1473641c56fbSDavid Chinner * push out the iclog we will never get that unlocked. hence we 1474641c56fbSDavid Chinner * need to force the log first. 1475641c56fbSDavid Chinner */ 1476a14a348bSChristoph Hellwig xfs_log_force(mp, XFS_LOG_SYNC); 1477c854363eSDave Chinner 1478c854363eSDave Chinner /* 1479*211e4d43SChristoph Hellwig * Flush all pending changes from the AIL. 1480c854363eSDave Chinner */ 1481*211e4d43SChristoph Hellwig xfs_ail_push_all_sync(mp->m_ail); 1482*211e4d43SChristoph Hellwig 1483*211e4d43SChristoph Hellwig /* 1484*211e4d43SChristoph Hellwig * And reclaim all inodes. At this point there should be no dirty 1485*211e4d43SChristoph Hellwig * inode, and none should be pinned or locked, but use synchronous 1486*211e4d43SChristoph Hellwig * reclaim just to be sure. 1487*211e4d43SChristoph Hellwig */ 1488c854363eSDave Chinner xfs_reclaim_inodes(mp, SYNC_WAIT); 14891da177e4SLinus Torvalds 14907d095257SChristoph Hellwig xfs_qm_unmount(mp); 1491a357a121SLachlan McIlroy 14921da177e4SLinus Torvalds /* 14931da177e4SLinus Torvalds * Flush out the log synchronously so that we know for sure 14941da177e4SLinus Torvalds * that nothing is pinned. This is important because bflush() 14951da177e4SLinus Torvalds * will skip pinned buffers. 14961da177e4SLinus Torvalds */ 1497a14a348bSChristoph Hellwig xfs_log_force(mp, XFS_LOG_SYNC); 14981da177e4SLinus Torvalds 149984e1e99fSDavid Chinner /* 150084e1e99fSDavid Chinner * Unreserve any blocks we have so that when we unmount we don't account 150184e1e99fSDavid Chinner * the reserved free space as used. This is really only necessary for 150284e1e99fSDavid Chinner * lazy superblock counting because it trusts the incore superblock 15039da096fdSMalcolm Parsons * counters to be absolutely correct on clean unmount. 150484e1e99fSDavid Chinner * 150584e1e99fSDavid Chinner * We don't bother correcting this elsewhere for lazy superblock 150684e1e99fSDavid Chinner * counting because on mount of an unclean filesystem we reconstruct the 150784e1e99fSDavid Chinner * correct counter value and this is irrelevant. 150884e1e99fSDavid Chinner * 150984e1e99fSDavid Chinner * For non-lazy counter filesystems, this doesn't matter at all because 151084e1e99fSDavid Chinner * we only every apply deltas to the superblock and hence the incore 151184e1e99fSDavid Chinner * value does not matter.... 151284e1e99fSDavid Chinner */ 151384e1e99fSDavid Chinner resblks = 0; 1514714082bcSDavid Chinner error = xfs_reserve_blocks(mp, &resblks, NULL); 1515714082bcSDavid Chinner if (error) 15160b932cccSDave Chinner xfs_warn(mp, "Unable to free reserved block pool. " 1517714082bcSDavid Chinner "Freespace may not be correct on next mount."); 1518714082bcSDavid Chinner 1519adab0f67SChandra Seetharaman error = xfs_log_sbcount(mp); 1520e5720eecSDavid Chinner if (error) 15210b932cccSDave Chinner xfs_warn(mp, "Unable to update superblock counters. " 1522e5720eecSDavid Chinner "Freespace may not be correct on next mount."); 152387c7bec7SChristoph Hellwig 152487c7bec7SChristoph Hellwig /* 1525*211e4d43SChristoph Hellwig * At this point we might have modified the superblock again and thus 1526*211e4d43SChristoph Hellwig * added an item to the AIL, thus flush it again. 152787c7bec7SChristoph Hellwig */ 1528*211e4d43SChristoph Hellwig xfs_ail_push_all_sync(mp->m_ail); 152987c7bec7SChristoph Hellwig xfs_wait_buftarg(mp->m_ddev_targp); 153087c7bec7SChristoph Hellwig 153121b699c8SChristoph Hellwig xfs_log_unmount_write(mp); 153221b699c8SChristoph Hellwig xfs_log_unmount(mp); 153327174203SChristoph Hellwig xfs_uuid_unmount(mp); 15341da177e4SLinus Torvalds 15351550d0b0SChristoph Hellwig #if defined(DEBUG) 15360ce4cfd4SChristoph Hellwig xfs_errortag_clearall(mp, 0); 15371da177e4SLinus Torvalds #endif 1538ff4f038cSChristoph Hellwig xfs_free_perag(mp); 15391da177e4SLinus Torvalds } 15401da177e4SLinus Torvalds 15411da177e4SLinus Torvalds int 154292821e2bSDavid Chinner xfs_fs_writable(xfs_mount_t *mp) 154392821e2bSDavid Chinner { 1544b267ce99SChristoph Hellwig return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || 1545bd186aa9SChristoph Hellwig (mp->m_flags & XFS_MOUNT_RDONLY)); 154692821e2bSDavid Chinner } 154792821e2bSDavid Chinner 154892821e2bSDavid Chinner /* 1549b2ce3974SAlex Elder * xfs_log_sbcount 1550b2ce3974SAlex Elder * 1551adab0f67SChandra Seetharaman * Sync the superblock counters to disk. 1552b2ce3974SAlex Elder * 1553b2ce3974SAlex Elder * Note this code can be called during the process of freezing, so 1554adab0f67SChandra Seetharaman * we may need to use the transaction allocator which does not 1555b2ce3974SAlex Elder * block when the transaction subsystem is in its frozen state. 155692821e2bSDavid Chinner */ 155792821e2bSDavid Chinner int 1558adab0f67SChandra Seetharaman xfs_log_sbcount(xfs_mount_t *mp) 155992821e2bSDavid Chinner { 156092821e2bSDavid Chinner xfs_trans_t *tp; 156192821e2bSDavid Chinner int error; 156292821e2bSDavid Chinner 156392821e2bSDavid Chinner if (!xfs_fs_writable(mp)) 156492821e2bSDavid Chinner return 0; 156592821e2bSDavid Chinner 1566d4d90b57SChristoph Hellwig xfs_icsb_sync_counters(mp, 0); 156792821e2bSDavid Chinner 156892821e2bSDavid Chinner /* 156992821e2bSDavid Chinner * we don't need to do this if we are updating the superblock 157092821e2bSDavid Chinner * counters on every modification. 157192821e2bSDavid Chinner */ 157292821e2bSDavid Chinner if (!xfs_sb_version_haslazysbcount(&mp->m_sb)) 157392821e2bSDavid Chinner return 0; 157492821e2bSDavid Chinner 1575b2ce3974SAlex Elder tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP); 157692821e2bSDavid Chinner error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 157792821e2bSDavid Chinner XFS_DEFAULT_LOG_COUNT); 157892821e2bSDavid Chinner if (error) { 157992821e2bSDavid Chinner xfs_trans_cancel(tp, 0); 158092821e2bSDavid Chinner return error; 158192821e2bSDavid Chinner } 158292821e2bSDavid Chinner 158392821e2bSDavid Chinner xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS); 158492821e2bSDavid Chinner xfs_trans_set_sync(tp); 1585e5720eecSDavid Chinner error = xfs_trans_commit(tp, 0); 1586e5720eecSDavid Chinner return error; 158792821e2bSDavid Chinner } 158892821e2bSDavid Chinner 15891da177e4SLinus Torvalds /* 15901da177e4SLinus Torvalds * xfs_mod_sb() can be used to copy arbitrary changes to the 15911da177e4SLinus Torvalds * in-core superblock into the superblock buffer to be logged. 15921da177e4SLinus Torvalds * It does not provide the higher level of locking that is 15931da177e4SLinus Torvalds * needed to protect the in-core superblock from concurrent 15941da177e4SLinus Torvalds * access. 15951da177e4SLinus Torvalds */ 15961da177e4SLinus Torvalds void 15971da177e4SLinus Torvalds xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) 15981da177e4SLinus Torvalds { 15991da177e4SLinus Torvalds xfs_buf_t *bp; 16001da177e4SLinus Torvalds int first; 16011da177e4SLinus Torvalds int last; 16021da177e4SLinus Torvalds xfs_mount_t *mp; 16031da177e4SLinus Torvalds xfs_sb_field_t f; 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds ASSERT(fields); 16061da177e4SLinus Torvalds if (!fields) 16071da177e4SLinus Torvalds return; 16081da177e4SLinus Torvalds mp = tp->t_mountp; 16091da177e4SLinus Torvalds bp = xfs_trans_getsb(tp, mp, 0); 16101da177e4SLinus Torvalds first = sizeof(xfs_sb_t); 16111da177e4SLinus Torvalds last = 0; 16121da177e4SLinus Torvalds 16131da177e4SLinus Torvalds /* translate/copy */ 16141da177e4SLinus Torvalds 16152bdf7cd0SChristoph Hellwig xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields); 16161da177e4SLinus Torvalds 16171da177e4SLinus Torvalds /* find modified range */ 1618587aa0feSDave Chinner f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields); 1619587aa0feSDave Chinner ASSERT((1LL << f) & XFS_SB_MOD_BITS); 1620587aa0feSDave Chinner last = xfs_sb_info[f + 1].offset - 1; 16211da177e4SLinus Torvalds 16221da177e4SLinus Torvalds f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); 16231da177e4SLinus Torvalds ASSERT((1LL << f) & XFS_SB_MOD_BITS); 16241da177e4SLinus Torvalds first = xfs_sb_info[f].offset; 16251da177e4SLinus Torvalds 16261da177e4SLinus Torvalds xfs_trans_log_buf(tp, bp, first, last); 16271da177e4SLinus Torvalds } 1628d210a28cSYingping Lu 1629d210a28cSYingping Lu 16301da177e4SLinus Torvalds /* 16311da177e4SLinus Torvalds * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply 16321da177e4SLinus Torvalds * a delta to a specified field in the in-core superblock. Simply 16331da177e4SLinus Torvalds * switch on the field indicated and apply the delta to that field. 16341da177e4SLinus Torvalds * Fields are not allowed to dip below zero, so if the delta would 16351da177e4SLinus Torvalds * do this do not apply it and return EINVAL. 16361da177e4SLinus Torvalds * 16373685c2a1SEric Sandeen * The m_sb_lock must be held when this routine is called. 16381da177e4SLinus Torvalds */ 1639d96f8f89SEric Sandeen STATIC int 164020f4ebf2SDavid Chinner xfs_mod_incore_sb_unlocked( 164120f4ebf2SDavid Chinner xfs_mount_t *mp, 164220f4ebf2SDavid Chinner xfs_sb_field_t field, 164320f4ebf2SDavid Chinner int64_t delta, 164420f4ebf2SDavid Chinner int rsvd) 16451da177e4SLinus Torvalds { 16461da177e4SLinus Torvalds int scounter; /* short counter for 32 bit fields */ 16471da177e4SLinus Torvalds long long lcounter; /* long counter for 64 bit fields */ 16481da177e4SLinus Torvalds long long res_used, rem; 16491da177e4SLinus Torvalds 16501da177e4SLinus Torvalds /* 16511da177e4SLinus Torvalds * With the in-core superblock spin lock held, switch 16521da177e4SLinus Torvalds * on the indicated field. Apply the delta to the 16531da177e4SLinus Torvalds * proper field. If the fields value would dip below 16541da177e4SLinus Torvalds * 0, then do not apply the delta and return EINVAL. 16551da177e4SLinus Torvalds */ 16561da177e4SLinus Torvalds switch (field) { 16571da177e4SLinus Torvalds case XFS_SBS_ICOUNT: 16581da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_icount; 16591da177e4SLinus Torvalds lcounter += delta; 16601da177e4SLinus Torvalds if (lcounter < 0) { 16611da177e4SLinus Torvalds ASSERT(0); 1662014c2544SJesper Juhl return XFS_ERROR(EINVAL); 16631da177e4SLinus Torvalds } 16641da177e4SLinus Torvalds mp->m_sb.sb_icount = lcounter; 1665014c2544SJesper Juhl return 0; 16661da177e4SLinus Torvalds case XFS_SBS_IFREE: 16671da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_ifree; 16681da177e4SLinus Torvalds lcounter += delta; 16691da177e4SLinus Torvalds if (lcounter < 0) { 16701da177e4SLinus Torvalds ASSERT(0); 1671014c2544SJesper Juhl return XFS_ERROR(EINVAL); 16721da177e4SLinus Torvalds } 16731da177e4SLinus Torvalds mp->m_sb.sb_ifree = lcounter; 1674014c2544SJesper Juhl return 0; 16751da177e4SLinus Torvalds case XFS_SBS_FDBLOCKS: 16764be536deSDavid Chinner lcounter = (long long) 16774be536deSDavid Chinner mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); 16781da177e4SLinus Torvalds res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); 16791da177e4SLinus Torvalds 16801da177e4SLinus Torvalds if (delta > 0) { /* Putting blocks back */ 16811da177e4SLinus Torvalds if (res_used > delta) { 16821da177e4SLinus Torvalds mp->m_resblks_avail += delta; 16831da177e4SLinus Torvalds } else { 16841da177e4SLinus Torvalds rem = delta - res_used; 16851da177e4SLinus Torvalds mp->m_resblks_avail = mp->m_resblks; 16861da177e4SLinus Torvalds lcounter += rem; 16871da177e4SLinus Torvalds } 16881da177e4SLinus Torvalds } else { /* Taking blocks away */ 16891da177e4SLinus Torvalds lcounter += delta; 16908babd8a2SDave Chinner if (lcounter >= 0) { 16918babd8a2SDave Chinner mp->m_sb.sb_fdblocks = lcounter + 16928babd8a2SDave Chinner XFS_ALLOC_SET_ASIDE(mp); 16938babd8a2SDave Chinner return 0; 16948babd8a2SDave Chinner } 16951da177e4SLinus Torvalds 16961da177e4SLinus Torvalds /* 16978babd8a2SDave Chinner * We are out of blocks, use any available reserved 16988babd8a2SDave Chinner * blocks if were allowed to. 16991da177e4SLinus Torvalds */ 17008babd8a2SDave Chinner if (!rsvd) 1701014c2544SJesper Juhl return XFS_ERROR(ENOSPC); 17028babd8a2SDave Chinner 17038babd8a2SDave Chinner lcounter = (long long)mp->m_resblks_avail + delta; 17048babd8a2SDave Chinner if (lcounter >= 0) { 17051da177e4SLinus Torvalds mp->m_resblks_avail = lcounter; 1706014c2544SJesper Juhl return 0; 17078babd8a2SDave Chinner } 17088babd8a2SDave Chinner printk_once(KERN_WARNING 17098babd8a2SDave Chinner "Filesystem \"%s\": reserve blocks depleted! " 17108babd8a2SDave Chinner "Consider increasing reserve pool size.", 17118babd8a2SDave Chinner mp->m_fsname); 1712014c2544SJesper Juhl return XFS_ERROR(ENOSPC); 17131da177e4SLinus Torvalds } 17141da177e4SLinus Torvalds 17154be536deSDavid Chinner mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); 1716014c2544SJesper Juhl return 0; 17171da177e4SLinus Torvalds case XFS_SBS_FREXTENTS: 17181da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_frextents; 17191da177e4SLinus Torvalds lcounter += delta; 17201da177e4SLinus Torvalds if (lcounter < 0) { 1721014c2544SJesper Juhl return XFS_ERROR(ENOSPC); 17221da177e4SLinus Torvalds } 17231da177e4SLinus Torvalds mp->m_sb.sb_frextents = lcounter; 1724014c2544SJesper Juhl return 0; 17251da177e4SLinus Torvalds case XFS_SBS_DBLOCKS: 17261da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_dblocks; 17271da177e4SLinus Torvalds lcounter += delta; 17281da177e4SLinus Torvalds if (lcounter < 0) { 17291da177e4SLinus Torvalds ASSERT(0); 1730014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17311da177e4SLinus Torvalds } 17321da177e4SLinus Torvalds mp->m_sb.sb_dblocks = lcounter; 1733014c2544SJesper Juhl return 0; 17341da177e4SLinus Torvalds case XFS_SBS_AGCOUNT: 17351da177e4SLinus Torvalds scounter = mp->m_sb.sb_agcount; 17361da177e4SLinus Torvalds scounter += delta; 17371da177e4SLinus Torvalds if (scounter < 0) { 17381da177e4SLinus Torvalds ASSERT(0); 1739014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17401da177e4SLinus Torvalds } 17411da177e4SLinus Torvalds mp->m_sb.sb_agcount = scounter; 1742014c2544SJesper Juhl return 0; 17431da177e4SLinus Torvalds case XFS_SBS_IMAX_PCT: 17441da177e4SLinus Torvalds scounter = mp->m_sb.sb_imax_pct; 17451da177e4SLinus Torvalds scounter += delta; 17461da177e4SLinus Torvalds if (scounter < 0) { 17471da177e4SLinus Torvalds ASSERT(0); 1748014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17491da177e4SLinus Torvalds } 17501da177e4SLinus Torvalds mp->m_sb.sb_imax_pct = scounter; 1751014c2544SJesper Juhl return 0; 17521da177e4SLinus Torvalds case XFS_SBS_REXTSIZE: 17531da177e4SLinus Torvalds scounter = mp->m_sb.sb_rextsize; 17541da177e4SLinus Torvalds scounter += delta; 17551da177e4SLinus Torvalds if (scounter < 0) { 17561da177e4SLinus Torvalds ASSERT(0); 1757014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17581da177e4SLinus Torvalds } 17591da177e4SLinus Torvalds mp->m_sb.sb_rextsize = scounter; 1760014c2544SJesper Juhl return 0; 17611da177e4SLinus Torvalds case XFS_SBS_RBMBLOCKS: 17621da177e4SLinus Torvalds scounter = mp->m_sb.sb_rbmblocks; 17631da177e4SLinus Torvalds scounter += delta; 17641da177e4SLinus Torvalds if (scounter < 0) { 17651da177e4SLinus Torvalds ASSERT(0); 1766014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17671da177e4SLinus Torvalds } 17681da177e4SLinus Torvalds mp->m_sb.sb_rbmblocks = scounter; 1769014c2544SJesper Juhl return 0; 17701da177e4SLinus Torvalds case XFS_SBS_RBLOCKS: 17711da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_rblocks; 17721da177e4SLinus Torvalds lcounter += delta; 17731da177e4SLinus Torvalds if (lcounter < 0) { 17741da177e4SLinus Torvalds ASSERT(0); 1775014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17761da177e4SLinus Torvalds } 17771da177e4SLinus Torvalds mp->m_sb.sb_rblocks = lcounter; 1778014c2544SJesper Juhl return 0; 17791da177e4SLinus Torvalds case XFS_SBS_REXTENTS: 17801da177e4SLinus Torvalds lcounter = (long long)mp->m_sb.sb_rextents; 17811da177e4SLinus Torvalds lcounter += delta; 17821da177e4SLinus Torvalds if (lcounter < 0) { 17831da177e4SLinus Torvalds ASSERT(0); 1784014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17851da177e4SLinus Torvalds } 17861da177e4SLinus Torvalds mp->m_sb.sb_rextents = lcounter; 1787014c2544SJesper Juhl return 0; 17881da177e4SLinus Torvalds case XFS_SBS_REXTSLOG: 17891da177e4SLinus Torvalds scounter = mp->m_sb.sb_rextslog; 17901da177e4SLinus Torvalds scounter += delta; 17911da177e4SLinus Torvalds if (scounter < 0) { 17921da177e4SLinus Torvalds ASSERT(0); 1793014c2544SJesper Juhl return XFS_ERROR(EINVAL); 17941da177e4SLinus Torvalds } 17951da177e4SLinus Torvalds mp->m_sb.sb_rextslog = scounter; 1796014c2544SJesper Juhl return 0; 17971da177e4SLinus Torvalds default: 17981da177e4SLinus Torvalds ASSERT(0); 1799014c2544SJesper Juhl return XFS_ERROR(EINVAL); 18001da177e4SLinus Torvalds } 18011da177e4SLinus Torvalds } 18021da177e4SLinus Torvalds 18031da177e4SLinus Torvalds /* 18041da177e4SLinus Torvalds * xfs_mod_incore_sb() is used to change a field in the in-core 18051da177e4SLinus Torvalds * superblock structure by the specified delta. This modification 18063685c2a1SEric Sandeen * is protected by the m_sb_lock. Just use the xfs_mod_incore_sb_unlocked() 18071da177e4SLinus Torvalds * routine to do the work. 18081da177e4SLinus Torvalds */ 18091da177e4SLinus Torvalds int 181020f4ebf2SDavid Chinner xfs_mod_incore_sb( 181196540c78SChristoph Hellwig struct xfs_mount *mp, 181220f4ebf2SDavid Chinner xfs_sb_field_t field, 181320f4ebf2SDavid Chinner int64_t delta, 181420f4ebf2SDavid Chinner int rsvd) 18151da177e4SLinus Torvalds { 18161da177e4SLinus Torvalds int status; 18171da177e4SLinus Torvalds 18188d280b98SDavid Chinner #ifdef HAVE_PERCPU_SB 181996540c78SChristoph Hellwig ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS); 18208d280b98SDavid Chinner #endif 18213685c2a1SEric Sandeen spin_lock(&mp->m_sb_lock); 18221da177e4SLinus Torvalds status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); 18233685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 18248d280b98SDavid Chinner 1825014c2544SJesper Juhl return status; 18261da177e4SLinus Torvalds } 18271da177e4SLinus Torvalds 18281da177e4SLinus Torvalds /* 18291b040712SChristoph Hellwig * Change more than one field in the in-core superblock structure at a time. 18301da177e4SLinus Torvalds * 18311b040712SChristoph Hellwig * The fields and changes to those fields are specified in the array of 18321b040712SChristoph Hellwig * xfs_mod_sb structures passed in. Either all of the specified deltas 18331b040712SChristoph Hellwig * will be applied or none of them will. If any modified field dips below 0, 18341b040712SChristoph Hellwig * then all modifications will be backed out and EINVAL will be returned. 18351b040712SChristoph Hellwig * 18361b040712SChristoph Hellwig * Note that this function may not be used for the superblock values that 18371b040712SChristoph Hellwig * are tracked with the in-memory per-cpu counters - a direct call to 18381b040712SChristoph Hellwig * xfs_icsb_modify_counters is required for these. 18391da177e4SLinus Torvalds */ 18401da177e4SLinus Torvalds int 18411b040712SChristoph Hellwig xfs_mod_incore_sb_batch( 18421b040712SChristoph Hellwig struct xfs_mount *mp, 18431b040712SChristoph Hellwig xfs_mod_sb_t *msb, 18441b040712SChristoph Hellwig uint nmsb, 18451b040712SChristoph Hellwig int rsvd) 18461da177e4SLinus Torvalds { 184745c51b99SDavid Sterba xfs_mod_sb_t *msbp; 18481b040712SChristoph Hellwig int error = 0; 18491da177e4SLinus Torvalds 18501da177e4SLinus Torvalds /* 18511b040712SChristoph Hellwig * Loop through the array of mod structures and apply each individually. 18521b040712SChristoph Hellwig * If any fail, then back out all those which have already been applied. 18531b040712SChristoph Hellwig * Do all of this within the scope of the m_sb_lock so that all of the 18541b040712SChristoph Hellwig * changes will be atomic. 18551da177e4SLinus Torvalds */ 18563685c2a1SEric Sandeen spin_lock(&mp->m_sb_lock); 185745c51b99SDavid Sterba for (msbp = msb; msbp < (msb + nmsb); msbp++) { 18581b040712SChristoph Hellwig ASSERT(msbp->msb_field < XFS_SBS_ICOUNT || 18591b040712SChristoph Hellwig msbp->msb_field > XFS_SBS_FDBLOCKS); 18608d280b98SDavid Chinner 18611b040712SChristoph Hellwig error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, 18621b040712SChristoph Hellwig msbp->msb_delta, rsvd); 18631b040712SChristoph Hellwig if (error) 18641b040712SChristoph Hellwig goto unwind; 18651da177e4SLinus Torvalds } 18661b040712SChristoph Hellwig spin_unlock(&mp->m_sb_lock); 18671b040712SChristoph Hellwig return 0; 18681da177e4SLinus Torvalds 18691b040712SChristoph Hellwig unwind: 18701b040712SChristoph Hellwig while (--msbp >= msb) { 18711b040712SChristoph Hellwig error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, 18721b040712SChristoph Hellwig -msbp->msb_delta, rsvd); 18731b040712SChristoph Hellwig ASSERT(error == 0); 18741da177e4SLinus Torvalds } 18753685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 18761b040712SChristoph Hellwig return error; 18771da177e4SLinus Torvalds } 18781da177e4SLinus Torvalds 18791da177e4SLinus Torvalds /* 18801da177e4SLinus Torvalds * xfs_getsb() is called to obtain the buffer for the superblock. 18811da177e4SLinus Torvalds * The buffer is returned locked and read in from disk. 18821da177e4SLinus Torvalds * The buffer should be released with a call to xfs_brelse(). 18831da177e4SLinus Torvalds * 18841da177e4SLinus Torvalds * If the flags parameter is BUF_TRYLOCK, then we'll only return 18851da177e4SLinus Torvalds * the superblock buffer if it can be locked without sleeping. 18861da177e4SLinus Torvalds * If it can't then we'll return NULL. 18871da177e4SLinus Torvalds */ 18880c842ad4SChristoph Hellwig struct xfs_buf * 18891da177e4SLinus Torvalds xfs_getsb( 18900c842ad4SChristoph Hellwig struct xfs_mount *mp, 18911da177e4SLinus Torvalds int flags) 18921da177e4SLinus Torvalds { 18930c842ad4SChristoph Hellwig struct xfs_buf *bp = mp->m_sb_bp; 18941da177e4SLinus Torvalds 18950c842ad4SChristoph Hellwig if (!xfs_buf_trylock(bp)) { 18960c842ad4SChristoph Hellwig if (flags & XBF_TRYLOCK) 18971da177e4SLinus Torvalds return NULL; 18980c842ad4SChristoph Hellwig xfs_buf_lock(bp); 18991da177e4SLinus Torvalds } 19000c842ad4SChristoph Hellwig 190172790aa1SChandra Seetharaman xfs_buf_hold(bp); 19021da177e4SLinus Torvalds ASSERT(XFS_BUF_ISDONE(bp)); 1903014c2544SJesper Juhl return bp; 19041da177e4SLinus Torvalds } 19051da177e4SLinus Torvalds 19061da177e4SLinus Torvalds /* 19071da177e4SLinus Torvalds * Used to free the superblock along various error paths. 19081da177e4SLinus Torvalds */ 19091da177e4SLinus Torvalds void 19101da177e4SLinus Torvalds xfs_freesb( 191126af6552SDave Chinner struct xfs_mount *mp) 19121da177e4SLinus Torvalds { 191326af6552SDave Chinner struct xfs_buf *bp = mp->m_sb_bp; 19141da177e4SLinus Torvalds 191526af6552SDave Chinner xfs_buf_lock(bp); 19161da177e4SLinus Torvalds mp->m_sb_bp = NULL; 191726af6552SDave Chinner xfs_buf_relse(bp); 19181da177e4SLinus Torvalds } 19191da177e4SLinus Torvalds 19201da177e4SLinus Torvalds /* 19211da177e4SLinus Torvalds * Used to log changes to the superblock unit and width fields which could 1922e6957ea4SEric Sandeen * be altered by the mount options, as well as any potential sb_features2 1923e6957ea4SEric Sandeen * fixup. Only the first superblock is updated. 19241da177e4SLinus Torvalds */ 19257884bc86SChristoph Hellwig int 1926ee1c0908SDavid Chinner xfs_mount_log_sb( 19271da177e4SLinus Torvalds xfs_mount_t *mp, 19281da177e4SLinus Torvalds __int64_t fields) 19291da177e4SLinus Torvalds { 19301da177e4SLinus Torvalds xfs_trans_t *tp; 1931e5720eecSDavid Chinner int error; 19321da177e4SLinus Torvalds 1933ee1c0908SDavid Chinner ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID | 19344b166de0SDavid Chinner XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 | 19354b166de0SDavid Chinner XFS_SB_VERSIONNUM)); 19361da177e4SLinus Torvalds 19371da177e4SLinus Torvalds tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); 1938e5720eecSDavid Chinner error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, 1939e5720eecSDavid Chinner XFS_DEFAULT_LOG_COUNT); 1940e5720eecSDavid Chinner if (error) { 19411da177e4SLinus Torvalds xfs_trans_cancel(tp, 0); 1942e5720eecSDavid Chinner return error; 19431da177e4SLinus Torvalds } 19441da177e4SLinus Torvalds xfs_mod_sb(tp, fields); 1945e5720eecSDavid Chinner error = xfs_trans_commit(tp, 0); 1946e5720eecSDavid Chinner return error; 19471da177e4SLinus Torvalds } 19488d280b98SDavid Chinner 1949dda35b8fSChristoph Hellwig /* 1950dda35b8fSChristoph Hellwig * If the underlying (data/log/rt) device is readonly, there are some 1951dda35b8fSChristoph Hellwig * operations that cannot proceed. 1952dda35b8fSChristoph Hellwig */ 1953dda35b8fSChristoph Hellwig int 1954dda35b8fSChristoph Hellwig xfs_dev_is_read_only( 1955dda35b8fSChristoph Hellwig struct xfs_mount *mp, 1956dda35b8fSChristoph Hellwig char *message) 1957dda35b8fSChristoph Hellwig { 1958dda35b8fSChristoph Hellwig if (xfs_readonly_buftarg(mp->m_ddev_targp) || 1959dda35b8fSChristoph Hellwig xfs_readonly_buftarg(mp->m_logdev_targp) || 1960dda35b8fSChristoph Hellwig (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { 19610b932cccSDave Chinner xfs_notice(mp, "%s required on read-only device.", message); 19620b932cccSDave Chinner xfs_notice(mp, "write access unavailable, cannot proceed."); 1963dda35b8fSChristoph Hellwig return EROFS; 1964dda35b8fSChristoph Hellwig } 1965dda35b8fSChristoph Hellwig return 0; 1966dda35b8fSChristoph Hellwig } 19678d280b98SDavid Chinner 19688d280b98SDavid Chinner #ifdef HAVE_PERCPU_SB 19698d280b98SDavid Chinner /* 19708d280b98SDavid Chinner * Per-cpu incore superblock counters 19718d280b98SDavid Chinner * 19728d280b98SDavid Chinner * Simple concept, difficult implementation 19738d280b98SDavid Chinner * 19748d280b98SDavid Chinner * Basically, replace the incore superblock counters with a distributed per cpu 19758d280b98SDavid Chinner * counter for contended fields (e.g. free block count). 19768d280b98SDavid Chinner * 19778d280b98SDavid Chinner * Difficulties arise in that the incore sb is used for ENOSPC checking, and 19788d280b98SDavid Chinner * hence needs to be accurately read when we are running low on space. Hence 19798d280b98SDavid Chinner * there is a method to enable and disable the per-cpu counters based on how 19808d280b98SDavid Chinner * much "stuff" is available in them. 19818d280b98SDavid Chinner * 19828d280b98SDavid Chinner * Basically, a counter is enabled if there is enough free resource to justify 19838d280b98SDavid Chinner * running a per-cpu fast-path. If the per-cpu counter runs out (i.e. a local 19848d280b98SDavid Chinner * ENOSPC), then we disable the counters to synchronise all callers and 19858d280b98SDavid Chinner * re-distribute the available resources. 19868d280b98SDavid Chinner * 19878d280b98SDavid Chinner * If, once we redistributed the available resources, we still get a failure, 19888d280b98SDavid Chinner * we disable the per-cpu counter and go through the slow path. 19898d280b98SDavid Chinner * 19908d280b98SDavid Chinner * The slow path is the current xfs_mod_incore_sb() function. This means that 19919da096fdSMalcolm Parsons * when we disable a per-cpu counter, we need to drain its resources back to 19928d280b98SDavid Chinner * the global superblock. We do this after disabling the counter to prevent 19938d280b98SDavid Chinner * more threads from queueing up on the counter. 19948d280b98SDavid Chinner * 19958d280b98SDavid Chinner * Essentially, this means that we still need a lock in the fast path to enable 19968d280b98SDavid Chinner * synchronisation between the global counters and the per-cpu counters. This 19978d280b98SDavid Chinner * is not a problem because the lock will be local to a CPU almost all the time 19988d280b98SDavid Chinner * and have little contention except when we get to ENOSPC conditions. 19998d280b98SDavid Chinner * 20008d280b98SDavid Chinner * Basically, this lock becomes a barrier that enables us to lock out the fast 20018d280b98SDavid Chinner * path while we do things like enabling and disabling counters and 20028d280b98SDavid Chinner * synchronising the counters. 20038d280b98SDavid Chinner * 20048d280b98SDavid Chinner * Locking rules: 20058d280b98SDavid Chinner * 20063685c2a1SEric Sandeen * 1. m_sb_lock before picking up per-cpu locks 20078d280b98SDavid Chinner * 2. per-cpu locks always picked up via for_each_online_cpu() order 20083685c2a1SEric Sandeen * 3. accurate counter sync requires m_sb_lock + per cpu locks 20098d280b98SDavid Chinner * 4. modifying per-cpu counters requires holding per-cpu lock 20103685c2a1SEric Sandeen * 5. modifying global counters requires holding m_sb_lock 20113685c2a1SEric Sandeen * 6. enabling or disabling a counter requires holding the m_sb_lock 20128d280b98SDavid Chinner * and _none_ of the per-cpu locks. 20138d280b98SDavid Chinner * 20148d280b98SDavid Chinner * Disabled counters are only ever re-enabled by a balance operation 20158d280b98SDavid Chinner * that results in more free resources per CPU than a given threshold. 20168d280b98SDavid Chinner * To ensure counters don't remain disabled, they are rebalanced when 20178d280b98SDavid Chinner * the global resource goes above a higher threshold (i.e. some hysteresis 20188d280b98SDavid Chinner * is present to prevent thrashing). 20198d280b98SDavid Chinner */ 2020e8234a68SDavid Chinner 20215a67e4c5SChandra Seetharaman #ifdef CONFIG_HOTPLUG_CPU 2022e8234a68SDavid Chinner /* 2023e8234a68SDavid Chinner * hot-plug CPU notifier support. 2024e8234a68SDavid Chinner * 20255a67e4c5SChandra Seetharaman * We need a notifier per filesystem as we need to be able to identify 20265a67e4c5SChandra Seetharaman * the filesystem to balance the counters out. This is achieved by 20275a67e4c5SChandra Seetharaman * having a notifier block embedded in the xfs_mount_t and doing pointer 20285a67e4c5SChandra Seetharaman * magic to get the mount pointer from the notifier block address. 2029e8234a68SDavid Chinner */ 2030e8234a68SDavid Chinner STATIC int 2031e8234a68SDavid Chinner xfs_icsb_cpu_notify( 2032e8234a68SDavid Chinner struct notifier_block *nfb, 2033e8234a68SDavid Chinner unsigned long action, 2034e8234a68SDavid Chinner void *hcpu) 2035e8234a68SDavid Chinner { 2036e8234a68SDavid Chinner xfs_icsb_cnts_t *cntp; 2037e8234a68SDavid Chinner xfs_mount_t *mp; 2038e8234a68SDavid Chinner 2039e8234a68SDavid Chinner mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier); 2040e8234a68SDavid Chinner cntp = (xfs_icsb_cnts_t *) 2041e8234a68SDavid Chinner per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu); 2042e8234a68SDavid Chinner switch (action) { 2043e8234a68SDavid Chinner case CPU_UP_PREPARE: 20448bb78442SRafael J. Wysocki case CPU_UP_PREPARE_FROZEN: 2045e8234a68SDavid Chinner /* Easy Case - initialize the area and locks, and 2046e8234a68SDavid Chinner * then rebalance when online does everything else for us. */ 204701e1b69cSDavid Chinner memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); 2048e8234a68SDavid Chinner break; 2049e8234a68SDavid Chinner case CPU_ONLINE: 20508bb78442SRafael J. Wysocki case CPU_ONLINE_FROZEN: 205103135cf7SDavid Chinner xfs_icsb_lock(mp); 205245af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); 205345af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); 205445af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); 205503135cf7SDavid Chinner xfs_icsb_unlock(mp); 2056e8234a68SDavid Chinner break; 2057e8234a68SDavid Chinner case CPU_DEAD: 20588bb78442SRafael J. Wysocki case CPU_DEAD_FROZEN: 2059e8234a68SDavid Chinner /* Disable all the counters, then fold the dead cpu's 2060e8234a68SDavid Chinner * count into the total on the global superblock and 2061e8234a68SDavid Chinner * re-enable the counters. */ 206203135cf7SDavid Chinner xfs_icsb_lock(mp); 20633685c2a1SEric Sandeen spin_lock(&mp->m_sb_lock); 2064e8234a68SDavid Chinner xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT); 2065e8234a68SDavid Chinner xfs_icsb_disable_counter(mp, XFS_SBS_IFREE); 2066e8234a68SDavid Chinner xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS); 2067e8234a68SDavid Chinner 2068e8234a68SDavid Chinner mp->m_sb.sb_icount += cntp->icsb_icount; 2069e8234a68SDavid Chinner mp->m_sb.sb_ifree += cntp->icsb_ifree; 2070e8234a68SDavid Chinner mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; 2071e8234a68SDavid Chinner 207201e1b69cSDavid Chinner memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); 2073e8234a68SDavid Chinner 207445af6c6dSChristoph Hellwig xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0); 207545af6c6dSChristoph Hellwig xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0); 207645af6c6dSChristoph Hellwig xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0); 20773685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 207803135cf7SDavid Chinner xfs_icsb_unlock(mp); 2079e8234a68SDavid Chinner break; 2080e8234a68SDavid Chinner } 2081e8234a68SDavid Chinner 2082e8234a68SDavid Chinner return NOTIFY_OK; 2083e8234a68SDavid Chinner } 20845a67e4c5SChandra Seetharaman #endif /* CONFIG_HOTPLUG_CPU */ 2085e8234a68SDavid Chinner 20868d280b98SDavid Chinner int 20878d280b98SDavid Chinner xfs_icsb_init_counters( 20888d280b98SDavid Chinner xfs_mount_t *mp) 20898d280b98SDavid Chinner { 20908d280b98SDavid Chinner xfs_icsb_cnts_t *cntp; 20918d280b98SDavid Chinner int i; 20928d280b98SDavid Chinner 20938d280b98SDavid Chinner mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t); 20948d280b98SDavid Chinner if (mp->m_sb_cnts == NULL) 20958d280b98SDavid Chinner return -ENOMEM; 20968d280b98SDavid Chinner 20975a67e4c5SChandra Seetharaman #ifdef CONFIG_HOTPLUG_CPU 2098e8234a68SDavid Chinner mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify; 2099e8234a68SDavid Chinner mp->m_icsb_notifier.priority = 0; 21005a67e4c5SChandra Seetharaman register_hotcpu_notifier(&mp->m_icsb_notifier); 21015a67e4c5SChandra Seetharaman #endif /* CONFIG_HOTPLUG_CPU */ 2102e8234a68SDavid Chinner 21038d280b98SDavid Chinner for_each_online_cpu(i) { 21048d280b98SDavid Chinner cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 210501e1b69cSDavid Chinner memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); 21068d280b98SDavid Chinner } 210720b64285SDavid Chinner 210820b64285SDavid Chinner mutex_init(&mp->m_icsb_mutex); 210920b64285SDavid Chinner 21108d280b98SDavid Chinner /* 21118d280b98SDavid Chinner * start with all counters disabled so that the 21128d280b98SDavid Chinner * initial balance kicks us off correctly 21138d280b98SDavid Chinner */ 21148d280b98SDavid Chinner mp->m_icsb_counters = -1; 21158d280b98SDavid Chinner return 0; 21168d280b98SDavid Chinner } 21178d280b98SDavid Chinner 21185478eeadSLachlan McIlroy void 21195478eeadSLachlan McIlroy xfs_icsb_reinit_counters( 21205478eeadSLachlan McIlroy xfs_mount_t *mp) 21215478eeadSLachlan McIlroy { 21225478eeadSLachlan McIlroy xfs_icsb_lock(mp); 21235478eeadSLachlan McIlroy /* 21245478eeadSLachlan McIlroy * start with all counters disabled so that the 21255478eeadSLachlan McIlroy * initial balance kicks us off correctly 21265478eeadSLachlan McIlroy */ 21275478eeadSLachlan McIlroy mp->m_icsb_counters = -1; 212845af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0); 212945af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0); 213045af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); 21315478eeadSLachlan McIlroy xfs_icsb_unlock(mp); 21325478eeadSLachlan McIlroy } 21335478eeadSLachlan McIlroy 2134c962fb79SChristoph Hellwig void 21358d280b98SDavid Chinner xfs_icsb_destroy_counters( 21368d280b98SDavid Chinner xfs_mount_t *mp) 21378d280b98SDavid Chinner { 2138e8234a68SDavid Chinner if (mp->m_sb_cnts) { 21395a67e4c5SChandra Seetharaman unregister_hotcpu_notifier(&mp->m_icsb_notifier); 21408d280b98SDavid Chinner free_percpu(mp->m_sb_cnts); 21418d280b98SDavid Chinner } 214203135cf7SDavid Chinner mutex_destroy(&mp->m_icsb_mutex); 2143e8234a68SDavid Chinner } 21448d280b98SDavid Chinner 2145b8f82a4aSChristoph Hellwig STATIC void 214601e1b69cSDavid Chinner xfs_icsb_lock_cntr( 214701e1b69cSDavid Chinner xfs_icsb_cnts_t *icsbp) 214801e1b69cSDavid Chinner { 214901e1b69cSDavid Chinner while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) { 215001e1b69cSDavid Chinner ndelay(1000); 215101e1b69cSDavid Chinner } 215201e1b69cSDavid Chinner } 215301e1b69cSDavid Chinner 2154b8f82a4aSChristoph Hellwig STATIC void 215501e1b69cSDavid Chinner xfs_icsb_unlock_cntr( 215601e1b69cSDavid Chinner xfs_icsb_cnts_t *icsbp) 215701e1b69cSDavid Chinner { 215801e1b69cSDavid Chinner clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags); 215901e1b69cSDavid Chinner } 216001e1b69cSDavid Chinner 21618d280b98SDavid Chinner 2162b8f82a4aSChristoph Hellwig STATIC void 21638d280b98SDavid Chinner xfs_icsb_lock_all_counters( 21648d280b98SDavid Chinner xfs_mount_t *mp) 21658d280b98SDavid Chinner { 21668d280b98SDavid Chinner xfs_icsb_cnts_t *cntp; 21678d280b98SDavid Chinner int i; 21688d280b98SDavid Chinner 21698d280b98SDavid Chinner for_each_online_cpu(i) { 21708d280b98SDavid Chinner cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 217101e1b69cSDavid Chinner xfs_icsb_lock_cntr(cntp); 21728d280b98SDavid Chinner } 21738d280b98SDavid Chinner } 21748d280b98SDavid Chinner 2175b8f82a4aSChristoph Hellwig STATIC void 21768d280b98SDavid Chinner xfs_icsb_unlock_all_counters( 21778d280b98SDavid Chinner xfs_mount_t *mp) 21788d280b98SDavid Chinner { 21798d280b98SDavid Chinner xfs_icsb_cnts_t *cntp; 21808d280b98SDavid Chinner int i; 21818d280b98SDavid Chinner 21828d280b98SDavid Chinner for_each_online_cpu(i) { 21838d280b98SDavid Chinner cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 218401e1b69cSDavid Chinner xfs_icsb_unlock_cntr(cntp); 21858d280b98SDavid Chinner } 21868d280b98SDavid Chinner } 21878d280b98SDavid Chinner 21888d280b98SDavid Chinner STATIC void 21898d280b98SDavid Chinner xfs_icsb_count( 21908d280b98SDavid Chinner xfs_mount_t *mp, 21918d280b98SDavid Chinner xfs_icsb_cnts_t *cnt, 21928d280b98SDavid Chinner int flags) 21938d280b98SDavid Chinner { 21948d280b98SDavid Chinner xfs_icsb_cnts_t *cntp; 21958d280b98SDavid Chinner int i; 21968d280b98SDavid Chinner 21978d280b98SDavid Chinner memset(cnt, 0, sizeof(xfs_icsb_cnts_t)); 21988d280b98SDavid Chinner 21998d280b98SDavid Chinner if (!(flags & XFS_ICSB_LAZY_COUNT)) 22008d280b98SDavid Chinner xfs_icsb_lock_all_counters(mp); 22018d280b98SDavid Chinner 22028d280b98SDavid Chinner for_each_online_cpu(i) { 22038d280b98SDavid Chinner cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); 22048d280b98SDavid Chinner cnt->icsb_icount += cntp->icsb_icount; 22058d280b98SDavid Chinner cnt->icsb_ifree += cntp->icsb_ifree; 22068d280b98SDavid Chinner cnt->icsb_fdblocks += cntp->icsb_fdblocks; 22078d280b98SDavid Chinner } 22088d280b98SDavid Chinner 22098d280b98SDavid Chinner if (!(flags & XFS_ICSB_LAZY_COUNT)) 22108d280b98SDavid Chinner xfs_icsb_unlock_all_counters(mp); 22118d280b98SDavid Chinner } 22128d280b98SDavid Chinner 22138d280b98SDavid Chinner STATIC int 22148d280b98SDavid Chinner xfs_icsb_counter_disabled( 22158d280b98SDavid Chinner xfs_mount_t *mp, 22168d280b98SDavid Chinner xfs_sb_field_t field) 22178d280b98SDavid Chinner { 22188d280b98SDavid Chinner ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 22198d280b98SDavid Chinner return test_bit(field, &mp->m_icsb_counters); 22208d280b98SDavid Chinner } 22218d280b98SDavid Chinner 222236fbe6e6SDavid Chinner STATIC void 22238d280b98SDavid Chinner xfs_icsb_disable_counter( 22248d280b98SDavid Chinner xfs_mount_t *mp, 22258d280b98SDavid Chinner xfs_sb_field_t field) 22268d280b98SDavid Chinner { 22278d280b98SDavid Chinner xfs_icsb_cnts_t cnt; 22288d280b98SDavid Chinner 22298d280b98SDavid Chinner ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 22308d280b98SDavid Chinner 223120b64285SDavid Chinner /* 223220b64285SDavid Chinner * If we are already disabled, then there is nothing to do 223320b64285SDavid Chinner * here. We check before locking all the counters to avoid 223420b64285SDavid Chinner * the expensive lock operation when being called in the 223520b64285SDavid Chinner * slow path and the counter is already disabled. This is 223620b64285SDavid Chinner * safe because the only time we set or clear this state is under 223720b64285SDavid Chinner * the m_icsb_mutex. 223820b64285SDavid Chinner */ 223920b64285SDavid Chinner if (xfs_icsb_counter_disabled(mp, field)) 224036fbe6e6SDavid Chinner return; 224120b64285SDavid Chinner 22428d280b98SDavid Chinner xfs_icsb_lock_all_counters(mp); 22438d280b98SDavid Chinner if (!test_and_set_bit(field, &mp->m_icsb_counters)) { 22448d280b98SDavid Chinner /* drain back to superblock */ 22458d280b98SDavid Chinner 2246ce46193bSChristoph Hellwig xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT); 22478d280b98SDavid Chinner switch(field) { 22488d280b98SDavid Chinner case XFS_SBS_ICOUNT: 22498d280b98SDavid Chinner mp->m_sb.sb_icount = cnt.icsb_icount; 22508d280b98SDavid Chinner break; 22518d280b98SDavid Chinner case XFS_SBS_IFREE: 22528d280b98SDavid Chinner mp->m_sb.sb_ifree = cnt.icsb_ifree; 22538d280b98SDavid Chinner break; 22548d280b98SDavid Chinner case XFS_SBS_FDBLOCKS: 22558d280b98SDavid Chinner mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; 22568d280b98SDavid Chinner break; 22578d280b98SDavid Chinner default: 22588d280b98SDavid Chinner BUG(); 22598d280b98SDavid Chinner } 22608d280b98SDavid Chinner } 22618d280b98SDavid Chinner 22628d280b98SDavid Chinner xfs_icsb_unlock_all_counters(mp); 22638d280b98SDavid Chinner } 22648d280b98SDavid Chinner 22658d280b98SDavid Chinner STATIC void 22668d280b98SDavid Chinner xfs_icsb_enable_counter( 22678d280b98SDavid Chinner xfs_mount_t *mp, 22688d280b98SDavid Chinner xfs_sb_field_t field, 22698d280b98SDavid Chinner uint64_t count, 22708d280b98SDavid Chinner uint64_t resid) 22718d280b98SDavid Chinner { 22728d280b98SDavid Chinner xfs_icsb_cnts_t *cntp; 22738d280b98SDavid Chinner int i; 22748d280b98SDavid Chinner 22758d280b98SDavid Chinner ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS)); 22768d280b98SDavid Chinner 22778d280b98SDavid Chinner xfs_icsb_lock_all_counters(mp); 22788d280b98SDavid Chinner for_each_online_cpu(i) { 22798d280b98SDavid Chinner cntp = per_cpu_ptr(mp->m_sb_cnts, i); 22808d280b98SDavid Chinner switch (field) { 22818d280b98SDavid Chinner case XFS_SBS_ICOUNT: 22828d280b98SDavid Chinner cntp->icsb_icount = count + resid; 22838d280b98SDavid Chinner break; 22848d280b98SDavid Chinner case XFS_SBS_IFREE: 22858d280b98SDavid Chinner cntp->icsb_ifree = count + resid; 22868d280b98SDavid Chinner break; 22878d280b98SDavid Chinner case XFS_SBS_FDBLOCKS: 22888d280b98SDavid Chinner cntp->icsb_fdblocks = count + resid; 22898d280b98SDavid Chinner break; 22908d280b98SDavid Chinner default: 22918d280b98SDavid Chinner BUG(); 22928d280b98SDavid Chinner break; 22938d280b98SDavid Chinner } 22948d280b98SDavid Chinner resid = 0; 22958d280b98SDavid Chinner } 22968d280b98SDavid Chinner clear_bit(field, &mp->m_icsb_counters); 22978d280b98SDavid Chinner xfs_icsb_unlock_all_counters(mp); 22988d280b98SDavid Chinner } 22998d280b98SDavid Chinner 2300dbcabad1SDavid Chinner void 2301d4d90b57SChristoph Hellwig xfs_icsb_sync_counters_locked( 23028d280b98SDavid Chinner xfs_mount_t *mp, 23038d280b98SDavid Chinner int flags) 23048d280b98SDavid Chinner { 23058d280b98SDavid Chinner xfs_icsb_cnts_t cnt; 23068d280b98SDavid Chinner 23078d280b98SDavid Chinner xfs_icsb_count(mp, &cnt, flags); 23088d280b98SDavid Chinner 23098d280b98SDavid Chinner if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT)) 23108d280b98SDavid Chinner mp->m_sb.sb_icount = cnt.icsb_icount; 23118d280b98SDavid Chinner if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE)) 23128d280b98SDavid Chinner mp->m_sb.sb_ifree = cnt.icsb_ifree; 23138d280b98SDavid Chinner if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS)) 23148d280b98SDavid Chinner mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; 23158d280b98SDavid Chinner } 23168d280b98SDavid Chinner 23178d280b98SDavid Chinner /* 23188d280b98SDavid Chinner * Accurate update of per-cpu counters to incore superblock 23198d280b98SDavid Chinner */ 2320d4d90b57SChristoph Hellwig void 23218d280b98SDavid Chinner xfs_icsb_sync_counters( 2322d4d90b57SChristoph Hellwig xfs_mount_t *mp, 2323d4d90b57SChristoph Hellwig int flags) 23248d280b98SDavid Chinner { 2325d4d90b57SChristoph Hellwig spin_lock(&mp->m_sb_lock); 2326d4d90b57SChristoph Hellwig xfs_icsb_sync_counters_locked(mp, flags); 2327d4d90b57SChristoph Hellwig spin_unlock(&mp->m_sb_lock); 23288d280b98SDavid Chinner } 23298d280b98SDavid Chinner 23308d280b98SDavid Chinner /* 23318d280b98SDavid Chinner * Balance and enable/disable counters as necessary. 23328d280b98SDavid Chinner * 233320b64285SDavid Chinner * Thresholds for re-enabling counters are somewhat magic. inode counts are 233420b64285SDavid Chinner * chosen to be the same number as single on disk allocation chunk per CPU, and 233520b64285SDavid Chinner * free blocks is something far enough zero that we aren't going thrash when we 233620b64285SDavid Chinner * get near ENOSPC. We also need to supply a minimum we require per cpu to 233720b64285SDavid Chinner * prevent looping endlessly when xfs_alloc_space asks for more than will 233820b64285SDavid Chinner * be distributed to a single CPU but each CPU has enough blocks to be 233920b64285SDavid Chinner * reenabled. 234020b64285SDavid Chinner * 234120b64285SDavid Chinner * Note that we can be called when counters are already disabled. 234220b64285SDavid Chinner * xfs_icsb_disable_counter() optimises the counter locking in this case to 234320b64285SDavid Chinner * prevent locking every per-cpu counter needlessly. 23448d280b98SDavid Chinner */ 234520b64285SDavid Chinner 234620b64285SDavid Chinner #define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64 23474be536deSDavid Chinner #define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \ 234820b64285SDavid Chinner (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp)) 23498d280b98SDavid Chinner STATIC void 235045af6c6dSChristoph Hellwig xfs_icsb_balance_counter_locked( 23518d280b98SDavid Chinner xfs_mount_t *mp, 23528d280b98SDavid Chinner xfs_sb_field_t field, 235320b64285SDavid Chinner int min_per_cpu) 23548d280b98SDavid Chinner { 23556fdf8cccSNathan Scott uint64_t count, resid; 23568d280b98SDavid Chinner int weight = num_online_cpus(); 235720b64285SDavid Chinner uint64_t min = (uint64_t)min_per_cpu; 23588d280b98SDavid Chinner 23598d280b98SDavid Chinner /* disable counter and sync counter */ 23608d280b98SDavid Chinner xfs_icsb_disable_counter(mp, field); 23618d280b98SDavid Chinner 23628d280b98SDavid Chinner /* update counters - first CPU gets residual*/ 23638d280b98SDavid Chinner switch (field) { 23648d280b98SDavid Chinner case XFS_SBS_ICOUNT: 23658d280b98SDavid Chinner count = mp->m_sb.sb_icount; 23668d280b98SDavid Chinner resid = do_div(count, weight); 236720b64285SDavid Chinner if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE)) 236845af6c6dSChristoph Hellwig return; 23698d280b98SDavid Chinner break; 23708d280b98SDavid Chinner case XFS_SBS_IFREE: 23718d280b98SDavid Chinner count = mp->m_sb.sb_ifree; 23728d280b98SDavid Chinner resid = do_div(count, weight); 237320b64285SDavid Chinner if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE)) 237445af6c6dSChristoph Hellwig return; 23758d280b98SDavid Chinner break; 23768d280b98SDavid Chinner case XFS_SBS_FDBLOCKS: 23778d280b98SDavid Chinner count = mp->m_sb.sb_fdblocks; 23788d280b98SDavid Chinner resid = do_div(count, weight); 237920b64285SDavid Chinner if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp))) 238045af6c6dSChristoph Hellwig return; 23818d280b98SDavid Chinner break; 23828d280b98SDavid Chinner default: 23838d280b98SDavid Chinner BUG(); 23846fdf8cccSNathan Scott count = resid = 0; /* quiet, gcc */ 23858d280b98SDavid Chinner break; 23868d280b98SDavid Chinner } 23878d280b98SDavid Chinner 23888d280b98SDavid Chinner xfs_icsb_enable_counter(mp, field, count, resid); 238945af6c6dSChristoph Hellwig } 239045af6c6dSChristoph Hellwig 239145af6c6dSChristoph Hellwig STATIC void 239245af6c6dSChristoph Hellwig xfs_icsb_balance_counter( 239345af6c6dSChristoph Hellwig xfs_mount_t *mp, 239445af6c6dSChristoph Hellwig xfs_sb_field_t fields, 239545af6c6dSChristoph Hellwig int min_per_cpu) 239645af6c6dSChristoph Hellwig { 239745af6c6dSChristoph Hellwig spin_lock(&mp->m_sb_lock); 239845af6c6dSChristoph Hellwig xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu); 23993685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 24008d280b98SDavid Chinner } 24018d280b98SDavid Chinner 24021b040712SChristoph Hellwig int 240320b64285SDavid Chinner xfs_icsb_modify_counters( 24048d280b98SDavid Chinner xfs_mount_t *mp, 24058d280b98SDavid Chinner xfs_sb_field_t field, 240620f4ebf2SDavid Chinner int64_t delta, 240720b64285SDavid Chinner int rsvd) 24088d280b98SDavid Chinner { 24098d280b98SDavid Chinner xfs_icsb_cnts_t *icsbp; 24108d280b98SDavid Chinner long long lcounter; /* long counter for 64 bit fields */ 24117a9e02d6SChristoph Lameter int ret = 0; 24128d280b98SDavid Chinner 241320b64285SDavid Chinner might_sleep(); 24148d280b98SDavid Chinner again: 24157a9e02d6SChristoph Lameter preempt_disable(); 24167a9e02d6SChristoph Lameter icsbp = this_cpu_ptr(mp->m_sb_cnts); 241720b64285SDavid Chinner 241820b64285SDavid Chinner /* 241920b64285SDavid Chinner * if the counter is disabled, go to slow path 242020b64285SDavid Chinner */ 24218d280b98SDavid Chinner if (unlikely(xfs_icsb_counter_disabled(mp, field))) 24228d280b98SDavid Chinner goto slow_path; 242320b64285SDavid Chinner xfs_icsb_lock_cntr(icsbp); 242420b64285SDavid Chinner if (unlikely(xfs_icsb_counter_disabled(mp, field))) { 242520b64285SDavid Chinner xfs_icsb_unlock_cntr(icsbp); 242620b64285SDavid Chinner goto slow_path; 242720b64285SDavid Chinner } 24288d280b98SDavid Chinner 24298d280b98SDavid Chinner switch (field) { 24308d280b98SDavid Chinner case XFS_SBS_ICOUNT: 24318d280b98SDavid Chinner lcounter = icsbp->icsb_icount; 24328d280b98SDavid Chinner lcounter += delta; 24338d280b98SDavid Chinner if (unlikely(lcounter < 0)) 243420b64285SDavid Chinner goto balance_counter; 24358d280b98SDavid Chinner icsbp->icsb_icount = lcounter; 24368d280b98SDavid Chinner break; 24378d280b98SDavid Chinner 24388d280b98SDavid Chinner case XFS_SBS_IFREE: 24398d280b98SDavid Chinner lcounter = icsbp->icsb_ifree; 24408d280b98SDavid Chinner lcounter += delta; 24418d280b98SDavid Chinner if (unlikely(lcounter < 0)) 244220b64285SDavid Chinner goto balance_counter; 24438d280b98SDavid Chinner icsbp->icsb_ifree = lcounter; 24448d280b98SDavid Chinner break; 24458d280b98SDavid Chinner 24468d280b98SDavid Chinner case XFS_SBS_FDBLOCKS: 24478d280b98SDavid Chinner BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0); 24488d280b98SDavid Chinner 24494be536deSDavid Chinner lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); 24508d280b98SDavid Chinner lcounter += delta; 24518d280b98SDavid Chinner if (unlikely(lcounter < 0)) 245220b64285SDavid Chinner goto balance_counter; 24534be536deSDavid Chinner icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); 24548d280b98SDavid Chinner break; 24558d280b98SDavid Chinner default: 24568d280b98SDavid Chinner BUG(); 24578d280b98SDavid Chinner break; 24588d280b98SDavid Chinner } 245901e1b69cSDavid Chinner xfs_icsb_unlock_cntr(icsbp); 24607a9e02d6SChristoph Lameter preempt_enable(); 24618d280b98SDavid Chinner return 0; 24628d280b98SDavid Chinner 24638d280b98SDavid Chinner slow_path: 24647a9e02d6SChristoph Lameter preempt_enable(); 246520b64285SDavid Chinner 246620b64285SDavid Chinner /* 246720b64285SDavid Chinner * serialise with a mutex so we don't burn lots of cpu on 246820b64285SDavid Chinner * the superblock lock. We still need to hold the superblock 246920b64285SDavid Chinner * lock, however, when we modify the global structures. 247020b64285SDavid Chinner */ 247103135cf7SDavid Chinner xfs_icsb_lock(mp); 247220b64285SDavid Chinner 247320b64285SDavid Chinner /* 247420b64285SDavid Chinner * Now running atomically. 247520b64285SDavid Chinner * 247620b64285SDavid Chinner * If the counter is enabled, someone has beaten us to rebalancing. 247720b64285SDavid Chinner * Drop the lock and try again in the fast path.... 247820b64285SDavid Chinner */ 247920b64285SDavid Chinner if (!(xfs_icsb_counter_disabled(mp, field))) { 248003135cf7SDavid Chinner xfs_icsb_unlock(mp); 248120b64285SDavid Chinner goto again; 248220b64285SDavid Chinner } 248320b64285SDavid Chinner 248420b64285SDavid Chinner /* 248520b64285SDavid Chinner * The counter is currently disabled. Because we are 248620b64285SDavid Chinner * running atomically here, we know a rebalance cannot 248720b64285SDavid Chinner * be in progress. Hence we can go straight to operating 248820b64285SDavid Chinner * on the global superblock. We do not call xfs_mod_incore_sb() 24893685c2a1SEric Sandeen * here even though we need to get the m_sb_lock. Doing so 249020b64285SDavid Chinner * will cause us to re-enter this function and deadlock. 24913685c2a1SEric Sandeen * Hence we get the m_sb_lock ourselves and then call 249220b64285SDavid Chinner * xfs_mod_incore_sb_unlocked() as the unlocked path operates 249320b64285SDavid Chinner * directly on the global counters. 249420b64285SDavid Chinner */ 24953685c2a1SEric Sandeen spin_lock(&mp->m_sb_lock); 249620b64285SDavid Chinner ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); 24973685c2a1SEric Sandeen spin_unlock(&mp->m_sb_lock); 249820b64285SDavid Chinner 249920b64285SDavid Chinner /* 250020b64285SDavid Chinner * Now that we've modified the global superblock, we 250120b64285SDavid Chinner * may be able to re-enable the distributed counters 250220b64285SDavid Chinner * (e.g. lots of space just got freed). After that 250320b64285SDavid Chinner * we are done. 250420b64285SDavid Chinner */ 250520b64285SDavid Chinner if (ret != ENOSPC) 250645af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, field, 0); 250703135cf7SDavid Chinner xfs_icsb_unlock(mp); 250820b64285SDavid Chinner return ret; 250920b64285SDavid Chinner 251020b64285SDavid Chinner balance_counter: 251101e1b69cSDavid Chinner xfs_icsb_unlock_cntr(icsbp); 25127a9e02d6SChristoph Lameter preempt_enable(); 25138d280b98SDavid Chinner 251420b64285SDavid Chinner /* 251520b64285SDavid Chinner * We may have multiple threads here if multiple per-cpu 251620b64285SDavid Chinner * counters run dry at the same time. This will mean we can 251720b64285SDavid Chinner * do more balances than strictly necessary but it is not 251820b64285SDavid Chinner * the common slowpath case. 251920b64285SDavid Chinner */ 252003135cf7SDavid Chinner xfs_icsb_lock(mp); 252120b64285SDavid Chinner 252220b64285SDavid Chinner /* 252320b64285SDavid Chinner * running atomically. 252420b64285SDavid Chinner * 252520b64285SDavid Chinner * This will leave the counter in the correct state for future 252620b64285SDavid Chinner * accesses. After the rebalance, we simply try again and our retry 252720b64285SDavid Chinner * will either succeed through the fast path or slow path without 252820b64285SDavid Chinner * another balance operation being required. 252920b64285SDavid Chinner */ 253045af6c6dSChristoph Hellwig xfs_icsb_balance_counter(mp, field, delta); 253103135cf7SDavid Chinner xfs_icsb_unlock(mp); 25328d280b98SDavid Chinner goto again; 25338d280b98SDavid Chinner } 25348d280b98SDavid Chinner 25358d280b98SDavid Chinner #endif 2536