aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 9055b60730d0..c04dd83cb57c 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -209,13 +209,16 @@ STATIC void
209xfs_free_perag( 209xfs_free_perag(
210 xfs_mount_t *mp) 210 xfs_mount_t *mp)
211{ 211{
212 if (mp->m_perag) { 212 xfs_agnumber_t agno;
213 int agno; 213 struct xfs_perag *pag;
214 214
215 for (agno = 0; agno < mp->m_maxagi; agno++) 215 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
216 if (mp->m_perag[agno].pagb_list) 216 spin_lock(&mp->m_perag_lock);
217 kmem_free(mp->m_perag[agno].pagb_list); 217 pag = radix_tree_delete(&mp->m_perag_tree, agno);
218 kmem_free(mp->m_perag); 218 spin_unlock(&mp->m_perag_lock);
219 ASSERT(pag);
220 kmem_free(pag->pagb_list);
221 kmem_free(pag);
219 } 222 }
220} 223}
221 224
@@ -389,10 +392,11 @@ xfs_initialize_perag_icache(
389 } 392 }
390} 393}
391 394
392xfs_agnumber_t 395int
393xfs_initialize_perag( 396xfs_initialize_perag(
394 xfs_mount_t *mp, 397 xfs_mount_t *mp,
395 xfs_agnumber_t agcount) 398 xfs_agnumber_t agcount,
399 xfs_agnumber_t *maxagi)
396{ 400{
397 xfs_agnumber_t index, max_metadata; 401 xfs_agnumber_t index, max_metadata;
398 xfs_perag_t *pag; 402 xfs_perag_t *pag;
@@ -405,6 +409,33 @@ xfs_initialize_perag(
405 agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); 409 agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
406 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); 410 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
407 411
412 /*
413 * Walk the current per-ag tree so we don't try to initialise AGs
414 * that already exist (growfs case). Allocate and insert all the
415 * AGs we don't find ready for initialisation.
416 */
417 for (index = 0; index < agcount; index++) {
418 pag = xfs_perag_get(mp, index);
419 if (pag) {
420 xfs_perag_put(pag);
421 continue;
422 }
423 pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
424 if (!pag)
425 return -ENOMEM;
426 if (radix_tree_preload(GFP_NOFS))
427 return -ENOMEM;
428 spin_lock(&mp->m_perag_lock);
429 if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
430 BUG();
431 spin_unlock(&mp->m_perag_lock);
432 kmem_free(pag);
433 return -EEXIST;
434 }
435 spin_unlock(&mp->m_perag_lock);
436 radix_tree_preload_end();
437 }
438
408 /* Clear the mount flag if no inode can overflow 32 bits 439 /* Clear the mount flag if no inode can overflow 32 bits
409 * on this filesystem, or if specifically requested.. 440 * on this filesystem, or if specifically requested..
410 */ 441 */
@@ -454,7 +485,9 @@ xfs_initialize_perag(
454 xfs_perag_put(pag); 485 xfs_perag_put(pag);
455 } 486 }
456 } 487 }
457 return index; 488 if (maxagi)
489 *maxagi = index;
490 return 0;
458} 491}
459 492
460void 493void
@@ -1155,13 +1188,13 @@ xfs_mountfs(
1155 /* 1188 /*
1156 * Allocate and initialize the per-ag data. 1189 * Allocate and initialize the per-ag data.
1157 */ 1190 */
1158 init_rwsem(&mp->m_peraglock); 1191 spin_lock_init(&mp->m_perag_lock);
1159 mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), 1192 INIT_RADIX_TREE(&mp->m_perag_tree, GFP_NOFS);
1160 KM_MAYFAIL); 1193 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
1161 if (!mp->m_perag) 1194 if (error) {
1195 cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
1162 goto out_remove_uuid; 1196 goto out_remove_uuid;
1163 1197 }
1164 mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
1165 1198
1166 if (!sbp->sb_logblocks) { 1199 if (!sbp->sb_logblocks) {
1167 cmn_err(CE_WARN, "XFS: no log defined"); 1200 cmn_err(CE_WARN, "XFS: no log defined");