xfs: improve handling of busy extents in the low-level allocator

Currently we force the log and simply try again if we hit a busy extent,
but especially with online discard enabled it might take a while after
the log force for the busy extents to disappear, and we might have
already completed our second pass.

So instead we add a new waitqueue and a generation counter to the pag
structure so that we can do wakeups once we've removed busy extents,
and we replace the single retry with an unconditional one - after
all we hold the AGF buffer lock, so no other allocations or frees
can be racing with us in this AG.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
Christoph Hellwig
2017-02-07 14:06:57 -08:00
committed by Darrick J. Wong
parent 5e30c23d13
commit ebf5587261
5 changed files with 166 additions and 73 deletions

View File

@@ -45,6 +45,7 @@
#include "xfs_rmap_btree.h"
#include "xfs_refcount_btree.h"
#include "xfs_reflink.h"
#include "xfs_extent_busy.h"
static DEFINE_MUTEX(xfs_uuid_table_mutex);
@@ -213,6 +214,7 @@ xfs_initialize_perag(
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
if (xfs_buf_hash_init(pag))
goto out_free_pag;
init_waitqueue_head(&pag->pagb_wait);
if (radix_tree_preload(GFP_NOFS))
goto out_hash_destroy;
@@ -1078,6 +1080,12 @@ xfs_unmountfs(
*/
xfs_log_force(mp, XFS_LOG_SYNC);
/*
* Wait for all busy extents to be freed, including completion of
* any discard operation.
*/
xfs_extent_busy_wait_all(mp);
/*
* We now need to tell the world we are unmounting. This will allow
* us to detect that the filesystem is going away and we should error