diff options
| -rw-r--r-- | fs/xfs/xfs_ialloc.c | 127 |
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 | */ |
| 992 | nextag: | 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 | |
| 1010 | nextag: | ||
| 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 | ||
| 1012 | out_alloc: | 1020 | out_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); |
| 1023 | out_error: | ||
| 1024 | xfs_perag_put(pag); | ||
| 1025 | return XFS_ERROR(error); | ||
| 1015 | } | 1026 | } |
| 1016 | 1027 | ||
| 1017 | /* | 1028 | /* |
