sync discard
Subsystems (2)
Jens Axboe
maintainercover sync discard
We recently had a pretty severe perf regression with the XFS async discard. This small series add a SYNC issue discard flag, and also limits the chain size for sync discards. Patch 2 adds support for reverting XFS back to doign sync discards.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerPATCH 1/2 block: add BLKDEV_DISCARD_SYNC flag
By default, blkdev_issue_discard() will build potentially big bio chains, even when the discard size has been limited by the user. Add a BLKDEV_DISCARD_SYNC flag, telling blkdev_issue_discard() to wait for completion of each discard.
--- block/blk-lib.c | 33 ++++++++++++++++++++++++--------- include/linux/blkdev.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-)
block/blk-lib.c +24 -9
@@ -11,13 +11,18 @@#include "blk.h" static struct bio *next_bio (struct bio *bio,unsigned int nr_pages, -gfp_t gfp) +gfp_t gfp,bool do_sync) {struct bio *new =bio_alloc (gfp, nr_pages);if (bio) { -bio_chain (bio, new); -submit_bio (bio); +if (do_sync) { +submit_bio_wait (bio); +bio_put (bio); + }else { +bio_chain (bio, new); +submit_bio (bio); + } }return new;
@@ -30,7 +35,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,struct request_queue *q =bdev_get_queue (bdev);struct bio *bio = *biop;unsigned int granularity; -unsigned int op; +unsigned int op, max_sectors;int alignment;sector_t bs_mask;
@@ -58,12 +63,17 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, granularity =max (q->limits.discard_granularity >>9 ,1U ); alignment = (bdev_discard_alignment (bdev) >>9 ) % granularity; +if (flags &BLKDEV_DISCARD_SYNC ) + max_sectors = q->limits.max_discard_sectors; +else + max_sectors =UINT_MAX >>9 ; +while (nr_sects) {unsigned int req_sects;sector_t end_sect, tmp;/* Make sure bi_size doesn't overflow */ - req_sects =min_t (sector_t, nr_sects,UINT_MAX >>9 ); + req_sects =min_t (sector_t, nr_sects, max_sectors);/** * If splitting a request, and the next starting sector would be
@@ -79,7 +89,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, req_sects = end_sect - sector; } - bio =next_bio (bio,0 , gfp_mask); + bio =next_bio (bio,0 , gfp_mask, flags &BLKDEV_DISCARD_SYNC ); bio->bi_iter.bi_sector = sector;bio_set_dev (bio, bdev);bio_set_op_attrs (bio, op,0 );
@@ -97,6 +107,11 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,cond_resched (); } +if (bio && (flags &BLKDEV_DISCARD_SYNC )) { +submit_bio_wait (bio); +bio_put (bio); + bio =NULL ; + } *biop = bio;return 0 ; }
@@ -173,7 +188,7 @@ static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector, max_write_same_sectors =UINT_MAX >>9 ;while (nr_sects) { - bio =next_bio (bio,1 , gfp_mask); + bio =next_bio (bio,1 , gfp_mask, false); bio->bi_iter.bi_sector = sector;bio_set_dev (bio, bdev); bio->bi_vcnt =1 ;
@@ -249,7 +264,7 @@ static int __blkdev_issue_write_zeroes(struct block_device *bdev,return -EOPNOTSUPP ;while (nr_sects) { - bio =next_bio (bio,0 , gfp_mask); + bio =next_bio (bio,0 , gfp_mask, false); bio->bi_iter.bi_sector = sector;bio_set_dev (bio, bdev); bio->bi_opf =REQ_OP_WRITE_ZEROES ;
@@ -301,7 +316,7 @@ static int __blkdev_issue_zero_pages(struct block_device *bdev,while (nr_sects !=0 ) { bio =next_bio (bio,__blkdev_sectors_to_bio_pages (nr_sects), - gfp_mask); + gfp_mask, false); bio->bi_iter.bi_sector = sector;bio_set_dev (bio, bdev);bio_set_op_attrs (bio,REQ_OP_WRITE ,0 );
include/linux/blkdev.h +1 -0
@@ -1396,6 +1396,7 @@ extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct page *page);#define BLKDEV_DISCARD_SECURE (1 << 0)/* issue a secure erase */ +#define BLKDEV_DISCARD_SYNC (1 << 1)extern int blkdev_issue_discard (struct block_device *bdev,sector_t sector,sector_t nr_sects,gfp_t gfp_mask,unsigned long flags);
Signature · 1 line
2.7.4
Jens Axboe
maintainerPATCH 2/2 xfs: add 'discard_sync' mount flag
In reply to Jens AxboeXFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Add a 'discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.
--- fs/xfs/xfs_log_cil.c | 18 ++++++++++++++---- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_super.c | 7 ++++++- 3 files changed, 21 insertions(+), 5 deletions(-)
fs/xfs/xfs_log_cil.c +14 -4
@@ -552,10 +552,16 @@ xlog_discard_busy_extents(struct bio *bio =NULL ;struct blk_plug plug;int error =0 ; +int discard_flags =0 ; +bool sync_discard = mp->m_flags &XFS_MOUNT_DISCARD_SYNC ;ASSERT (mp->m_flags &XFS_MOUNT_DISCARD ); -blk_start_plug (&plug); +if (!sync_discard) +blk_start_plug (&plug); +else + discard_flags =BLKDEV_DISCARD_SYNC ; +list_for_each_entry (busyp, list, list) {trace_xfs_discard_extent (mp, busyp->agno, busyp->bno, busyp->length);
@@ -563,7 +569,7 @@ xlog_discard_busy_extents( error =__blkdev_issue_discard (mp->m_ddev_targp->bt_bdev,XFS_AGB_TO_DADDR (mp, busyp->agno, busyp->bno),XFS_FSB_TO_BB (mp, busyp->length), -GFP_NOFS ,0 , &bio); +GFP_NOFS , discard_flags, &bio);if (error && error != -EOPNOTSUPP ) { xfs_info(mp, "discard failed for extent [0x%llx,%u], error %d",
@@ -574,14 +580,18 @@ xlog_discard_busy_extents( } } -if (bio) { +if (sync_discard) { +xfs_extent_busy_clear (mp, &ctx->busy_extents, false); +kmem_free (ctx); + }else if (bio) { bio->bi_private = ctx; bio->bi_end_io = xlog_discard_endio;submit_bio (bio); +blk_finish_plug (&plug); }else {xlog_discard_endio_work (&ctx->discard_endio_work); +blk_finish_plug (&plug); } -blk_finish_plug (&plug); }/*
fs/xfs/xfs_mount.h +1 -0
@@ -219,6 +219,7 @@ typedef struct xfs_mount {operations, typically for disk errors in metadata */ #define XFS_MOUNT_DISCARD (1ULL << 5)/* discard unused blocks */ +#define XFS_MOUNT_DISCARD_SYNC (1ULL << 6)/* discard unused blocks sync */ #define XFS_MOUNT_NOALIGN (1ULL << 7)/* turn off stripe alignment allocations */ #define XFS_MOUNT_ATTR2 (1ULL << 8)/* allow use of attr2 format */
fs/xfs/xfs_super.c +6 -1
@@ -83,7 +83,7 @@ enum { Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota, Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, + Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, Opt_discard_sync, }; static const match_table_t tokens = {
@@ -129,6 +129,7 @@ static const match_table_t tokens = { {Opt_pqnoenforce,"pqnoenforce"},/* project quota limit enforcement */ {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ {Opt_discard, "discard"}, /* Discard unused blocks */ + {Opt_discard_sync,"discard_sync"},/* Discard unused blocks sync */ {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ {Opt_dax, "dax"}, /* Enable direct access to bdev pages */
@@ -363,11 +364,15 @@ xfs_parseargs( mp->m_qflags |= (XFS_GQUOTA_ACCT |XFS_GQUOTA_ACTIVE ); mp->m_qflags &= ~XFS_GQUOTA_ENFD ;break ; +case Opt_discard_sync: + mp->m_flags |=XFS_MOUNT_DISCARD_SYNC ; +/* fall through and set XFS_MOUNT_DISCARD too */ case Opt_discard: mp->m_flags |=XFS_MOUNT_DISCARD ;break ;case Opt_nodiscard: mp->m_flags &= ~XFS_MOUNT_DISCARD ; + mp->m_flags &= ~XFS_MOUNT_DISCARD_SYNC ;break ;#ifdef CONFIG_FS_DAX case Opt_dax:
Signature · 1 line
2.7.4
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Do you have any more data around the workload where the old sync discard behavior actually provides an overall win over the newer behavior? Is it purely a matter of workload, or is it a workload+device thing with how discards may be handled by certain devices?
I'm ultimately not against doing this if it's useful for somebody and is otherwise buried under a mount option, but it would be nice to see if there's opportunity to improve the async mechanism before resorting to that. Is the issue here too large bio chains, too many chains at once, or just simply too many discards (regardless of chaining) at the same time?
I'm wondering if xfs could separate discard submission from log I/O completion entirely and then perhaps limit/throttle submission somehow or another (Christoph, thoughts?) via a background task. Perhaps doing something like that may even eliminate the need for some discards on busy filesystems with a lot of block free -> reallocation activity, but I'm just handwaving atm.
Brian
Quoted 113 lines
fs/xfs/xfs_log_cil.c | 18 ++++++++++++++---- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_super.c | 7 ++++++- 3 files changed, 21 insertions(+), 5 deletions(-)fs/xfs/xfs_log_cil.c +14
-4@@ -552,10 +552,16 @@ xlog_discard_busy_extents(struct bio *bio =NULL ;struct blk_plug plug;int error =0 ; +int discard_flags =0 ; +bool sync_discard = mp->m_flags &XFS_MOUNT_DISCARD_SYNC ;ASSERT (mp->m_flags &XFS_MOUNT_DISCARD ); -blk_start_plug (&plug); +if (!sync_discard) +blk_start_plug (&plug); +else + discard_flags =BLKDEV_DISCARD_SYNC ; +list_for_each_entry (busyp, list, list) {trace_xfs_discard_extent (mp, busyp->agno, busyp->bno, busyp->length);@@ -563,7 +569,7 @@ xlog_discard_busy_extents( error =__blkdev_issue_discard (mp->m_ddev_targp->bt_bdev,XFS_AGB_TO_DADDR (mp, busyp->agno, busyp->bno),XFS_FSB_TO_BB (mp, busyp->length), -GFP_NOFS ,0 , &bio); +GFP_NOFS , discard_flags, &bio);if (error && error != -EOPNOTSUPP ) { xfs_info(mp, "discard failed for extent [0x%llx,%u], error %d",@@ -574,14 +580,18 @@ xlog_discard_busy_extents( } } -if (bio) { +if (sync_discard) { +xfs_extent_busy_clear (mp, &ctx->busy_extents, false); +kmem_free (ctx); + }else if (bio) { bio->bi_private = ctx; bio->bi_end_io = xlog_discard_endio;submit_bio (bio); +blk_finish_plug (&plug); }else {xlog_discard_endio_work (&ctx->discard_endio_work); +blk_finish_plug (&plug); } -blk_finish_plug (&plug); }/* fs/xfs/xfs_mount.h +1
-0@@ -219,6 +219,7 @@ typedef struct xfs_mount {operations, typically for disk errors in metadata */ #define XFS_MOUNT_DISCARD (1ULL << 5)/* discard unused blocks */ +#define XFS_MOUNT_DISCARD_SYNC (1ULL << 6)/* discard unused blocks sync */ #define XFS_MOUNT_NOALIGN (1ULL << 7)/* turn off stripe alignment allocations */ #define XFS_MOUNT_ATTR2 (1ULL << 8)/* allow use of attr2 format */ fs/xfs/xfs_super.c +6
-1@@ -83,7 +83,7 @@ enum { Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota, Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, + Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, Opt_discard_sync, }; static const match_table_t tokens = {@@ -129,6 +129,7 @@ static const match_table_t tokens = { {Opt_pqnoenforce,"pqnoenforce"},/* project quota limit enforcement */ {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ {Opt_discard, "discard"}, /* Discard unused blocks */ + {Opt_discard_sync,"discard_sync"},/* Discard unused blocks sync */ {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ {Opt_dax, "dax"}, /* Enable direct access to bdev pages */@@ -363,11 +364,15 @@ xfs_parseargs( mp->m_qflags |= (XFS_GQUOTA_ACCT |XFS_GQUOTA_ACTIVE ); mp->m_qflags &= ~XFS_GQUOTA_ENFD ;break ; +case Opt_discard_sync: + mp->m_flags |=XFS_MOUNT_DISCARD_SYNC ; +/* fall through and set XFS_MOUNT_DISCARD too */ case Opt_discard: mp->m_flags |=XFS_MOUNT_DISCARD ;break ;case Opt_nodiscard: mp->m_flags &= ~XFS_MOUNT_DISCARD ; + mp->m_flags &= ~XFS_MOUNT_DISCARD_SYNC ;break ;#ifdef CONFIG_FS_DAX case Opt_dax:Signature · 6 lines
2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 14 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Quoted 7 lines
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
It's not a secret that most devices suck at discard. While the async discard is nifty and I bet works well for some cases, it can also cause a flood of discards on the device side which does not work well for other cases.
Quoted 4 lines
Do you have any more data around the workload where the old sync discard behavior actually provides an overall win over the newer behavior? Is it purely a matter of workload, or is it a workload+device thing with how discards may be handled by certain devices?
The worse read latencies were observed on more than one device type, making it sync again was universally a win. We've had many issues with discard, one trick that is often used is to chop up file deletion into smaller chunks. Say you want to kill 10GB of data, you do it incrementally, since 10G of discard usually doesn't behave very nicely. If you make that async, then you're back to square one.
Quoted 6 lines
I'm ultimately not against doing this if it's useful for somebody and is otherwise buried under a mount option, but it would be nice to see if there's opportunity to improve the async mechanism before resorting to that. Is the issue here too large bio chains, too many chains at once, or just simply too many discards (regardless of chaining) at the same time?
Well, ultimately you'd need better scheduling of the discards, but for most devices what really works the best is a simple "just do one at the time". The size constraint was added to further limit the impact.
Honestly, I think the only real improvement would be on the device side. Most folks want discard as an advisory hint, and it should not impact current workloads at all. In reality, many implementations are much more strict and even include substantial flash writes. For the cases where we can't just turn it off (I'd love to), we at least need to make it less intrusive.
Quoted 6 lines
I'm wondering if xfs could separate discard submission from log I/O completion entirely and then perhaps limit/throttle submission somehow or another (Christoph, thoughts?) via a background task. Perhaps doing something like that may even eliminate the need for some discards on busy filesystems with a lot of block free -> reallocation activity, but I'm just handwaving atm.
Just having the sync vs async option is the best split imho. The async could potentially be scheduled. I don't think more involved logic belongs in the fs.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 23 lines · Jens Axboe
Quoted 14 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Quoted 7 lines
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 1 line
It's not a secret that most devices suck at discard.
How can we know if a device sucks at discard?
Quoted 4 lines
While the async
discard is nifty and I bet works well for some cases, it can also cause a flood of discards on the device side which does not work well for other cases.
Shouldn't async then be only enabled if the device used supports it well? Or should a blacklist per device be more suitable? Which is more popular?
Luis
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 24 lines · Luis R. Rodriguez
Quoted 23 lines · Jens Axboe
Quoted 21 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 3 lines
Quoted 1 line
It's not a secret that most devices suck at discard.
How can we know if a device sucks at discard?
This test usually works well - does it support discard? Then it probably sucks :-)
But seriously, synthetic test case with reads/writes (the actual workload) and then mix in trims. If the performance suffers, then discards suck. Just consider this series - it was a 25% latency win.
Quoted 7 lines
Quoted 4 lines
While the async
discard is nifty and I bet works well for some cases, it can also cause a flood of discards on the device side which does not work well for other cases.Shouldn't async then be only enabled if the device used supports it well? Or should a blacklist per device be more suitable? Which is more popular?
You'd be left with nothing... My general recommendation is to not use discards at all, unless there's a proven case that it makes a write amplification difference for you - from at all, to "big enough that I'd suffer the latency consequences".
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
In reply to Luis R. RodriguezQuoted 24 lines · Luis R. Rodriguez
Quoted 23 lines · Jens Axboe
Quoted 21 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 3 lines
Quoted 1 line
It's not a secret that most devices suck at discard.
How can we know if a device sucks at discard?
I was going to ask the same thing. ;) "Meh, punt to the admin!"
I'm having deja vu but can't remember why. Seems like this has come up before and we thought it should be a block device tunable, not pushed down from the filesystem. Is that possible?
-Eric
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 29 lines · Eric Sandeen
Quoted 26 lines · Luis R. Rodriguez
Quoted 24 lines · Jens Axboe
Quoted 14 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Quoted 7 lines
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
It's not a secret that most devices suck at discard.
Quoted 7 lines
Quoted 1 line
How can we know if a device sucks at discard?
I was going to ask the same thing. ;) "Meh, punt to the admin!"
I'm having deja vu but can't remember why. Seems like this has come up before and we thought it should be a block device tunable, not pushed down from the filesystem. Is that possible?
The problem is that it'll depend on the workload as well. The device in may laptop is fine with discard for my workload, which is very light. But if you are running RocksDB on it, and doing heavy compactions and deletes, it probably would not be.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 34 lines · Jens Axboe
Quoted 33 lines · Eric Sandeen
Quoted 24 lines · Luis R. Rodriguez
Quoted 23 lines · Jens Axboe
Quoted 21 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 3 lines
Quoted 1 line
It's not a secret that most devices suck at discard.
How can we know if a device sucks at discard?
I was going to ask the same thing. ;) "Meh, punt to the admin!"
Quoted 8 lines
Quoted 3 lines
I'm having deja vu but can't remember why. Seems like this has come up before and we thought it should be a block device tunable, not pushed down from the filesystem. Is that possible?
The problem is that it'll depend on the workload as well. The device in may laptop is fine with discard for my workload, which is very light. But if you are running RocksDB on it, and doing heavy compactions and deletes, it probably would not be.
Ok, but I'm not sure how that precludes a block device tunable? You'd tune it for your workload, right?
Or is the concern that it could only be for the entire block device, and perhaps different partitions have different workloads?
Sorry, caveman filesystem guy doesn't completely understand block devices.
-Eric
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 41 lines · Eric Sandeen
Quoted 38 lines · Jens Axboe
Quoted 36 lines · Eric Sandeen
Quoted 24 lines · Luis R. Rodriguez
Quoted 23 lines · Jens Axboe
Quoted 21 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 3 lines
Quoted 1 line
It's not a secret that most devices suck at discard.
How can we know if a device sucks at discard?
I was going to ask the same thing. ;) "Meh, punt to the admin!"
I'm having deja vu but can't remember why. Seems like this has come up before and we thought it should be a block device tunable, not pushed down from the filesystem. Is that possible?
Quoted 7 lines
Quoted 4 lines
The problem is that it'll depend on the workload as well. The device in may laptop is fine with discard for my workload, which is very light. But if you are running RocksDB on it, and doing heavy compactions and deletes, it probably would not be.
Ok, but I'm not sure how that precludes a block device tunable? You'd tune it for your workload, right?
What kind of tunable are you thinking of? Right now we have one tunable, which is the max discard size. Patch #1 actually helps make this do what it should for sync discards, instead of just building a bio chain and submitting that all at once.
Quoted 4 lines
Or is the concern that it could only be for the entire block device, and perhaps different partitions have different workloads?
Sorry, caveman filesystem guy doesn't completely understand block devices.
I just don't know what you are trying to tune :-)
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 2 lines · Jens Axboe
Quoted 1 line · Eric Sandeen
On 4/30/18 2:21 PM, Jens Axboe wrote:
...
Quoted 8 lines
Quoted 2 lines
Ok, but I'm not sure how that precludes a block device tunable? You'd tune it for your workload, right?
What kind of tunable are you thinking of? Right now we have one tunable, which is the max discard size. Patch #1 actually helps make this do what it should for sync discards, instead of just building a bio chain and submitting that all at once.
Quoted 6 lines
Quoted 4 lines
Or is the concern that it could only be for the entire block device, and perhaps different partitions have different workloads?
Sorry, caveman filesystem guy doesn't completely understand block devices.
I just don't know what you are trying to tune :-)
I'm wondering if "make discards synchronous" couldn't just be a block device tunable, rather than a filesystem mount option tunable.
-Eric
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 17 lines · Eric Sandeen
Quoted 2 lines · Jens Axboe
Quoted 1 line · Eric Sandeen
On 4/30/18 2:21 PM, Jens Axboe wrote:
...
Quoted 11 lines
Quoted 2 lines
Ok, but I'm not sure how that precludes a block device tunable? You'd tune it for your workload, right?
What kind of tunable are you thinking of? Right now we have one tunable, which is the max discard size. Patch #1 actually helps make this do what it should for sync discards, instead of just building a bio chain and submitting that all at once.
Quoted 3 lines
Or is the concern that it could only be for the entire block device, and perhaps different partitions have different workloads?
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Sorry, caveman filesystem guy doesn't completely understand block devices.
I just don't know what you are trying to tune :-)
I'm wondering if "make discards synchronous" couldn't just be a block device tunable, rather than a filesystem mount option tunable.
See e-mail I just sent out. With that, you get that tunable bundled with the discard_max_bytes tunable. If you leave it at the default, which is generally very high, then you get huge discards. If you tune it down, they become basically sync. I don't think we need a separate tunable for this.
It's still per-caller, which is good enough for us. I don't want to make it more complicated until people show up with a valid use case that shows we need it strictly throttled per-device.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
In reply to Jens AxboeQuoted 23 lines · Jens Axboe
Quoted 14 lines · Brian Foster
Quoted 5 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
Quoted 7 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.Signed-off-by Jens Axboe <[email protected]>---
Quoted 7 lines
Hm, I figured the async discard stuff would have been a pretty clear win all around, but then again I'm not terribly familiar with what happens with discards beneath the fs. I do know that the previous behavior would cause fs level latencies due to holding up log I/O completion while discards completed one at a time. My understanding is that this lead to online discard being pretty much universally "not recommended" in favor of fstrim.
Quoted 5 lines
It's not a secret that most devices suck at discard. While the async discard is nifty and I bet works well for some cases, it can also cause a flood of discards on the device side which does not work well for other cases.
Heh, Ok.
Quoted 5 lines
Quoted 4 lines
Do you have any more data around the workload where the old sync discard behavior actually provides an overall win over the newer behavior? Is it purely a matter of workload, or is it a workload+device thing with how discards may be handled by certain devices?
Quoted 7 lines
The worse read latencies were observed on more than one device type, making it sync again was universally a win. We've had many issues with discard, one trick that is often used is to chop up file deletion into smaller chunks. Say you want to kill 10GB of data, you do it incrementally, since 10G of discard usually doesn't behave very nicely. If you make that async, then you're back to square one.
Makes sense, so there's not much win in chopping up huge discard ranges into smaller, async requests that cover the same overall size/range..
Quoted 11 lines
Quoted 6 lines
I'm ultimately not against doing this if it's useful for somebody and is otherwise buried under a mount option, but it would be nice to see if there's opportunity to improve the async mechanism before resorting to that. Is the issue here too large bio chains, too many chains at once, or just simply too many discards (regardless of chaining) at the same time?
Well, ultimately you'd need better scheduling of the discards, but for most devices what really works the best is a simple "just do one at the time". The size constraint was added to further limit the impact.
... but presumably there is some value in submitting some number of requests together provided they adhere to some size constraint..? Is there a typical size constraint for the average ssd, or is this value all over the place? (Is there a field somewhere in the bdev that the fs can query?)
(I guess I'll defer to Christoph's input on this, I assume he measured some kind of improvement in the previous async work..)
Quoted 14 lines
Honestly, I think the only real improvement would be on the device side. Most folks want discard as an advisory hint, and it should not impact current workloads at all. In reality, many implementations are much more strict and even include substantial flash writes. For the cases where we can't just turn it off (I'd love to), we at least need to make it less intrusive.
Quoted 6 lines
I'm wondering if xfs could separate discard submission from log I/O completion entirely and then perhaps limit/throttle submission somehow or another (Christoph, thoughts?) via a background task. Perhaps doing something like that may even eliminate the need for some discards on busy filesystems with a lot of block free -> reallocation activity, but I'm just handwaving atm.
Quoted 4 lines
Just having the sync vs async option is the best split imho. The async could potentially be scheduled. I don't think more involved logic belongs in the fs.
The more interesting part to me is whether we can safely separate discard from log I/O completion in XFS. Then we can release the log buffer locks and whatnot and let the fs proceed without waiting on any number of discards to complete. In theory, I think the background task could issue discards one at a time (or N at a time, or N blocks at a time, whatever..) without putting us back in a place where discards hold up the log and subsequently lock up the rest of the fs.
If that's possible, then the whole sync/async thing is more of an implementation detail and we have no need for separate mount options for users to try and grok.
Brian
Quoted 7 lines
Signature · 6 lines
Jens Axboe -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
In reply to Jens AxboeQuoted 4 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
FWIW, convention is it document the performance regression in the commit message, not leave the reader to guess at what it was....
Did anyone analyse the pattern of discards being issued to work out what pattern was worse for async vs sync discard? is it lots of little discards, large extents being discarded, perhaps a problem with the request request queue starving other IOs because we queue so many async discards in such a short time (which is the difference in behaviour vs the old code), or something else?
Quoted 4 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.
I'm not a fan of adding a mount option to work around bad, unpredictable performance due to a mount option we recommend you don't use because it results in bad, unpredictable performance.
Without any details of the discard pattern that results in problems I don't think we should be changing anything - adding an opaque, user-unfriendly mount option does nothing to address the underlying problem - it's just a hack to work around the symptoms being seen...
More details of the regression and the root cause analysis is needed, please.
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 8 lines · Dave Chinner
Quoted 4 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
FWIW, convention is it document the performance regression in the commit message, not leave the reader to guess at what it was....
Yeah I'll give you that, I can improve the commit message for sure.
Quoted 6 lines
Did anyone analyse the pattern of discards being issued to work out what pattern was worse for async vs sync discard? is it lots of little discards, large extents being discarded, perhaps a problem with the request request queue starving other IOs because we queue so many async discards in such a short time (which is the difference in behaviour vs the old code), or something else?
What was observed was a big discard which would previously have gone down as smaller discards now going down as either one or many discards. Looking at the blktrace data, it's the difference between
discard 1 queue
discard 1 complete
discatd 2 queue
discard 2 complete
[...]
discard n queue
discard n complete
which is now
discard 1 queue
discard 2 queue
[...]
discard n queue
[...]
discard 1 complete
discard 2 complete
[...]
discard n complete
Note that we set a max discard size of 64MB for most devices, since it's been shown to have less impact on latencies for the IO that jobs actually care about.
Quoted 8 lines
Quoted 4 lines
Add a '
discard_sync' mount flag to revert to using sync discard, issuing them one at the time and waiting for each one. This fixes a big performance regression we had moving to kernels that include the XFS async discard support.I'm not a fan of adding a mount option to work around bad, unpredictable performance due to a mount option we recommend you don't use because it results in bad, unpredictable performance.
Oh I hear you, as I wrote in other replies, I don't generally recommend discard except for cases where it's been proven to be useful in terms of write amplification improvements. If we can avoid using it, we do. It's a tradeoff, and for some situations, the right decision is to use discards.
Quoted 7 lines
Without any details of the discard pattern that results in problems I don't think we should be changing anything - adding an opaque, user-unfriendly mount option does nothing to address the underlying problem - it's just a hack to work around the symptoms being seen...
More details of the regression and the root cause analysis is needed, please.
It brings back the same behavior as we had before, which performs better for us. It's preventing users of XFS+discard from upgrading, which is sad.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 43 lines · Jens Axboe
Quoted 8 lines · Dave Chinner
Quoted 4 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
FWIW, convention is it document the performance regression in the commit message, not leave the reader to guess at what it was....
Yeah I'll give you that, I can improve the commit message for sure.
Quoted 6 lines
Did anyone analyse the pattern of discards being issued to work out what pattern was worse for async vs sync discard? is it lots of little discards, large extents being discarded, perhaps a problem with the request request queue starving other IOs because we queue so many async discards in such a short time (which is the difference in behaviour vs the old code), or something else?
What was observed was a big discard which would previously have gone down as smaller discards now going down as either one or many discards. Looking at the blktrace data, it's the difference between
discard 1 queue
discard 1 complete
discatd 2 queue
discard 2 complete
[...]
discard n queue
discard n completewhich is now
discard 1 queue
discard 2 queue
[...]
discard n queue
[...]
discard 1 complete
discard 2 complete
[...]
discard n complete
Quoted 3 lines
Note that we set a max discard size of 64MB for most devices, since it's been shown to have less impact on latencies for the IO that jobs actually care about.
IOWs, this has nothing to do with XFS behaviour, and everything to do with suboptimal scheduling control for concurrent queued discards in the block layer....
XFS can issue discard requests of up to 8GB (on 4k block size filesystems), and how they are optimised is completely up to the block layer. blkdev_issue_discard() happens to be synchronous (for historical reasons) and that does not match our asynchronous log IO model. it's always been a cause of total filesystem stall problems for XFS because we can't free log space until all the pending discards have been issued. Hence we can see global filesystems stalls of *minutes* with synchronous discards on bad devices and can cause OOM and all sorts of other nasty cascading failures.
Async discard dispatch solves this problem for XFS - discards no longer block forward journal progress, and we really don't want to go back to having that ticking timebomb in XFS. Handling concurrent discard requests in an optimal manner is not a filesystem problem - it's an IO scheduling problem.
Essentially, we've exposed yet another limitation of the block/IO layer handling of discard requests in the linux storage stack - it does not have a configurable discard queue depth.
I'd much prefer these problems get handled at the IO scheduling layer where there is visibulity of device capabilities and request queue state. i.e. we should be throttling async discards just like we can throttle read or write IO, especially given there are many devices that serialise discards at the device level (i.e. not queued device commands). This solves the problem for everyone and makes things much better for the future where hardware implementations are likely to get better and support more and more concurrency in discard operations.
IMO, the way the high level code dispatches discard requests is irrelevant here - this is a problem to do with queue depth and IO scheduling/throttling. That's why I don't think adding permanent ABI changes to filesystems to work around this problem is the right solution....
Quoted 10 lines
Quoted 6 lines
I don't think we should be changing anything - adding an opaque, user-unfriendly mount option does nothing to address the underlying problem - it's just a hack to work around the symptoms being seen...
More details of the regression and the root cause analysis is needed, please.
It brings back the same behavior as we had before, which performs better for us. It's preventing users of XFS+discard from upgrading, which is sad.
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 44 lines · Dave Chinner
Quoted 43 lines · Jens Axboe
Quoted 8 lines · Dave Chinner
Quoted 4 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
FWIW, convention is it document the performance regression in the commit message, not leave the reader to guess at what it was....
Yeah I'll give you that, I can improve the commit message for sure.
Quoted 6 lines
Did anyone analyse the pattern of discards being issued to work out what pattern was worse for async vs sync discard? is it lots of little discards, large extents being discarded, perhaps a problem with the request request queue starving other IOs because we queue so many async discards in such a short time (which is the difference in behaviour vs the old code), or something else?
What was observed was a big discard which would previously have gone down as smaller discards now going down as either one or many discards. Looking at the blktrace data, it's the difference between
discard 1 queue
discard 1 complete
discatd 2 queue
discard 2 complete
[...]
discard n queue
discard n completewhich is now
discard 1 queue
discard 2 queue
[...]
discard n queue
[...]
discard 1 complete
discard 2 complete
[...]
discard n complete
Quoted 7 lines
Quoted 3 lines
Note that we set a max discard size of 64MB for most devices, since it's been shown to have less impact on latencies for the IO that jobs actually care about.
IOWs, this has nothing to do with XFS behaviour, and everything to do with suboptimal scheduling control for concurrent queued discards in the block layer....
You could argue that, and it's fallout from XFS being the first user of async discard. Prior to that, we've never had that use case. I'm quite fine making all discards throttle to depth 1.
Quoted 31 lines
XFS can issue discard requests of up to 8GB (on 4k block size filesystems), and how they are optimised is completely up to the block layer.
blkdev_issue_discard()happens to be synchronous (for historical reasons) and that does not match our asynchronous log IO model. it's always been a cause of total filesystem stall problems for XFS because we can't free log space until all the pending discards have been issued. Hence we can see global filesystems stalls of *minutes* with synchronous discards on bad devices and can cause OOM and all sorts of other nasty cascading failures.Async discard dispatch solves this problem for XFS - discards no longer block forward journal progress, and we really don't want to go back to having that ticking timebomb in XFS. Handling concurrent discard requests in an optimal manner is not a filesystem problem - it's an IO scheduling problem.
Essentially, we've exposed yet another limitation of the block/IO layer handling of discard requests in the linux storage stack - it does not have a configurable discard queue depth.
I'd much prefer these problems get handled at the IO scheduling layer where there is visibulity of device capabilities and request queue state. i.e. we should be throttling async discards just like we can throttle read or write IO, especially given there are many devices that serialise discards at the device level (i.e. not queued device commands). This solves the problem for everyone and makes things much better for the future where hardware implementations are likely to get better and support more and more concurrency in discard operations.
Quoted 5 lines
IMO, the way the high level code dispatches discard requests is irrelevant here - this is a problem to do with queue depth and IO scheduling/throttling. That's why I don't think adding permanent ABI changes to filesystems to work around this problem is the right solution....
If you get off your high horse for a bit, this is essentially a performance regression. I can either migrate folks off of XFS, or I can come up with something that works for them. It's pretty easy to claim this is "yet another limitation of the IO stack", but it's really not fair to make crazy claims like that when it's an entirely new use case. Let's try to state things objectively and fairly.
This work should probably have been done before making XFS discard async. This isn't the first fallout we've had from that code.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
I don't think we should be changing anything - adding an opaque, user-unfriendly mount option does nothing to address the underlying problem - it's just a hack to work around the symptoms being seen...
More details of the regression and the root cause analysis is needed, please.
Quoted 7 lines
Quoted 3 lines
It brings back the same behavior as we had before, which performs better for us. It's preventing users of XFS+discard from upgrading, which is sad.
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
Signature · 1 line
Jens Axboe
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 7 lines · Jens Axboe
Quoted 3 lines · Dave Chinner
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
Totally untested, but this should do the trick. It ensures we have a QD of 1 (per caller), which should be sufficient.
If people tune down the discard size, then you'll be blocking waiting for discards on issue.
block/blk-lib.c +11 -7
@@ -11,16 +11,19 @@#include "blk.h" static struct bio *next_bio (struct bio *bio,unsigned int nr_pages, -gfp_t gfp) +gfp_t gfp) { -struct bio *new =bio_alloc (gfp, nr_pages); - +/* +* Devices suck at discard, so if we have to break up the bio +* size due to the max discard size setting, wait for the +* previous one to finish first. +*/ if (bio) { -bio_chain (bio, new); -submit_bio (bio); +submit_bio_wait (bio); +bio_put (bio); } -return new; +return bio_alloc (gfp, nr_pages); } int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
@@ -63,7 +66,8 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,sector_t end_sect, tmp;/* Make sure bi_size doesn't overflow */ - req_sects =min_t (sector_t, nr_sects,UINT_MAX >>9 ); + req_sects =min_t (sector_t, nr_sects, + q->limits.max_discard_sectors);/** * If splitting a request, and the next starting sector would be
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 29 lines · Jens Axboe
Quoted 7 lines · Jens Axboe
Quoted 3 lines · Dave Chinner
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
Totally untested, but this should do the trick. It ensures we have a QD of 1 (per caller), which should be sufficient.
If people tune down the discard size, then you'll be blocking waiting for discards on issue.
block/blk-lib.c +2
-3@@ -11,16 +11,19 @@#include "blk.h" static struct bio *next_bio (struct bio *bio,unsigned int nr_pages, -gfp_t gfp) +gfp_t gfp) { -struct bio *new =bio_alloc (gfp, nr_pages); - +/*
block/blk-lib.c line 24
Quoted 10 lines
block/blk-lib.c +6
-2+* Devices suck at discard, so if we have to break up the bio +* size due to the max discard size setting, wait for the +* previous one to finish first. +*/ if (bio) { -bio_chain (bio, new); -submit_bio (bio); +submit_bio_wait (bio); +bio_put (bio); }
This only addresses the case where __blkdev_issue_discard() breaks up a single large discard, right? It seems like a brute force solution, too, because it will do so even when the underlying device is idle and there's no need to throttle.
Shouldn't the throttling logic at least look at device congestion? i.e. if the device is not backlogged, then we should be able to issue the discard without problems.
I ask this because this only addresses throttling the "discard large extent" case when the discard limit is set low. i.e. your exact problem case. We know that XFS can issue large numbers of discontiguous async discards in a single batch - this patch does not address that case and so it will still cause starvation problems.
If we look at device congestion in determining how to throttle/back off during discard issuing, then it doesn't matter what max_discard_sectors is set to - it will throttle in all situations that cause device overloads and starvations....
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 37 lines · Dave Chinner
Quoted 36 lines · Jens Axboe
Quoted 7 lines · Jens Axboe
Quoted 3 lines · Dave Chinner
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
Totally untested, but this should do the trick. It ensures we have a QD of 1 (per caller), which should be sufficient.
If people tune down the discard size, then you'll be blocking waiting for discards on issue.
block/blk-lib.c +6
-5@@ -11,16 +11,19 @@#include "blk.h" static struct bio *next_bio (struct bio *bio,unsigned int nr_pages, -gfp_t gfp) +gfp_t gfp) { -struct bio *new =bio_alloc (gfp, nr_pages); - +/* +* Devices suck at discard, so if we have to break up the bio +* size due to the max discard size setting, wait for the +* previous one to finish first. +*/ if (bio) { -bio_chain (bio, new); -submit_bio (bio);
Quoted 9 lines
block/blk-lib.c line 24
Quoted 3 lines
block/blk-lib.c +2
-0+submit_bio_wait (bio); +bio_put (bio); }This only addresses the case where
__blkdev_issue_discard()breaks up a single large discard, right? It seems like a brute force solution, too, because it will do so even when the underlying device is idle and there's no need to throttle.
I think the above serializes the discards regardless of whether __blkdev_issue_discard() splits up a single range itself or the caller passes discontiguous ranges as part of a single chain.
That said, I agree that it seems brute force. ISTM that this wouldn't address separate callers causing the same problem (i.e., if the discard burst doesn't happen to be part of a single chain)...? Alternatively, what if the discard chain is large but covers a very small range (e.g., consider a chain of single block discards, for example)? Given your previous comments around the size of the range being the determining factor, would we really want to serialize in that case?
BTW, what happens with submit_bio_wait() if the block device is plugged? Note that xlog_discard_busy_extents() currently plugs around the discard bio chain construction.
Quoted 10 lines
Shouldn't the throttling logic at least look at device congestion? i.e. if the device is not backlogged, then we should be able to issue the discard without problems.
I ask this because this only addresses throttling the "discard large extent" case when the discard limit is set low. i.e. your exact problem case. We know that XFS can issue large numbers of discontiguous async discards in a single batch - this patch does not address that case and so it will still cause starvation problems.
Quoted 5 lines
If we look at device congestion in determining how to throttle/back off during discard issuing, then it doesn't matter what
max_discard_sectorsis set to - it will throttle in all situations that cause device overloads and starvations....
Indeed, this all seems more robust to me. TBH, even something more simple like allowing one discard chain at a time where the chain itself is size limited (and so puts the onus on the caller a bit to construct larger chains to trade off for more simple block layer throttling logic) seems reasonable, but I'm not sure if/how feasible that is (or if it really is any more simple). Just a thought.
Note that however the implementation, I think that channeling the backpressure in the form of sync submission has the potential to reintroduce the filesystem latencies that have been brought up a couple times in this thread. Unless I'm missing something, I still think there's value in trying to separate discard submission from log I/O completion in XFS.
Dave, do you have any fundamental thoughts on that? For example, I'm wondering if there's any danger in creating a sort of intermediary busy state between log I/O completion and some time later when a background wq job or something discards the pending busy extents and removes them from the pag tree. That actually might open the door for more interesting optimizations like eliminating the need for certain discards at all if the assocated blocks are reallocated (after the associated log I/O completed but before the background discard happened to occur). Actually, I'm told that explicit reuse of such blocks might be a significant win for things like VDO (dm dedup), where discards are apparently extra double ungood. Thoughts?
Brian
Quoted 10 lines
Cheers,
Dave.
Signature · 6 lines
Dave Chinner [email protected] -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
In reply to Dave ChinnerQuoted 37 lines · Dave Chinner
Quoted 36 lines · Jens Axboe
Quoted 7 lines · Jens Axboe
Quoted 3 lines · Dave Chinner
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
Totally untested, but this should do the trick. It ensures we have a QD of 1 (per caller), which should be sufficient.
If people tune down the discard size, then you'll be blocking waiting for discards on issue.
block/blk-lib.c +6
-5@@ -11,16 +11,19 @@#include "blk.h" static struct bio *next_bio (struct bio *bio,unsigned int nr_pages, -gfp_t gfp) +gfp_t gfp) { -struct bio *new =bio_alloc (gfp, nr_pages); - +/* +* Devices suck at discard, so if we have to break up the bio +* size due to the max discard size setting, wait for the +* previous one to finish first. +*/ if (bio) { -bio_chain (bio, new); -submit_bio (bio);
Quoted 8 lines
block/blk-lib.c line 24
Quoted 3 lines
block/blk-lib.c +2
-0+submit_bio_wait (bio); +bio_put (bio); }This only addresses the case where
__blkdev_issue_discard()breaks up a single large discard, right? It seems like a brute force solution, too, because it will do so even when the underlying device is idle and there's no need to throttle.
Right, the above would only break up a single discard, that's the per-caller part.
Quoted 10 lines
Shouldn't the throttling logic at least look at device congestion? i.e. if the device is not backlogged, then we should be able to issue the discard without problems.
I ask this because this only addresses throttling the "discard large extent" case when the discard limit is set low. i.e. your exact problem case. We know that XFS can issue large numbers of discontiguous async discards in a single batch - this patch does not address that case and so it will still cause starvation problems.
Quoted 4 lines
If we look at device congestion in determining how to throttle/back off during discard issuing, then it doesn't matter what
max_discard_sectorsis set to - it will throttle in all situations that cause device overloads and starvations....
How about the below? It integrates it with the writeback throttling, treating it like background writes. Totally untested. The benefit of this is that it ties into that whole framework, and it's per-device managed.
The blk-lib change is a separate patch, ensuring we break up discards according to the user size. Will get broken up.
block/blk-lib.c +4 -3
@@ -62,10 +62,11 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,unsigned int req_sects;sector_t end_sect, tmp; -/* Make sure bi_size doesn't overflow */ - req_sects =min_t (sector_t, nr_sects,UINT_MAX >>9 ); +/* Issue in chunks of the user defined max discard setting */ + req_sects =min_t (sector_t, nr_sects, + q->limits.max_discard_sectors); -/** +/* * If splitting a request, and the next starting sector would be * misaligned, stop the discard at the previous aligned sector. */
block/blk-stat.h +3 -3
@@ -10,11 +10,11 @@/* * from upper: -* 3 bits: reserved for other usage +* 4 bits: reserved for other usage * 12 bits: size -* 49 bits: time +* 48 bits: time */ -#define BLK_STAT_RES_BITS 3 +#define BLK_STAT_RES_BITS 4#define BLK_STAT_SIZE_BITS 12#define BLK_STAT_RES_SHIFT (64 - BLK_STAT_RES_BITS)#define BLK_STAT_SIZE_SHIFT (BLK_STAT_RES_SHIFT - BLK_STAT_SIZE_BITS)
block/blk-wbt.c +34 -18
104 lines not on this page · raw message
block/blk-wbt.h +7 -2
@@ -14,12 +14,17 @@ enum wbt_flags {WBT_TRACKED =1 ,/* write, tracked for throttling */ WBT_READ =2 ,/* read */ WBT_KSWAPD =4 ,/* write, from kswapd */ +WBT_TRIM =8 , - WBT_NR_BITS = 3, /* number of bits */ + WBT_NR_BITS = 4, /* number of bits */ };enum { -WBT_NUM_RWQ =2 , +WBT_REQ_BG =0 , +WBT_REQ_KSWAPD , +WBT_REQ_TRIM , + +WBT_NUM_RWQ , };/*
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Jens,
block/blk-wbt.h enum wbt_flags { · line 17
Quoted 9 lines
block/blk-wbt.h +1
-0@@ -14,12 +14,17 @@ enum wbt_flags {WBT_TRACKED =1 ,/* write, tracked for throttling */ WBT_READ =2 ,/* read */ WBT_KSWAPD =4 ,/* write, from kswapd */ + WBT_TRIM = 8,
The term TRIM does not apply to NVMe, nor SCSI. Please call it WBT_DISCARD.
Signature · 1 line
Martin K. Petersen Oracle Linux Engineering
Jens Axboe
maintainerRe: [PATCH 2/2] xfs: add 'discard_sync' mount flag
Quoted 15 lines · Martin K. Petersen
Jens,
block/blk-wbt.h enum wbt_flags { · line 17
Quoted 9 lines
block/blk-wbt.h +1
-0@@ -14,12 +14,17 @@ enum wbt_flags {WBT_TRACKED =1 ,/* write, tracked for throttling */ WBT_READ =2 ,/* read */ WBT_KSWAPD =4 ,/* write, from kswapd */ + WBT_TRIM = 8,The term TRIM does not apply to NVMe, nor SCSI. Please call it
WBT_DISCARD.
Sure, I can do that.
Signature · 1 line
Jens Axboe
Re: [PATCH 2/2] xfs: add 'discard_sync' mount flag
In reply to Jens AxboeQuoted 45 lines · Jens Axboe
Quoted 44 lines · Dave Chinner
Quoted 43 lines · Jens Axboe
Quoted 8 lines · Dave Chinner
Quoted 4 lines · Jens Axboe
XFS recently added support for async discards. While this can be a win for some workloads and devices, there are also cases where async bursty discard will severly harm the latencies of reads and writes.
FWIW, convention is it document the performance regression in the commit message, not leave the reader to guess at what it was....
Yeah I'll give you that, I can improve the commit message for sure.
Quoted 6 lines
Did anyone analyse the pattern of discards being issued to work out what pattern was worse for async vs sync discard? is it lots of little discards, large extents being discarded, perhaps a problem with the request request queue starving other IOs because we queue so many async discards in such a short time (which is the difference in behaviour vs the old code), or something else?
What was observed was a big discard which would previously have gone down as smaller discards now going down as either one or many discards. Looking at the blktrace data, it's the difference between
discard 1 queue
discard 1 complete
discatd 2 queue
discard 2 complete
[...]
discard n queue
discard n completewhich is now
discard 1 queue
discard 2 queue
[...]
discard n queue
[...]
discard 1 complete
discard 2 complete
[...]
discard n complete
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Note that we set a max discard size of 64MB for most devices, since it's been shown to have less impact on latencies for the IO that jobs actually care about.
Ok, so as I see it the problem here is that discards are not some instantaneous command, but instead have some cost that is (probably) less than (say) a full write of the same quantity of zeroes. Previously we'd feed the block layer one discard io at a time, but now we batch them up and send multiple large discard requests at the same time. The discards then tie up the device for long periods of time. We'd get the same result if we sent gigabytes of write commands simultaneously too, right?
Wouldn't the same problem would happen if say 200 threads were each issuing discards one by one because there's just too many bytes in flight at a time?
So what I'm asking here is, can we throttle discard IOs so that no single issuer can monopolize a device? As a stupid example, if program A is sending 200MB of reads, program B is sending 200MB of writes, and xfs is sending 200MB of discards at the same time, can we throttle all three so that they each get roughly a third of the queue at a time?
This way XFS can still send huge batches of discard IOs asynchronously, and it's fine enough if some of those have to wait longer in order to avoid starving other things.
(Yes, I imagine you could serialize discards and run them one at a time, but that seems a little suboptimal...)
Quoted 70 lines
Quoted 4 lines
IOWs, this has nothing to do with XFS behaviour, and everything to do with suboptimal scheduling control for concurrent queued discards in the block layer....
You could argue that, and it's fallout from XFS being the first user of async discard. Prior to that, we've never had that use case. I'm quite fine making all discards throttle to depth 1.
Quoted 31 lines
XFS can issue discard requests of up to 8GB (on 4k block size filesystems), and how they are optimised is completely up to the block layer.
blkdev_issue_discard()happens to be synchronous (for historical reasons) and that does not match our asynchronous log IO model. it's always been a cause of total filesystem stall problems for XFS because we can't free log space until all the pending discards have been issued. Hence we can see global filesystems stalls of *minutes* with synchronous discards on bad devices and can cause OOM and all sorts of other nasty cascading failures.Async discard dispatch solves this problem for XFS - discards no longer block forward journal progress, and we really don't want to go back to having that ticking timebomb in XFS. Handling concurrent discard requests in an optimal manner is not a filesystem problem - it's an IO scheduling problem.
Essentially, we've exposed yet another limitation of the block/IO layer handling of discard requests in the linux storage stack - it does not have a configurable discard queue depth.
I'd much prefer these problems get handled at the IO scheduling layer where there is visibulity of device capabilities and request queue state. i.e. we should be throttling async discards just like we can throttle read or write IO, especially given there are many devices that serialise discards at the device level (i.e. not queued device commands). This solves the problem for everyone and makes things much better for the future where hardware implementations are likely to get better and support more and more concurrency in discard operations.
Quoted 5 lines
IMO, the way the high level code dispatches discard requests is irrelevant here - this is a problem to do with queue depth and IO scheduling/throttling. That's why I don't think adding permanent ABI changes to filesystems to work around this problem is the right solution....
If you get off your high horse for a bit, this is essentially a performance regression. I can either migrate folks off of XFS, or I can come up with something that works for them. It's pretty easy to claim this is "yet another limitation of the IO stack", but it's really not fair to make crazy claims like that when it's an entirely new use case. Let's try to state things objectively and fairly.
This work should probably have been done before making XFS discard async. This isn't the first fallout we've had from that code.
Quoted 11 lines
Quoted 10 lines
Quoted 6 lines
I don't think we should be changing anything - adding an opaque, user-unfriendly mount option does nothing to address the underlying problem - it's just a hack to work around the symptoms being seen...
More details of the regression and the root cause analysis is needed, please.
It brings back the same behavior as we had before, which performs better for us. It's preventing users of XFS+discard from upgrading, which is sad.
Quoted 6 lines
Quoted 3 lines
Yes, it does, but so would having the block layer to throttle device discard requests in flight to a queue depth of 1. And then we don't have to change XFS at all.
I'm perfectly fine with making that change by default, and much easier for me since I don't have to patch file systems.
...and I prefer not to add mount options, fwiw.
--D
Quoted 7 lines
Signature · 6 lines
Jens Axboe -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 4 lines · Jens Axboe
We recently had a pretty severe perf regression with the XFS async discard. This small series add a SYNC issue discard flag, and also limits the chain size for sync discards. Patch 2 adds support for reverting XFS back to doign sync discards.
Please explain the hardware and workload that you see this with. Also given that it is a hardware limitation a quirk limiting the size of discard requests and/or number of outstanding discards would be more useful than falling back to a broken mode of issueing block commands.
Jens Axboe
maintainerQuoted 11 lines · Christoph Hellwig
Quoted 4 lines · Jens Axboe
We recently had a pretty severe perf regression with the XFS async discard. This small series add a SYNC issue discard flag, and also limits the chain size for sync discards. Patch 2 adds support for reverting XFS back to doign sync discards.
Please explain the hardware and workload that you see this with. Also given that it is a hardware limitation a quirk limiting the size of discard requests and/or number of outstanding discards would be more useful than falling back to a broken mode of issueing block commands.
Honestly, from what I've seen in production, I can whitelist one device and that one is no longer being produced. The rest is crap in terms of latency impacting trim. A quirk or whitelist/blacklist isn't going to be of any help.
Signature · 1 line
Jens Axboe