diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 31 |
1 files changed, 4 insertions, 27 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 27d64d752eab..37c4952c2f53 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -1326,6 +1326,8 @@ xfs_alloc_ag_vextent_small( | |||
1326 | if (error) | 1326 | if (error) |
1327 | goto error0; | 1327 | goto error0; |
1328 | if (fbno != NULLAGBLOCK) { | 1328 | if (fbno != NULLAGBLOCK) { |
1329 | if (xfs_alloc_busy_search(args->mp, args->agno, fbno, 1)) | ||
1330 | xfs_trans_set_sync(args->tp); | ||
1329 | if (args->userdata) { | 1331 | if (args->userdata) { |
1330 | xfs_buf_t *bp; | 1332 | xfs_buf_t *bp; |
1331 | 1333 | ||
@@ -1617,18 +1619,6 @@ xfs_free_ag_extent( | |||
1617 | 1619 | ||
1618 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); | 1620 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); |
1619 | 1621 | ||
1620 | /* | ||
1621 | * Since blocks move to the free list without the coordination | ||
1622 | * used in xfs_bmap_finish, we can't allow block to be available | ||
1623 | * for reallocation and non-transaction writing (user data) | ||
1624 | * until we know that the transaction that moved it to the free | ||
1625 | * list is permanently on disk. We track the blocks by declaring | ||
1626 | * these blocks as "busy"; the busy list is maintained on a per-ag | ||
1627 | * basis and each transaction records which entries should be removed | ||
1628 | * when the iclog commits to disk. If a busy block is allocated, | ||
1629 | * the iclog is pushed up to the LSN that freed the block. | ||
1630 | */ | ||
1631 | xfs_alloc_busy_insert(tp, agno, bno, len); | ||
1632 | return 0; | 1622 | return 0; |
1633 | 1623 | ||
1634 | error0: | 1624 | error0: |
@@ -1923,21 +1913,6 @@ xfs_alloc_get_freelist( | |||
1923 | xfs_alloc_log_agf(tp, agbp, logflags); | 1913 | xfs_alloc_log_agf(tp, agbp, logflags); |
1924 | *bnop = bno; | 1914 | *bnop = bno; |
1925 | 1915 | ||
1926 | /* | ||
1927 | * As blocks are freed, they are added to the per-ag busy list and | ||
1928 | * remain there until the freeing transaction is committed to disk. | ||
1929 | * Now that we have allocated blocks, this list must be searched to see | ||
1930 | * if a block is being reused. If one is, then the freeing transaction | ||
1931 | * must be pushed to disk before this transaction. | ||
1932 | * | ||
1933 | * We do this by setting the current transaction to a sync transaction | ||
1934 | * which guarantees that the freeing transaction is on disk before this | ||
1935 | * transaction. This is done instead of a synchronous log force here so | ||
1936 | * that we don't sit and wait with the AGF locked in the transaction | ||
1937 | * during the log force. | ||
1938 | */ | ||
1939 | if (xfs_alloc_busy_search(mp, be32_to_cpu(agf->agf_seqno), bno, 1)) | ||
1940 | xfs_trans_set_sync(tp); | ||
1941 | return 0; | 1916 | return 0; |
1942 | } | 1917 | } |
1943 | 1918 | ||
@@ -2423,6 +2398,8 @@ xfs_free_extent( | |||
2423 | } | 2398 | } |
2424 | 2399 | ||
2425 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); | 2400 | error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); |
2401 | if (!error) | ||
2402 | xfs_alloc_busy_insert(tp, args.agno, args.agbno, len); | ||
2426 | error0: | 2403 | error0: |
2427 | xfs_perag_put(args.pag); | 2404 | xfs_perag_put(args.pag); |
2428 | return error; | 2405 | return error; |