diff mbox series

[RFC,v3,07/14] mm: add bdi_set_max_bytes() function.

Message ID 20221024190603.3987969-8-shr@devkernel.io (mailing list archive)
State New, archived
Headers show
Series mm/block: add bdi sysfs knobs | expand

Commit Message

Stefan Roesch Oct. 24, 2022, 7:05 p.m. UTC
This introduces the bdi_set_max_bytes() function. The max_bytes function
does not store the max_bytes value. Instead it converts the max_bytes
value into the corresponding ratio value.

Signed-off-by: Stefan Roesch <shr@devkernel.io>
---
 include/linux/backing-dev.h |  1 +
 mm/page-writeback.c         | 38 +++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

Comments

Andrew Morton Nov. 16, 2022, 9:29 p.m. UTC | #1
On Mon, 24 Oct 2022 12:05:56 -0700 Stefan Roesch <shr@devkernel.io> wrote:

> This introduces the bdi_set_max_bytes() function. The max_bytes function
> does not store the max_bytes value. Instead it converts the max_bytes
> value into the corresponding ratio value.
> 
> ...
>
> +EXPORT_SYMBOL_GPL(bdi_set_max_bytes);

Is this needed?
Andrew Morton Nov. 16, 2022, 9:29 p.m. UTC | #2
On Mon, 24 Oct 2022 12:05:56 -0700 Stefan Roesch <shr@devkernel.io> wrote:

> This introduces the bdi_set_max_bytes() function. The max_bytes function
> does not store the max_bytes value. Instead it converts the max_bytes
> value into the corresponding ratio value.
> 
> ...
>
> --- a/include/linux/backing-dev.h
> +++ b/include/linux/backing-dev.h
> @@ -108,6 +108,7 @@ static inline unsigned long wb_stat_error(void)
>  unsigned long long bdi_get_max_bytes(struct backing_dev_info *bdi);
>  int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
>  int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
> +int bdi_set_max_bytes(struct backing_dev_info *bdi, unsigned long long max_bytes);
>  int bdi_set_strict_limit(struct backing_dev_info *bdi, unsigned int strict_limit);
>  
>  /*
> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> index 8b8936603783..21d7c1880ea8 100644
> --- a/mm/page-writeback.c
> +++ b/mm/page-writeback.c
> @@ -13,6 +13,7 @@
>   */
>  
>  #include <linux/kernel.h>
> +#include <linux/math64.h>
>  #include <linux/export.h>
>  #include <linux/spinlock.h>
>  #include <linux/fs.h>
> @@ -650,6 +651,28 @@ void wb_domain_exit(struct wb_domain *dom)
>   */
>  static unsigned int bdi_min_ratio;
>  
> +static int bdi_check_pages_limit(unsigned long pages)
> +{
> +	unsigned long max_dirty_pages = global_dirtyable_memory();
> +
> +	if (pages > max_dirty_pages / 2)
> +		return -EINVAL;
> +
> +	return 0;
> +}

Some code comments are needed here.  Explain what it does and why it
does it.  The "/ 2" seems utterly arbitray - explain why this value was
chosen?  Why is it better than "/ 3"?



> +static unsigned long bdi_ratio_from_pages(unsigned long pages)
> +{
> +	unsigned long background_thresh;
> +	unsigned long dirty_thresh;
> +	unsigned long ratio;
> +
> +	global_dirty_limits(&background_thresh, &dirty_thresh);
> +	ratio = div64_u64(pages * 100ULL * BDI_RATIO_SCALE, dirty_thresh);

`unsigned long' is 32-bit on 32-bit machines, which makes this code a
bit odd.  Should everything here be u64?
Stefan Roesch Nov. 19, 2022, 12:14 a.m. UTC | #3
Andrew Morton <akpm@linux-foundation.org> writes:

> On Mon, 24 Oct 2022 12:05:56 -0700 Stefan Roesch <shr@devkernel.io> wrote:
>
>> This introduces the bdi_set_max_bytes() function. The max_bytes function
>> does not store the max_bytes value. Instead it converts the max_bytes
>> value into the corresponding ratio value.
>>
>> ...
>>
>> +EXPORT_SYMBOL_GPL(bdi_set_max_bytes);
>
> Is this needed?

I removed the export in the next version.
Stefan Roesch Nov. 19, 2022, 12:16 a.m. UTC | #4
Andrew Morton <akpm@linux-foundation.org> writes:

> On Mon, 24 Oct 2022 12:05:56 -0700 Stefan Roesch <shr@devkernel.io> wrote:
>
>> This introduces the bdi_set_max_bytes() function. The max_bytes function
>> does not store the max_bytes value. Instead it converts the max_bytes
>> value into the corresponding ratio value.
>>
>> ...
>>
>> --- a/include/linux/backing-dev.h
>> +++ b/include/linux/backing-dev.h
>> @@ -108,6 +108,7 @@ static inline unsigned long wb_stat_error(void)
>>  unsigned long long bdi_get_max_bytes(struct backing_dev_info *bdi);
>>  int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
>>  int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
>> +int bdi_set_max_bytes(struct backing_dev_info *bdi, unsigned long long max_bytes);
>>  int bdi_set_strict_limit(struct backing_dev_info *bdi, unsigned int strict_limit);
>>
>>  /*
>> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
>> index 8b8936603783..21d7c1880ea8 100644
>> --- a/mm/page-writeback.c
>> +++ b/mm/page-writeback.c
>> @@ -13,6 +13,7 @@
>>   */
>>
>>  #include <linux/kernel.h>
>> +#include <linux/math64.h>
>>  #include <linux/export.h>
>>  #include <linux/spinlock.h>
>>  #include <linux/fs.h>
>> @@ -650,6 +651,28 @@ void wb_domain_exit(struct wb_domain *dom)
>>   */
>>  static unsigned int bdi_min_ratio;
>>
>> +static int bdi_check_pages_limit(unsigned long pages)
>> +{
>> +	unsigned long max_dirty_pages = global_dirtyable_memory();
>> +
>> +	if (pages > max_dirty_pages / 2)
>> +		return -EINVAL;
>> +
>> +	return 0;
>> +}
>
> Some code comments are needed here.  Explain what it does and why it
> does it.  The "/ 2" seems utterly arbitray - explain why this value was
> chosen?  Why is it better than "/ 3"?
>
>

I changed the check to
   (pages > max_dirty_pages)

>
>> +static unsigned long bdi_ratio_from_pages(unsigned long pages)
>> +{
>> +	unsigned long background_thresh;
>> +	unsigned long dirty_thresh;
>> +	unsigned long ratio;
>> +
>> +	global_dirty_limits(&background_thresh, &dirty_thresh);
>> +	ratio = div64_u64(pages * 100ULL * BDI_RATIO_SCALE, dirty_thresh);
>
> `unsigned long' is 32-bit on 32-bit machines, which makes this code a
> bit odd.  Should everything here be u64?

The function global_dirty_limits() uses unsigned long pointers for its
arguments. unsigned long looks like a better fit. Any thoughts?
diff mbox series

Patch

diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index cb0e66564d4d..5eb1ae3410b2 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -108,6 +108,7 @@  static inline unsigned long wb_stat_error(void)
 unsigned long long bdi_get_max_bytes(struct backing_dev_info *bdi);
 int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio);
 int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
+int bdi_set_max_bytes(struct backing_dev_info *bdi, unsigned long long max_bytes);
 int bdi_set_strict_limit(struct backing_dev_info *bdi, unsigned int strict_limit);
 
 /*
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 8b8936603783..21d7c1880ea8 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -13,6 +13,7 @@ 
  */
 
 #include <linux/kernel.h>
+#include <linux/math64.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
 #include <linux/fs.h>
@@ -650,6 +651,28 @@  void wb_domain_exit(struct wb_domain *dom)
  */
 static unsigned int bdi_min_ratio;
 
+static int bdi_check_pages_limit(unsigned long pages)
+{
+	unsigned long max_dirty_pages = global_dirtyable_memory();
+
+	if (pages > max_dirty_pages / 2)
+		return -EINVAL;
+
+	return 0;
+}
+
+static unsigned long bdi_ratio_from_pages(unsigned long pages)
+{
+	unsigned long background_thresh;
+	unsigned long dirty_thresh;
+	unsigned long ratio;
+
+	global_dirty_limits(&background_thresh, &dirty_thresh);
+	ratio = div64_u64(pages * 100ULL * BDI_RATIO_SCALE, dirty_thresh);
+
+	return ratio;
+}
+
 static unsigned long long bdi_get_bytes(unsigned int ratio)
 {
 	unsigned long background_thresh;
@@ -723,6 +746,21 @@  unsigned long long bdi_get_max_bytes(struct backing_dev_info *bdi)
 }
 EXPORT_SYMBOL_GPL(bdi_get_max_bytes);
 
+int bdi_set_max_bytes(struct backing_dev_info *bdi, unsigned long long max_bytes)
+{
+	int ret;
+	unsigned long pages = max_bytes >> PAGE_SHIFT;
+	unsigned long max_ratio;
+
+	ret = bdi_check_pages_limit(pages);
+	if (ret)
+		return ret;
+
+	max_ratio = bdi_ratio_from_pages(pages);
+	return __bdi_set_max_ratio(bdi, max_ratio);
+}
+EXPORT_SYMBOL_GPL(bdi_set_max_bytes);
+
 int bdi_set_strict_limit(struct backing_dev_info *bdi, unsigned int strict_limit)
 {
 	if (strict_limit > 1)