diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 68 |
1 files changed, 29 insertions, 39 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index d7bf38c8cd1c..d59f4e8bedcf 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -268,10 +268,10 @@ xfs_sb_validate_fsb_count( | |||
268 | 268 | ||
269 | #if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ | 269 | #if XFS_BIG_BLKNOS /* Limited by ULONG_MAX of page cache index */ |
270 | if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX) | 270 | if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX) |
271 | return E2BIG; | 271 | return EFBIG; |
272 | #else /* Limited by UINT_MAX of sectors */ | 272 | #else /* Limited by UINT_MAX of sectors */ |
273 | if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX) | 273 | if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX) |
274 | return E2BIG; | 274 | return EFBIG; |
275 | #endif | 275 | #endif |
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
@@ -393,7 +393,7 @@ xfs_mount_validate_sb( | |||
393 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { | 393 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { |
394 | xfs_fs_mount_cmn_err(flags, | 394 | xfs_fs_mount_cmn_err(flags, |
395 | "file system too large to be mounted on this system."); | 395 | "file system too large to be mounted on this system."); |
396 | return XFS_ERROR(E2BIG); | 396 | return XFS_ERROR(EFBIG); |
397 | } | 397 | } |
398 | 398 | ||
399 | if (unlikely(sbp->sb_inprogress)) { | 399 | if (unlikely(sbp->sb_inprogress)) { |
@@ -413,17 +413,6 @@ xfs_mount_validate_sb( | |||
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | 415 | ||
416 | STATIC void | ||
417 | xfs_initialize_perag_icache( | ||
418 | xfs_perag_t *pag) | ||
419 | { | ||
420 | if (!pag->pag_ici_init) { | ||
421 | rwlock_init(&pag->pag_ici_lock); | ||
422 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); | ||
423 | pag->pag_ici_init = 1; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | int | 416 | int |
428 | xfs_initialize_perag( | 417 | xfs_initialize_perag( |
429 | xfs_mount_t *mp, | 418 | xfs_mount_t *mp, |
@@ -436,13 +425,8 @@ xfs_initialize_perag( | |||
436 | xfs_agino_t agino; | 425 | xfs_agino_t agino; |
437 | xfs_ino_t ino; | 426 | xfs_ino_t ino; |
438 | xfs_sb_t *sbp = &mp->m_sb; | 427 | xfs_sb_t *sbp = &mp->m_sb; |
439 | xfs_ino_t max_inum = XFS_MAXINUMBER_32; | ||
440 | int error = -ENOMEM; | 428 | int error = -ENOMEM; |
441 | 429 | ||
442 | /* Check to see if the filesystem can overflow 32 bit inodes */ | ||
443 | agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); | ||
444 | ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); | ||
445 | |||
446 | /* | 430 | /* |
447 | * Walk the current per-ag tree so we don't try to initialise AGs | 431 | * Walk the current per-ag tree so we don't try to initialise AGs |
448 | * that already exist (growfs case). Allocate and insert all the | 432 | * that already exist (growfs case). Allocate and insert all the |
@@ -456,11 +440,18 @@ xfs_initialize_perag( | |||
456 | } | 440 | } |
457 | if (!first_initialised) | 441 | if (!first_initialised) |
458 | first_initialised = index; | 442 | first_initialised = index; |
443 | |||
459 | pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); | 444 | pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); |
460 | if (!pag) | 445 | if (!pag) |
461 | goto out_unwind; | 446 | goto out_unwind; |
447 | pag->pag_agno = index; | ||
448 | pag->pag_mount = mp; | ||
449 | rwlock_init(&pag->pag_ici_lock); | ||
450 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); | ||
451 | |||
462 | if (radix_tree_preload(GFP_NOFS)) | 452 | if (radix_tree_preload(GFP_NOFS)) |
463 | goto out_unwind; | 453 | goto out_unwind; |
454 | |||
464 | spin_lock(&mp->m_perag_lock); | 455 | spin_lock(&mp->m_perag_lock); |
465 | if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { | 456 | if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { |
466 | BUG(); | 457 | BUG(); |
@@ -469,25 +460,26 @@ xfs_initialize_perag( | |||
469 | error = -EEXIST; | 460 | error = -EEXIST; |
470 | goto out_unwind; | 461 | goto out_unwind; |
471 | } | 462 | } |
472 | pag->pag_agno = index; | ||
473 | pag->pag_mount = mp; | ||
474 | spin_unlock(&mp->m_perag_lock); | 463 | spin_unlock(&mp->m_perag_lock); |
475 | radix_tree_preload_end(); | 464 | radix_tree_preload_end(); |
476 | } | 465 | } |
477 | 466 | ||
478 | /* Clear the mount flag if no inode can overflow 32 bits | 467 | /* |
479 | * on this filesystem, or if specifically requested.. | 468 | * If we mount with the inode64 option, or no inode overflows |
469 | * the legacy 32-bit address space clear the inode32 option. | ||
480 | */ | 470 | */ |
481 | if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) { | 471 | agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0); |
472 | ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino); | ||
473 | |||
474 | if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32) | ||
482 | mp->m_flags |= XFS_MOUNT_32BITINODES; | 475 | mp->m_flags |= XFS_MOUNT_32BITINODES; |
483 | } else { | 476 | else |
484 | mp->m_flags &= ~XFS_MOUNT_32BITINODES; | 477 | mp->m_flags &= ~XFS_MOUNT_32BITINODES; |
485 | } | ||
486 | 478 | ||
487 | /* If we can overflow then setup the ag headers accordingly */ | ||
488 | if (mp->m_flags & XFS_MOUNT_32BITINODES) { | 479 | if (mp->m_flags & XFS_MOUNT_32BITINODES) { |
489 | /* Calculate how much should be reserved for inodes to | 480 | /* |
490 | * meet the max inode percentage. | 481 | * Calculate how much should be reserved for inodes to meet |
482 | * the max inode percentage. | ||
491 | */ | 483 | */ |
492 | if (mp->m_maxicount) { | 484 | if (mp->m_maxicount) { |
493 | __uint64_t icount; | 485 | __uint64_t icount; |
@@ -500,30 +492,28 @@ xfs_initialize_perag( | |||
500 | } else { | 492 | } else { |
501 | max_metadata = agcount; | 493 | max_metadata = agcount; |
502 | } | 494 | } |
495 | |||
503 | for (index = 0; index < agcount; index++) { | 496 | for (index = 0; index < agcount; index++) { |
504 | ino = XFS_AGINO_TO_INO(mp, index, agino); | 497 | ino = XFS_AGINO_TO_INO(mp, index, agino); |
505 | if (ino > max_inum) { | 498 | if (ino > XFS_MAXINUMBER_32) { |
506 | index++; | 499 | index++; |
507 | break; | 500 | break; |
508 | } | 501 | } |
509 | 502 | ||
510 | /* This ag is preferred for inodes */ | ||
511 | pag = xfs_perag_get(mp, index); | 503 | pag = xfs_perag_get(mp, index); |
512 | pag->pagi_inodeok = 1; | 504 | pag->pagi_inodeok = 1; |
513 | if (index < max_metadata) | 505 | if (index < max_metadata) |
514 | pag->pagf_metadata = 1; | 506 | pag->pagf_metadata = 1; |
515 | xfs_initialize_perag_icache(pag); | ||
516 | xfs_perag_put(pag); | 507 | xfs_perag_put(pag); |
517 | } | 508 | } |
518 | } else { | 509 | } else { |
519 | /* Setup default behavior for smaller filesystems */ | ||
520 | for (index = 0; index < agcount; index++) { | 510 | for (index = 0; index < agcount; index++) { |
521 | pag = xfs_perag_get(mp, index); | 511 | pag = xfs_perag_get(mp, index); |
522 | pag->pagi_inodeok = 1; | 512 | pag->pagi_inodeok = 1; |
523 | xfs_initialize_perag_icache(pag); | ||
524 | xfs_perag_put(pag); | 513 | xfs_perag_put(pag); |
525 | } | 514 | } |
526 | } | 515 | } |
516 | |||
527 | if (maxagi) | 517 | if (maxagi) |
528 | *maxagi = index; | 518 | *maxagi = index; |
529 | return 0; | 519 | return 0; |
@@ -1009,7 +999,7 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
1009 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); | 999 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); |
1010 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { | 1000 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { |
1011 | cmn_err(CE_WARN, "XFS: size check 1 failed"); | 1001 | cmn_err(CE_WARN, "XFS: size check 1 failed"); |
1012 | return XFS_ERROR(E2BIG); | 1002 | return XFS_ERROR(EFBIG); |
1013 | } | 1003 | } |
1014 | error = xfs_read_buf(mp, mp->m_ddev_targp, | 1004 | error = xfs_read_buf(mp, mp->m_ddev_targp, |
1015 | d - XFS_FSS_TO_BB(mp, 1), | 1005 | d - XFS_FSS_TO_BB(mp, 1), |
@@ -1019,7 +1009,7 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
1019 | } else { | 1009 | } else { |
1020 | cmn_err(CE_WARN, "XFS: size check 2 failed"); | 1010 | cmn_err(CE_WARN, "XFS: size check 2 failed"); |
1021 | if (error == ENOSPC) | 1011 | if (error == ENOSPC) |
1022 | error = XFS_ERROR(E2BIG); | 1012 | error = XFS_ERROR(EFBIG); |
1023 | return error; | 1013 | return error; |
1024 | } | 1014 | } |
1025 | 1015 | ||
@@ -1027,7 +1017,7 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
1027 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); | 1017 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); |
1028 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { | 1018 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { |
1029 | cmn_err(CE_WARN, "XFS: size check 3 failed"); | 1019 | cmn_err(CE_WARN, "XFS: size check 3 failed"); |
1030 | return XFS_ERROR(E2BIG); | 1020 | return XFS_ERROR(EFBIG); |
1031 | } | 1021 | } |
1032 | error = xfs_read_buf(mp, mp->m_logdev_targp, | 1022 | error = xfs_read_buf(mp, mp->m_logdev_targp, |
1033 | d - XFS_FSB_TO_BB(mp, 1), | 1023 | d - XFS_FSB_TO_BB(mp, 1), |
@@ -1037,7 +1027,7 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
1037 | } else { | 1027 | } else { |
1038 | cmn_err(CE_WARN, "XFS: size check 3 failed"); | 1028 | cmn_err(CE_WARN, "XFS: size check 3 failed"); |
1039 | if (error == ENOSPC) | 1029 | if (error == ENOSPC) |
1040 | error = XFS_ERROR(E2BIG); | 1030 | error = XFS_ERROR(EFBIG); |
1041 | return error; | 1031 | return error; |
1042 | } | 1032 | } |
1043 | } | 1033 | } |
@@ -1254,7 +1244,7 @@ xfs_mountfs( | |||
1254 | * Allocate and initialize the per-ag data. | 1244 | * Allocate and initialize the per-ag data. |
1255 | */ | 1245 | */ |
1256 | spin_lock_init(&mp->m_perag_lock); | 1246 | spin_lock_init(&mp->m_perag_lock); |
1257 | INIT_RADIX_TREE(&mp->m_perag_tree, GFP_NOFS); | 1247 | INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); |
1258 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); | 1248 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); |
1259 | if (error) { | 1249 | if (error) { |
1260 | cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); | 1250 | cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); |