diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 63 |
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 | |||
209 | xfs_free_perag( | 209 | xfs_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 | ||
392 | xfs_agnumber_t | 395 | int |
393 | xfs_initialize_perag( | 396 | xfs_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 | ||
460 | void | 493 | void |
@@ -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"); |