aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-07-04 10:54:50 -0400
committerBen Myers <bpm@sgi.com>2012-07-29 17:10:54 -0400
commitbe60fe54b216a62403b816d3930a66ad7c51cbc6 (patch)
tree20ae0c5de24e347a42f49a33802de67ff6ee4442 /fs/xfs
parent55d6af64cb8bf8c7e9a84b254d2c3479be8c067c (diff)
xfs: do not read the AGI buffer in xfs_dialloc until nessecary
Refactor the AG selection loop in xfs_dialloc to operate on the in-memory perag data as much as possible. We only read the AGI buffer once we have selected an AG to allocate inodes now instead of for every AG considered. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_ialloc.c127
1 files changed, 69 insertions, 58 deletions
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index ecb9f22a7f35..21e37b55f7e5 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -900,11 +900,10 @@ xfs_dialloc(
900 struct xfs_mount *mp = tp->t_mountp; 900 struct xfs_mount *mp = tp->t_mountp;
901 struct xfs_buf *agbp; 901 struct xfs_buf *agbp;
902 xfs_agnumber_t agno; 902 xfs_agnumber_t agno;
903 struct xfs_agi *agi;
904 int error; 903 int error;
905 int ialloced; 904 int ialloced;
906 int noroom = 0; 905 int noroom = 0;
907 xfs_agnumber_t tagno; 906 xfs_agnumber_t start_agno;
908 struct xfs_perag *pag; 907 struct xfs_perag *pag;
909 908
910 if (*IO_agbp) { 909 if (*IO_agbp) {
@@ -921,25 +920,17 @@ xfs_dialloc(
921 * We do not have an agbp, so select an initial allocation 920 * We do not have an agbp, so select an initial allocation
922 * group for inode allocation. 921 * group for inode allocation.
923 */ 922 */
924 agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc); 923 start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
925 if (agno == NULLAGNUMBER) { 924 if (start_agno == NULLAGNUMBER) {
926 *inop = NULLFSINO; 925 *inop = NULLFSINO;
927 return 0; 926 return 0;
928 } 927 }
929 928
930 error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
931 if (error)
932 return XFS_ERROR(error);
933 agi = XFS_BUF_TO_AGI(agbp);
934
935 tagno = agno;
936
937 /* 929 /*
938 * If we have already hit the ceiling of inode blocks then clear 930 * If we have already hit the ceiling of inode blocks then clear
939 * okalloc so we scan all available agi structures for a free 931 * okalloc so we scan all available agi structures for a free
940 * inode. 932 * inode.
941 */ 933 */
942
943 if (mp->m_maxicount && 934 if (mp->m_maxicount &&
944 mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) { 935 mp->m_sb.sb_icount + XFS_IALLOC_INODES(mp) > mp->m_maxicount) {
945 noroom = 1; 936 noroom = 1;
@@ -951,67 +942,87 @@ xfs_dialloc(
951 * or in which we can allocate some inodes. Iterate through the 942 * or in which we can allocate some inodes. Iterate through the
952 * allocation groups upward, wrapping at the end. 943 * allocation groups upward, wrapping at the end.
953 */ 944 */
954 while (!agi->agi_freecount) { 945 agno = start_agno;
955 /* 946 for (;;) {
956 * Don't do anything if we're not supposed to allocate 947 pag = xfs_perag_get(mp, agno);
957 * any blocks, just go on to the next ag. 948 if (!pag->pagi_inodeok) {
958 */ 949 xfs_ialloc_next_ag(mp);
959 if (okalloc) { 950 goto nextag;
960 /* 951 }
961 * Try to allocate some new inodes in the allocation 952
962 * group. 953 if (!pag->pagi_init) {
963 */ 954 error = xfs_ialloc_pagi_init(mp, tp, agno);
964 if ((error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced))) { 955 if (error)
965 xfs_trans_brelse(tp, agbp); 956 goto out_error;
966 if (error == ENOSPC) {
967 *inop = NULLFSINO;
968 return 0;
969 } else
970 return error;
971 }
972 if (ialloced) {
973 /*
974 * We successfully allocated some inodes, return
975 * the current context to the caller so that it
976 * can commit the current transaction and call
977 * us again where we left off.
978 */
979 ASSERT(be32_to_cpu(agi->agi_freecount) > 0);
980 *IO_agbp = agbp;
981 *inop = NULLFSINO;
982 return 0;
983 }
984 } 957 }
958
985 /* 959 /*
986 * If it failed, give up on this ag. 960 * Do a first racy fast path check if this AG is usable.
987 */ 961 */
988 xfs_trans_brelse(tp, agbp); 962 if (!pag->pagi_freecount && !okalloc)
963 goto nextag;
964
965 error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
966 if (error)
967 goto out_error;
968
989 /* 969 /*
990 * Go on to the next ag: get its ag header. 970 * Once the AGI has been read in we have to recheck
971 * pagi_freecount with the AGI buffer lock held.
991 */ 972 */
992nextag: 973 if (pag->pagi_freecount) {
993 if (++tagno == mp->m_sb.sb_agcount) 974 xfs_perag_put(pag);
994 tagno = 0; 975 goto out_alloc;
995 if (tagno == agno) { 976 }
977
978 if (!okalloc) {
979 xfs_trans_brelse(tp, agbp);
980 goto nextag;
981 }
982
983 error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced);
984 if (error) {
985 xfs_trans_brelse(tp, agbp);
986
987 if (error != ENOSPC)
988 goto out_error;
989
990 xfs_perag_put(pag);
996 *inop = NULLFSINO; 991 *inop = NULLFSINO;
997 return noroom ? ENOSPC : 0; 992 return 0;
998 } 993 }
999 pag = xfs_perag_get(mp, tagno); 994
1000 if (pag->pagi_inodeok == 0) { 995 if (ialloced) {
996 /*
997 * We successfully allocated some inodes, return
998 * the current context to the caller so that it
999 * can commit the current transaction and call
1000 * us again where we left off.
1001 */
1002 ASSERT(pag->pagi_freecount > 0);
1001 xfs_perag_put(pag); 1003 xfs_perag_put(pag);
1002 goto nextag; 1004
1005 *IO_agbp = agbp;
1006 *inop = NULLFSINO;
1007 return 0;
1003 } 1008 }
1004 error = xfs_ialloc_read_agi(mp, tp, tagno, &agbp); 1009
1010nextag:
1005 xfs_perag_put(pag); 1011 xfs_perag_put(pag);
1006 if (error) 1012 if (++agno == mp->m_sb.sb_agcount)
1007 goto nextag; 1013 agno = 0;
1008 agi = XFS_BUF_TO_AGI(agbp); 1014 if (agno == start_agno) {
1009 ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); 1015 *inop = NULLFSINO;
1016 return noroom ? ENOSPC : 0;
1017 }
1010 } 1018 }
1011 1019
1012out_alloc: 1020out_alloc:
1013 *IO_agbp = NULL; 1021 *IO_agbp = NULL;
1014 return xfs_dialloc_ag(tp, agbp, parent, inop); 1022 return xfs_dialloc_ag(tp, agbp, parent, inop);
1023out_error:
1024 xfs_perag_put(pag);
1025 return XFS_ERROR(error);
1015} 1026}
1016 1027
1017/* 1028/*