[12/19] btrfs: limit max discard size for async discard
diff mbox series

Message ID 7eed2e0ebdc4cc4a7e31c6fa7a180f10158fba0f.1570479299.git.dennis@kernel.org
State New
Headers show
Series
  • btrfs: async discard support
Related show

Commit Message

Dennis Zhou Oct. 7, 2019, 8:17 p.m. UTC
Throttle the maximum size of a discard so that we can provide an upper
bound for the rate of async discard. While the block layer is able to
split discards into the appropriate sized discards, we want to be able
to account more accurately the rate at which we are consuming ncq slots
as well as limit the upper bound of work for a discard.

Signed-off-by: Dennis Zhou <dennis@kernel.org>
---
 fs/btrfs/discard.h          |  4 ++++
 fs/btrfs/free-space-cache.c | 47 +++++++++++++++++++++++++++----------
 2 files changed, 39 insertions(+), 12 deletions(-)

Comments

Josef Bacik Oct. 10, 2019, 4:16 p.m. UTC | #1
On Mon, Oct 07, 2019 at 04:17:43PM -0400, Dennis Zhou wrote:
> Throttle the maximum size of a discard so that we can provide an upper
> bound for the rate of async discard. While the block layer is able to
> split discards into the appropriate sized discards, we want to be able
> to account more accurately the rate at which we are consuming ncq slots
> as well as limit the upper bound of work for a discard.
> 
> Signed-off-by: Dennis Zhou <dennis@kernel.org>
> ---
>  fs/btrfs/discard.h          |  4 ++++
>  fs/btrfs/free-space-cache.c | 47 +++++++++++++++++++++++++++----------
>  2 files changed, 39 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/btrfs/discard.h b/fs/btrfs/discard.h
> index acaf56f63b1c..898dd92dbf8f 100644
> --- a/fs/btrfs/discard.h
> +++ b/fs/btrfs/discard.h
> @@ -8,6 +8,7 @@
>  
>  #include <linux/kernel.h>
>  #include <linux/jiffies.h>
> +#include <linux/sizes.h>
>  #include <linux/time.h>
>  #include <linux/workqueue.h>
>  
> @@ -15,6 +16,9 @@
>  #include "block-group.h"
>  #include "free-space-cache.h"
>  
> +/* discard size limits */
> +#define BTRFS_DISCARD_MAX_SIZE		(SZ_64M)
> +

Let's make this configurable via sysfs as well.  I assume at some point in the
far, far future SSD's will stop being shitty and it would be nice to be able to
easily adjust and test.  Also this only applies to async, so
BTRFS_ASYNC_DISCARD_MAX_SIZE.  You can add a follow up patch for the sysfs
stuff, just adjust the name and you can add

Reviewed-by: Josef Bacik <josef@toxicpanda.com>

Thanks,

Josef
Dennis Zhou Oct. 14, 2019, 7:57 p.m. UTC | #2
On Thu, Oct 10, 2019 at 12:16:38PM -0400, Josef Bacik wrote:
> On Mon, Oct 07, 2019 at 04:17:43PM -0400, Dennis Zhou wrote:
> > Throttle the maximum size of a discard so that we can provide an upper
> > bound for the rate of async discard. While the block layer is able to
> > split discards into the appropriate sized discards, we want to be able
> > to account more accurately the rate at which we are consuming ncq slots
> > as well as limit the upper bound of work for a discard.
> > 
> > Signed-off-by: Dennis Zhou <dennis@kernel.org>
> > ---
> >  fs/btrfs/discard.h          |  4 ++++
> >  fs/btrfs/free-space-cache.c | 47 +++++++++++++++++++++++++++----------
> >  2 files changed, 39 insertions(+), 12 deletions(-)
> > 
> > diff --git a/fs/btrfs/discard.h b/fs/btrfs/discard.h
> > index acaf56f63b1c..898dd92dbf8f 100644
> > --- a/fs/btrfs/discard.h
> > +++ b/fs/btrfs/discard.h
> > @@ -8,6 +8,7 @@
> >  
> >  #include <linux/kernel.h>
> >  #include <linux/jiffies.h>
> > +#include <linux/sizes.h>
> >  #include <linux/time.h>
> >  #include <linux/workqueue.h>
> >  
> > @@ -15,6 +16,9 @@
> >  #include "block-group.h"
> >  #include "free-space-cache.h"
> >  
> > +/* discard size limits */
> > +#define BTRFS_DISCARD_MAX_SIZE		(SZ_64M)
> > +
> 
> Let's make this configurable via sysfs as well.  I assume at some point in the
> far, far future SSD's will stop being shitty and it would be nice to be able to
> easily adjust and test.  Also this only applies to async, so
> BTRFS_ASYNC_DISCARD_MAX_SIZE.  You can add a follow up patch for the sysfs
> stuff, just adjust the name and you can add

Yeah that sounds good. I exposed it as max_discard_bytes in another
patch and renamed all the variables to BTRFS_ASYNC_DISCARD_* around
discard size limits.

> Reviewed-by: Josef Bacik <josef@toxicpanda.com>
> 

Thanks,
Dennis

Patch
diff mbox series

diff --git a/fs/btrfs/discard.h b/fs/btrfs/discard.h
index acaf56f63b1c..898dd92dbf8f 100644
--- a/fs/btrfs/discard.h
+++ b/fs/btrfs/discard.h
@@ -8,6 +8,7 @@ 
 
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
+#include <linux/sizes.h>
 #include <linux/time.h>
 #include <linux/workqueue.h>
 
@@ -15,6 +16,9 @@ 
 #include "block-group.h"
 #include "free-space-cache.h"
 
+/* discard size limits */
+#define BTRFS_DISCARD_MAX_SIZE		(SZ_64M)
+
 /* discard flags */
 #define BTRFS_DISCARD_RESET_CURSOR	(1UL << 0)
 #define BTRFS_DISCARD_BITMAPS           (1UL << 1)
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 54f3c8325858..ce33803a45b2 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -3399,19 +3399,39 @@  static int trim_no_bitmap(struct btrfs_block_group_cache *block_group,
 		if (entry->offset >= end)
 			goto out_unlock;
 
-		extent_start = entry->offset;
-		extent_bytes = entry->bytes;
-		extent_flags = entry->flags;
-		start = max(start, extent_start);
-		bytes = min(extent_start + extent_bytes, end) - start;
-		if (bytes < minlen) {
-			spin_unlock(&ctl->tree_lock);
-			mutex_unlock(&ctl->cache_writeout_mutex);
-			goto next;
-		}
+		if (async) {
+			start = extent_start = entry->offset;
+			bytes = extent_bytes = entry->bytes;
+			extent_flags = entry->flags;
+			if (bytes < minlen) {
+				spin_unlock(&ctl->tree_lock);
+				mutex_unlock(&ctl->cache_writeout_mutex);
+				goto next;
+			}
+			unlink_free_space(ctl, entry);
+			if (bytes > BTRFS_DISCARD_MAX_SIZE) {
+				bytes = extent_bytes = BTRFS_DISCARD_MAX_SIZE;
+				entry->offset += BTRFS_DISCARD_MAX_SIZE;
+				entry->bytes -= BTRFS_DISCARD_MAX_SIZE;
+				link_free_space(ctl, entry);
+			} else {
+				kmem_cache_free(btrfs_free_space_cachep, entry);
+			}
+		} else {
+			extent_start = entry->offset;
+			extent_bytes = entry->bytes;
+			extent_flags = entry->flags;
+			start = max(start, extent_start);
+			bytes = min(extent_start + extent_bytes, end) - start;
+			if (bytes < minlen) {
+				spin_unlock(&ctl->tree_lock);
+				mutex_unlock(&ctl->cache_writeout_mutex);
+				goto next;
+			}
 
-		unlink_free_space(ctl, entry);
-		kmem_cache_free(btrfs_free_space_cachep, entry);
+			unlink_free_space(ctl, entry);
+			kmem_cache_free(btrfs_free_space_cachep, entry);
+		}
 
 		spin_unlock(&ctl->tree_lock);
 		trim_entry.start = extent_start;
@@ -3567,6 +3587,9 @@  static int trim_bitmaps(struct btrfs_block_group_cache *block_group,
 			goto next;
 		}
 
+		if (async && bytes > BTRFS_DISCARD_MAX_SIZE)
+			bytes = BTRFS_DISCARD_MAX_SIZE;
+
 		bitmap_clear_bits(ctl, entry, start, bytes);
 		if (entry->bytes == 0)
 			free_bitmap(ctl, entry);