aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@sandeen.net>2007-10-11 21:03:40 -0400
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-02-07 02:11:56 -0500
commit0771fb4515229821b7d74865b87a430de9fc1113 (patch)
tree073bec9401cc39ee3f4f01cf549d943c4409d653
parentb53e675dc868c4844ecbcce9149cf68e4299231d (diff)
[XFS] Refactor xfs_mountfs
Refactoring xfs_mountfs() to call sub-functions for logical chunks can help save a bit of stack, and can make it easier to read this long function. The mount path is one of the longest common callchains, easily getting to within a few bytes of the end of a 4k stack when over lvm, quotas are enabled, and quotacheck must be done. With this change on top of the other stack-related changes I've sent, I can get xfs to survive a normal xfsqa run on 4k stacks over lvm. SGI-PV: 971186 SGI-Modid: xfs-linux-melb:xfs-kern:29834a Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Signed-off-by: Donald Douwsma <donaldd@sgi.com> Signed-off-by: Tim Shimmin <tes@sgi.com>
-rw-r--r--fs/xfs/xfs_mount.c267
1 files changed, 162 insertions, 105 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 6115f371663d..2806d43d7d23 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -733,49 +733,13 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
733} 733}
734 734
735/* 735/*
736 * xfs_mountfs 736 * Update alignment values based on mount options and sb values
737 *
738 * This function does the following on an initial mount of a file system:
739 * - reads the superblock from disk and init the mount struct
740 * - if we're a 32-bit kernel, do a size check on the superblock
741 * so we don't mount terabyte filesystems
742 * - init mount struct realtime fields
743 * - allocate inode hash table for fs
744 * - init directory manager
745 * - perform recovery and init the log manager
746 */ 737 */
747int 738STATIC int
748xfs_mountfs( 739xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags)
749 xfs_mount_t *mp,
750 int mfsi_flags)
751{ 740{
752 xfs_buf_t *bp;
753 xfs_sb_t *sbp = &(mp->m_sb); 741 xfs_sb_t *sbp = &(mp->m_sb);
754 xfs_inode_t *rip;
755 bhv_vnode_t *rvp = NULL;
756 int readio_log, writeio_log;
757 xfs_daddr_t d;
758 __uint64_t resblks;
759 __int64_t update_flags;
760 uint quotamount, quotaflags;
761 int agno;
762 int uuid_mounted = 0;
763 int error = 0;
764 742
765 if (mp->m_sb_bp == NULL) {
766 if ((error = xfs_readsb(mp, mfsi_flags))) {
767 return error;
768 }
769 }
770 xfs_mount_common(mp, sbp);
771
772 /*
773 * Check if sb_agblocks is aligned at stripe boundary
774 * If sb_agblocks is NOT aligned turn off m_dalign since
775 * allocator alignment is within an ag, therefore ag has
776 * to be aligned at stripe boundary.
777 */
778 update_flags = 0LL;
779 if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) { 743 if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) {
780 /* 744 /*
781 * If stripe unit and stripe width are not multiples 745 * If stripe unit and stripe width are not multiples
@@ -786,8 +750,7 @@ xfs_mountfs(
786 if (mp->m_flags & XFS_MOUNT_RETERR) { 750 if (mp->m_flags & XFS_MOUNT_RETERR) {
787 cmn_err(CE_WARN, 751 cmn_err(CE_WARN,
788 "XFS: alignment check 1 failed"); 752 "XFS: alignment check 1 failed");
789 error = XFS_ERROR(EINVAL); 753 return XFS_ERROR(EINVAL);
790 goto error1;
791 } 754 }
792 mp->m_dalign = mp->m_swidth = 0; 755 mp->m_dalign = mp->m_swidth = 0;
793 } else { 756 } else {
@@ -797,8 +760,7 @@ xfs_mountfs(
797 mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign); 760 mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
798 if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) { 761 if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
799 if (mp->m_flags & XFS_MOUNT_RETERR) { 762 if (mp->m_flags & XFS_MOUNT_RETERR) {
800 error = XFS_ERROR(EINVAL); 763 return XFS_ERROR(EINVAL);
801 goto error1;
802 } 764 }
803 xfs_fs_cmn_err(CE_WARN, mp, 765 xfs_fs_cmn_err(CE_WARN, mp,
804"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", 766"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
@@ -815,8 +777,7 @@ xfs_mountfs(
815"stripe alignment turned off: sunit(%d) less than bsize(%d)", 777"stripe alignment turned off: sunit(%d) less than bsize(%d)",
816 mp->m_dalign, 778 mp->m_dalign,
817 mp->m_blockmask +1); 779 mp->m_blockmask +1);
818 error = XFS_ERROR(EINVAL); 780 return XFS_ERROR(EINVAL);
819 goto error1;
820 } 781 }
821 mp->m_swidth = 0; 782 mp->m_swidth = 0;
822 } 783 }
@@ -829,11 +790,11 @@ xfs_mountfs(
829 if (XFS_SB_VERSION_HASDALIGN(sbp)) { 790 if (XFS_SB_VERSION_HASDALIGN(sbp)) {
830 if (sbp->sb_unit != mp->m_dalign) { 791 if (sbp->sb_unit != mp->m_dalign) {
831 sbp->sb_unit = mp->m_dalign; 792 sbp->sb_unit = mp->m_dalign;
832 update_flags |= XFS_SB_UNIT; 793 *update_flags |= XFS_SB_UNIT;
833 } 794 }
834 if (sbp->sb_width != mp->m_swidth) { 795 if (sbp->sb_width != mp->m_swidth) {
835 sbp->sb_width = mp->m_swidth; 796 sbp->sb_width = mp->m_swidth;
836 update_flags |= XFS_SB_WIDTH; 797 *update_flags |= XFS_SB_WIDTH;
837 } 798 }
838 } 799 }
839 } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && 800 } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
@@ -842,49 +803,45 @@ xfs_mountfs(
842 mp->m_swidth = sbp->sb_width; 803 mp->m_swidth = sbp->sb_width;
843 } 804 }
844 805
845 xfs_alloc_compute_maxlevels(mp); 806 return 0;
846 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); 807}
847 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
848 xfs_ialloc_compute_maxlevels(mp);
849 808
850 if (sbp->sb_imax_pct) { 809/*
851 __uint64_t icount; 810 * Set the maximum inode count for this filesystem
811 */
812STATIC void
813xfs_set_maxicount(xfs_mount_t *mp)
814{
815 xfs_sb_t *sbp = &(mp->m_sb);
816 __uint64_t icount;
852 817
853 /* Make sure the maximum inode count is a multiple of the 818 if (sbp->sb_imax_pct) {
854 * units we allocate inodes in. 819 /*
820 * Make sure the maximum inode count is a multiple
821 * of the units we allocate inodes in.
855 */ 822 */
856
857 icount = sbp->sb_dblocks * sbp->sb_imax_pct; 823 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
858 do_div(icount, 100); 824 do_div(icount, 100);
859 do_div(icount, mp->m_ialloc_blks); 825 do_div(icount, mp->m_ialloc_blks);
860 mp->m_maxicount = (icount * mp->m_ialloc_blks) << 826 mp->m_maxicount = (icount * mp->m_ialloc_blks) <<
861 sbp->sb_inopblog; 827 sbp->sb_inopblog;
862 } else 828 } else {
863 mp->m_maxicount = 0; 829 mp->m_maxicount = 0;
864
865 mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
866
867 /*
868 * XFS uses the uuid from the superblock as the unique
869 * identifier for fsid. We can not use the uuid from the volume
870 * since a single partition filesystem is identical to a single
871 * partition volume/filesystem.
872 */
873 if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
874 (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
875 if (xfs_uuid_mount(mp)) {
876 error = XFS_ERROR(EINVAL);
877 goto error1;
878 }
879 uuid_mounted=1;
880 } 830 }
831}
832
833/*
834 * Set the default minimum read and write sizes unless
835 * already specified in a mount option.
836 * We use smaller I/O sizes when the file system
837 * is being used for NFS service (wsync mount option).
838 */
839STATIC void
840xfs_set_rw_sizes(xfs_mount_t *mp)
841{
842 xfs_sb_t *sbp = &(mp->m_sb);
843 int readio_log, writeio_log;
881 844
882 /*
883 * Set the default minimum read and write sizes unless
884 * already specified in a mount option.
885 * We use smaller I/O sizes when the file system
886 * is being used for NFS service (wsync mount option).
887 */
888 if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) { 845 if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
889 if (mp->m_flags & XFS_MOUNT_WSYNC) { 846 if (mp->m_flags & XFS_MOUNT_WSYNC) {
890 readio_log = XFS_WSYNC_READIO_LOG; 847 readio_log = XFS_WSYNC_READIO_LOG;
@@ -910,17 +867,14 @@ xfs_mountfs(
910 mp->m_writeio_log = writeio_log; 867 mp->m_writeio_log = writeio_log;
911 } 868 }
912 mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog); 869 mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
870}
913 871
914 /* 872/*
915 * Set the inode cluster size. 873 * Set whether we're using inode alignment.
916 * This may still be overridden by the file system 874 */
917 * block size if it is larger than the chosen cluster size. 875STATIC void
918 */ 876xfs_set_inoalignment(xfs_mount_t *mp)
919 mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE; 877{
920
921 /*
922 * Set whether we're using inode alignment.
923 */
924 if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) && 878 if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) &&
925 mp->m_sb.sb_inoalignmt >= 879 mp->m_sb.sb_inoalignmt >=
926 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) 880 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
@@ -936,14 +890,22 @@ xfs_mountfs(
936 mp->m_sinoalign = mp->m_dalign; 890 mp->m_sinoalign = mp->m_dalign;
937 else 891 else
938 mp->m_sinoalign = 0; 892 mp->m_sinoalign = 0;
939 /* 893}
940 * Check that the data (and log if separate) are an ok size. 894
941 */ 895/*
896 * Check that the data (and log if separate) are an ok size.
897 */
898STATIC int
899xfs_check_sizes(xfs_mount_t *mp, int mfsi_flags)
900{
901 xfs_buf_t *bp;
902 xfs_daddr_t d;
903 int error;
904
942 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); 905 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
943 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { 906 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
944 cmn_err(CE_WARN, "XFS: size check 1 failed"); 907 cmn_err(CE_WARN, "XFS: size check 1 failed");
945 error = XFS_ERROR(E2BIG); 908 return XFS_ERROR(E2BIG);
946 goto error1;
947 } 909 }
948 error = xfs_read_buf(mp, mp->m_ddev_targp, 910 error = xfs_read_buf(mp, mp->m_ddev_targp,
949 d - XFS_FSS_TO_BB(mp, 1), 911 d - XFS_FSS_TO_BB(mp, 1),
@@ -952,10 +914,9 @@ xfs_mountfs(
952 xfs_buf_relse(bp); 914 xfs_buf_relse(bp);
953 } else { 915 } else {
954 cmn_err(CE_WARN, "XFS: size check 2 failed"); 916 cmn_err(CE_WARN, "XFS: size check 2 failed");
955 if (error == ENOSPC) { 917 if (error == ENOSPC)
956 error = XFS_ERROR(E2BIG); 918 error = XFS_ERROR(E2BIG);
957 } 919 return error;
958 goto error1;
959 } 920 }
960 921
961 if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) && 922 if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) &&
@@ -963,8 +924,7 @@ xfs_mountfs(
963 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); 924 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
964 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { 925 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
965 cmn_err(CE_WARN, "XFS: size check 3 failed"); 926 cmn_err(CE_WARN, "XFS: size check 3 failed");
966 error = XFS_ERROR(E2BIG); 927 return XFS_ERROR(E2BIG);
967 goto error1;
968 } 928 }
969 error = xfs_read_buf(mp, mp->m_logdev_targp, 929 error = xfs_read_buf(mp, mp->m_logdev_targp,
970 d - XFS_FSB_TO_BB(mp, 1), 930 d - XFS_FSB_TO_BB(mp, 1),
@@ -973,17 +933,111 @@ xfs_mountfs(
973 xfs_buf_relse(bp); 933 xfs_buf_relse(bp);
974 } else { 934 } else {
975 cmn_err(CE_WARN, "XFS: size check 3 failed"); 935 cmn_err(CE_WARN, "XFS: size check 3 failed");
976 if (error == ENOSPC) { 936 if (error == ENOSPC)
977 error = XFS_ERROR(E2BIG); 937 error = XFS_ERROR(E2BIG);
978 } 938 return error;
939 }
940 }
941 return 0;
942}
943
944/*
945 * xfs_mountfs
946 *
947 * This function does the following on an initial mount of a file system:
948 * - reads the superblock from disk and init the mount struct
949 * - if we're a 32-bit kernel, do a size check on the superblock
950 * so we don't mount terabyte filesystems
951 * - init mount struct realtime fields
952 * - allocate inode hash table for fs
953 * - init directory manager
954 * - perform recovery and init the log manager
955 */
956int
957xfs_mountfs(
958 xfs_mount_t *mp,
959 int mfsi_flags)
960{
961 xfs_sb_t *sbp = &(mp->m_sb);
962 xfs_inode_t *rip;
963 bhv_vnode_t *rvp = NULL;
964 __uint64_t resblks;
965 __int64_t update_flags = 0LL;
966 uint quotamount, quotaflags;
967 int agno;
968 int uuid_mounted = 0;
969 int error = 0;
970
971 if (mp->m_sb_bp == NULL) {
972 error = xfs_readsb(mp, mfsi_flags);
973 if (error)
974 return error;
975 }
976 xfs_mount_common(mp, sbp);
977
978 /*
979 * Check if sb_agblocks is aligned at stripe boundary
980 * If sb_agblocks is NOT aligned turn off m_dalign since
981 * allocator alignment is within an ag, therefore ag has
982 * to be aligned at stripe boundary.
983 */
984 error = xfs_update_alignment(mp, mfsi_flags, &update_flags);
985 if (error)
986 goto error1;
987
988 xfs_alloc_compute_maxlevels(mp);
989 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
990 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
991 xfs_ialloc_compute_maxlevels(mp);
992
993 xfs_set_maxicount(mp);
994
995 mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
996
997 /*
998 * XFS uses the uuid from the superblock as the unique
999 * identifier for fsid. We can not use the uuid from the volume
1000 * since a single partition filesystem is identical to a single
1001 * partition volume/filesystem.
1002 */
1003 if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
1004 (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
1005 if (xfs_uuid_mount(mp)) {
1006 error = XFS_ERROR(EINVAL);
979 goto error1; 1007 goto error1;
980 } 1008 }
1009 uuid_mounted=1;
981 } 1010 }
982 1011
983 /* 1012 /*
1013 * Set the minimum read and write sizes
1014 */
1015 xfs_set_rw_sizes(mp);
1016
1017 /*
1018 * Set the inode cluster size.
1019 * This may still be overridden by the file system
1020 * block size if it is larger than the chosen cluster size.
1021 */
1022 mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
1023
1024 /*
1025 * Set inode alignment fields
1026 */
1027 xfs_set_inoalignment(mp);
1028
1029 /*
1030 * Check that the data (and log if separate) are an ok size.
1031 */
1032 error = xfs_check_sizes(mp, mfsi_flags);
1033 if (error)
1034 goto error1;
1035
1036 /*
984 * Initialize realtime fields in the mount structure 1037 * Initialize realtime fields in the mount structure
985 */ 1038 */
986 if ((error = xfs_rtmount_init(mp))) { 1039 error = xfs_rtmount_init(mp);
1040 if (error) {
987 cmn_err(CE_WARN, "XFS: RT mount failed"); 1041 cmn_err(CE_WARN, "XFS: RT mount failed");
988 goto error1; 1042 goto error1;
989 } 1043 }
@@ -1101,7 +1155,8 @@ xfs_mountfs(
1101 /* 1155 /*
1102 * Initialize realtime inode pointers in the mount structure 1156 * Initialize realtime inode pointers in the mount structure
1103 */ 1157 */
1104 if ((error = xfs_rtmount_inodes(mp))) { 1158 error = xfs_rtmount_inodes(mp);
1159 if (error) {
1105 /* 1160 /*
1106 * Free up the root inode. 1161 * Free up the root inode.
1107 */ 1162 */
@@ -1119,7 +1174,8 @@ xfs_mountfs(
1119 /* 1174 /*
1120 * Initialise the XFS quota management subsystem for this mount 1175 * Initialise the XFS quota management subsystem for this mount
1121 */ 1176 */
1122 if ((error = XFS_QM_INIT(mp, &quotamount, &quotaflags))) 1177 error = XFS_QM_INIT(mp, &quotamount, &quotaflags);
1178 if (error)
1123 goto error4; 1179 goto error4;
1124 1180
1125 /* 1181 /*
@@ -1136,7 +1192,8 @@ xfs_mountfs(
1136 /* 1192 /*
1137 * Complete the quota initialisation, post-log-replay component. 1193 * Complete the quota initialisation, post-log-replay component.
1138 */ 1194 */
1139 if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags))) 1195 error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags);
1196 if (error)
1140 goto error4; 1197 goto error4;
1141 1198
1142 /* 1199 /*