diff mbox series

[v1,07/14] fs: Add aop_flags parameter to create_page_buffers()

Message ID 20220214174403.4147994-8-shr@fb.com (mailing list archive)
State New, archived
Headers show
Series Support sync buffered writes for io-uring | expand

Commit Message

Stefan Roesch Feb. 14, 2022, 5:43 p.m. UTC
This adds the aop_flags parameter to the create_page_buffers function.
When AOP_FLAGS_NOWAIT parameter is set, the atomic allocation flag is
set. The AOP_FLAGS_NOWAIT flag is set, when async buffered writes are
enabled.

Signed-off-by: Stefan Roesch <shr@fb.com>
---
 fs/buffer.c | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

Comments

Matthew Wilcox Feb. 14, 2022, 6:14 p.m. UTC | #1
On Mon, Feb 14, 2022 at 09:43:56AM -0800, Stefan Roesch wrote:
> This adds the aop_flags parameter to the create_page_buffers function.
> When AOP_FLAGS_NOWAIT parameter is set, the atomic allocation flag is
> set. The AOP_FLAGS_NOWAIT flag is set, when async buffered writes are
> enabled.

Why is this better than passing in gfp flags directly?

> Signed-off-by: Stefan Roesch <shr@fb.com>
> ---
>  fs/buffer.c | 28 +++++++++++++++++++++-------
>  1 file changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 948505480b43..5e3067173580 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -1682,13 +1682,27 @@ static inline int block_size_bits(unsigned int blocksize)
>  	return ilog2(blocksize);
>  }
>  
> -static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
> +static struct buffer_head *create_page_buffers(struct page *page,
> +					struct inode *inode,
> +					unsigned int b_state,
> +					unsigned int aop_flags)
>  {
>  	BUG_ON(!PageLocked(page));
>  
> -	if (!page_has_buffers(page))
> -		create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
> -				     b_state);
> +	if (!page_has_buffers(page)) {
> +		gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT;
> +
> +		if (aop_flags & AOP_FLAGS_NOWAIT) {
> +			gfp |= GFP_ATOMIC | __GFP_NOWARN;
> +			gfp &= ~__GFP_DIRECT_RECLAIM;
> +		} else {
> +			gfp |= __GFP_NOFAIL;
> +		}
> +
> +		__create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
> +				     b_state, gfp);
> +	}
> +
>  	return page_buffers(page);
>  }
>  
> @@ -1734,7 +1748,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
>  	int write_flags = wbc_to_write_flags(wbc);
>  
>  	head = create_page_buffers(page, inode,
> -					(1 << BH_Dirty)|(1 << BH_Uptodate));
> +					(1 << BH_Dirty)|(1 << BH_Uptodate), 0);
>  
>  	/*
>  	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers
> @@ -2000,7 +2014,7 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
>  	BUG_ON(to > PAGE_SIZE);
>  	BUG_ON(from > to);
>  
> -	head = create_page_buffers(&folio->page, inode, 0);
> +	head = create_page_buffers(&folio->page, inode, 0, flags);
>  	blocksize = head->b_size;
>  	bbits = block_size_bits(blocksize);
>  
> @@ -2280,7 +2294,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
>  	int nr, i;
>  	int fully_mapped = 1;
>  
> -	head = create_page_buffers(page, inode, 0);
> +	head = create_page_buffers(page, inode, 0, 0);
>  	blocksize = head->b_size;
>  	bbits = block_size_bits(blocksize);
>  
> -- 
> 2.30.2
>
Stefan Roesch Feb. 16, 2022, 6:30 p.m. UTC | #2
On 2/14/22 10:14 AM, Matthew Wilcox wrote:
> On Mon, Feb 14, 2022 at 09:43:56AM -0800, Stefan Roesch wrote:
>> This adds the aop_flags parameter to the create_page_buffers function.
>> When AOP_FLAGS_NOWAIT parameter is set, the atomic allocation flag is
>> set. The AOP_FLAGS_NOWAIT flag is set, when async buffered writes are
>> enabled.
> 
> Why is this better than passing in gfp flags directly?
> 

I don't think that gfp flags are a great fit here. We only want to pass in
a nowait flag and this does not map nicely to a gfp flag. 

Instead of passing in a flag parameter we can also pass in a bool parameter,
however that has its limitations as it can't be extended in the future.

>> Signed-off-by: Stefan Roesch <shr@fb.com>
>> ---
>>  fs/buffer.c | 28 +++++++++++++++++++++-------
>>  1 file changed, 21 insertions(+), 7 deletions(-)
>>
>> diff --git a/fs/buffer.c b/fs/buffer.c
>> index 948505480b43..5e3067173580 100644
>> --- a/fs/buffer.c
>> +++ b/fs/buffer.c
>> @@ -1682,13 +1682,27 @@ static inline int block_size_bits(unsigned int blocksize)
>>  	return ilog2(blocksize);
>>  }
>>  
>> -static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
>> +static struct buffer_head *create_page_buffers(struct page *page,
>> +					struct inode *inode,
>> +					unsigned int b_state,
>> +					unsigned int aop_flags)
>>  {
>>  	BUG_ON(!PageLocked(page));
>>  
>> -	if (!page_has_buffers(page))
>> -		create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
>> -				     b_state);
>> +	if (!page_has_buffers(page)) {
>> +		gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT;
>> +
>> +		if (aop_flags & AOP_FLAGS_NOWAIT) {
>> +			gfp |= GFP_ATOMIC | __GFP_NOWARN;
>> +			gfp &= ~__GFP_DIRECT_RECLAIM;
>> +		} else {
>> +			gfp |= __GFP_NOFAIL;
>> +		}
>> +
>> +		__create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
>> +				     b_state, gfp);
>> +	}
>> +
>>  	return page_buffers(page);
>>  }
>>  
>> @@ -1734,7 +1748,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
>>  	int write_flags = wbc_to_write_flags(wbc);
>>  
>>  	head = create_page_buffers(page, inode,
>> -					(1 << BH_Dirty)|(1 << BH_Uptodate));
>> +					(1 << BH_Dirty)|(1 << BH_Uptodate), 0);
>>  
>>  	/*
>>  	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers
>> @@ -2000,7 +2014,7 @@ int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
>>  	BUG_ON(to > PAGE_SIZE);
>>  	BUG_ON(from > to);
>>  
>> -	head = create_page_buffers(&folio->page, inode, 0);
>> +	head = create_page_buffers(&folio->page, inode, 0, flags);
>>  	blocksize = head->b_size;
>>  	bbits = block_size_bits(blocksize);
>>  
>> @@ -2280,7 +2294,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
>>  	int nr, i;
>>  	int fully_mapped = 1;
>>  
>> -	head = create_page_buffers(page, inode, 0);
>> +	head = create_page_buffers(page, inode, 0, 0);
>>  	blocksize = head->b_size;
>>  	bbits = block_size_bits(blocksize);
>>  
>> -- 
>> 2.30.2
>>
Matthew Wilcox Feb. 16, 2022, 6:34 p.m. UTC | #3
On Wed, Feb 16, 2022 at 10:30:33AM -0800, Stefan Roesch wrote:
> On 2/14/22 10:14 AM, Matthew Wilcox wrote:
> > On Mon, Feb 14, 2022 at 09:43:56AM -0800, Stefan Roesch wrote:
> >> This adds the aop_flags parameter to the create_page_buffers function.
> >> When AOP_FLAGS_NOWAIT parameter is set, the atomic allocation flag is
> >> set. The AOP_FLAGS_NOWAIT flag is set, when async buffered writes are
> >> enabled.
> > 
> > Why is this better than passing in gfp flags directly?
> > 
> 
> I don't think that gfp flags are a great fit here. We only want to pass in
> a nowait flag and this does not map nicely to a gfp flag. 

... what?  The only thing you do with this flag is use it to choose
some gfp flags.  Pass those gfp flags in directly.

> >> +		gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT;
> >> +
> >> +		if (aop_flags & AOP_FLAGS_NOWAIT) {
> >> +			gfp |= GFP_ATOMIC | __GFP_NOWARN;
> >> +			gfp &= ~__GFP_DIRECT_RECLAIM;
> >> +		} else {
> >> +			gfp |= __GFP_NOFAIL;
> >> +		}

The flags you've chosen here are also bonkers, but I'm not sure that
it's worth explaining to you why if you're this resistant to making
obvious corrections to your patches.
Stefan Roesch Feb. 16, 2022, 6:35 p.m. UTC | #4
On 2/16/22 10:34 AM, Matthew Wilcox wrote:
> On Wed, Feb 16, 2022 at 10:30:33AM -0800, Stefan Roesch wrote:
>> On 2/14/22 10:14 AM, Matthew Wilcox wrote:
>>> On Mon, Feb 14, 2022 at 09:43:56AM -0800, Stefan Roesch wrote:
>>>> This adds the aop_flags parameter to the create_page_buffers function.
>>>> When AOP_FLAGS_NOWAIT parameter is set, the atomic allocation flag is
>>>> set. The AOP_FLAGS_NOWAIT flag is set, when async buffered writes are
>>>> enabled.
>>>
>>> Why is this better than passing in gfp flags directly?
>>>
>>
>> I don't think that gfp flags are a great fit here. We only want to pass in
>> a nowait flag and this does not map nicely to a gfp flag. 
> 
> ... what?  The only thing you do with this flag is use it to choose
> some gfp flags.  Pass those gfp flags in directly.
> 
>>>> +		gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT;
>>>> +
>>>> +		if (aop_flags & AOP_FLAGS_NOWAIT) {
>>>> +			gfp |= GFP_ATOMIC | __GFP_NOWARN;
>>>> +			gfp &= ~__GFP_DIRECT_RECLAIM;
>>>> +		} else {
>>>> +			gfp |= __GFP_NOFAIL;
>>>> +		}
> 
> The flags you've chosen here are also bonkers, but I'm not sure that
> it's worth explaining to you why if you're this resistant to making
> obvious corrections to your patches.


Sorry my comment was for patch 1 not patch 7.
diff mbox series

Patch

diff --git a/fs/buffer.c b/fs/buffer.c
index 948505480b43..5e3067173580 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1682,13 +1682,27 @@  static inline int block_size_bits(unsigned int blocksize)
 	return ilog2(blocksize);
 }
 
-static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
+static struct buffer_head *create_page_buffers(struct page *page,
+					struct inode *inode,
+					unsigned int b_state,
+					unsigned int aop_flags)
 {
 	BUG_ON(!PageLocked(page));
 
-	if (!page_has_buffers(page))
-		create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
-				     b_state);
+	if (!page_has_buffers(page)) {
+		gfp_t gfp = GFP_NOFS | __GFP_ACCOUNT;
+
+		if (aop_flags & AOP_FLAGS_NOWAIT) {
+			gfp |= GFP_ATOMIC | __GFP_NOWARN;
+			gfp &= ~__GFP_DIRECT_RECLAIM;
+		} else {
+			gfp |= __GFP_NOFAIL;
+		}
+
+		__create_empty_buffers(page, 1 << READ_ONCE(inode->i_blkbits),
+				     b_state, gfp);
+	}
+
 	return page_buffers(page);
 }
 
@@ -1734,7 +1748,7 @@  int __block_write_full_page(struct inode *inode, struct page *page,
 	int write_flags = wbc_to_write_flags(wbc);
 
 	head = create_page_buffers(page, inode,
-					(1 << BH_Dirty)|(1 << BH_Uptodate));
+					(1 << BH_Dirty)|(1 << BH_Uptodate), 0);
 
 	/*
 	 * Be very careful.  We have no exclusion from __set_page_dirty_buffers
@@ -2000,7 +2014,7 @@  int __block_write_begin_int(struct folio *folio, loff_t pos, unsigned len,
 	BUG_ON(to > PAGE_SIZE);
 	BUG_ON(from > to);
 
-	head = create_page_buffers(&folio->page, inode, 0);
+	head = create_page_buffers(&folio->page, inode, 0, flags);
 	blocksize = head->b_size;
 	bbits = block_size_bits(blocksize);
 
@@ -2280,7 +2294,7 @@  int block_read_full_page(struct page *page, get_block_t *get_block)
 	int nr, i;
 	int fully_mapped = 1;
 
-	head = create_page_buffers(page, inode, 0);
+	head = create_page_buffers(page, inode, 0, 0);
 	blocksize = head->b_size;
 	bbits = block_size_bits(blocksize);