All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vivek Goyal <vgoyal@redhat.com>
To: Miklos Szeredi <mszeredi@redhat.com>
Cc: linux-fsdevel@vger.kernel.org, Pengfei Xu <pengfei.xu@intel.com>,
	syzbot+462da39f0667b357c4b6@syzkaller.appspotmail.com
Subject: Re: [PATCH] fuse: lock inode unconditionally in fuse_fallocate()
Date: Mon, 28 Nov 2022 15:09:43 -0500	[thread overview]
Message-ID: <Y4UVhzMHYbigU72b@redhat.com> (raw)
In-Reply-To: <20221123104336.1030702-1-mszeredi@redhat.com>

On Wed, Nov 23, 2022 at 11:43:36AM +0100, Miklos Szeredi wrote:
> file_modified() must be called with inode lock held.  fuse_fallocate()
> didn't lock the inode in case of just FALLOC_KEEP_SIZE flags value, which
> resulted in a kernel Warning in notify_change().
> 
> Lock the inode unconditionally, like all other fallocate implementations
> do.
> 
> Reported-by: Pengfei Xu <pengfei.xu@intel.com>
> Reported-and-tested-by: syzbot+462da39f0667b357c4b6@syzkaller.appspotmail.com
> Fixes: 4a6f278d4827 ("fuse: add file_modified() to fallocate")
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
> ---
>  fs/fuse/file.c | 37 ++++++++++++++++---------------------
>  1 file changed, 16 insertions(+), 21 deletions(-)
> 
> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
> index 71bfb663aac5..89f4741728ba 100644
> --- a/fs/fuse/file.c
> +++ b/fs/fuse/file.c
> @@ -2963,11 +2963,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
>  		.mode = mode
>  	};
>  	int err;
> -	bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
> -			   (mode & (FALLOC_FL_PUNCH_HOLE |
> -				    FALLOC_FL_ZERO_RANGE));
> -
> -	bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
> +	bool block_faults = FUSE_IS_DAX(inode) &&
> +		(!(mode & FALLOC_FL_KEEP_SIZE) ||
> +		 (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)));

Hi Miklos,

I think that we probably don't need above tests for "block_faults".
Initially, ideas was that I wanted to synchronize truncate/punch_hole
with fault handler path. Fuse did not seem to do it, so I decided to
add it only for fuse DAX code to begin with. Details are in following
commit.

commit 6ae330cad6ef22ab8347ea9e0707dc56a7c7363f
Author: Vivek Goyal <vgoyal@redhat.com>
Date:   Wed Aug 19 18:19:54 2020 -0400

    virtiofs: serialize truncate/punch_hole and dax fault path

I wanted to take following two locks for it to work.
   inode_lock(inode)
     down_write(&fi->i_mmap_sem);

And that's why following condition.

bool block_faults = FUSE_IS_DAX(inode) && lock_inode;

Given that we will now always take inode lock, we could just do.

bool block_faults = FUSE_IS_DAX(inode); instead. Not sure is there really
a benefit in going through different "mode" flags and make this condition
even narrower.

I see that now fi->i_mmap_sem has been replaced by
filemap_invalidate_lock(inode->i_mapping).

At some point of time we should review fuse fault code and see if that
code need to serialize with truncate/punch_hole path as well. If answer
is yes, then we could get rid of this "block_faults" altogether and
always take inode->i_mapping lock in truncate path.

IOW, I think we should be able to simplify above to just for now.

bool block_faults = FUSE_IS_DAX(inode);
 
Thanks
Vivek

>  
>  	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE |
>  		     FALLOC_FL_ZERO_RANGE))
> @@ -2976,22 +2974,20 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
>  	if (fm->fc->no_fallocate)
>  		return -EOPNOTSUPP;
>  
> -	if (lock_inode) {
> -		inode_lock(inode);
> -		if (block_faults) {
> -			filemap_invalidate_lock(inode->i_mapping);
> -			err = fuse_dax_break_layouts(inode, 0, 0);
> -			if (err)
> -				goto out;
> -		}
> +	inode_lock(inode);
> +	if (block_faults) {
> +		filemap_invalidate_lock(inode->i_mapping);
> +		err = fuse_dax_break_layouts(inode, 0, 0);
> +		if (err)
> +			goto out;
> +	}
>  
> -		if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) {
> -			loff_t endbyte = offset + length - 1;
> +	if (mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) {
> +		loff_t endbyte = offset + length - 1;
>  
> -			err = fuse_writeback_range(inode, offset, endbyte);
> -			if (err)
> -				goto out;
> -		}
> +		err = fuse_writeback_range(inode, offset, endbyte);
> +		if (err)
> +			goto out;
>  	}
>  
>  	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
> @@ -3039,8 +3035,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
>  	if (block_faults)
>  		filemap_invalidate_unlock(inode->i_mapping);
>  
> -	if (lock_inode)
> -		inode_unlock(inode);
> +	inode_unlock(inode);
>  
>  	fuse_flush_time_update(inode);
>  
> -- 
> 2.38.1
> 


      reply	other threads:[~2022-11-28 20:10 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-23 10:43 [PATCH] fuse: lock inode unconditionally in fuse_fallocate() Miklos Szeredi
2022-11-28 20:09 ` Vivek Goyal [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y4UVhzMHYbigU72b@redhat.com \
    --to=vgoyal@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=mszeredi@redhat.com \
    --cc=pengfei.xu@intel.com \
    --cc=syzbot+462da39f0667b357c4b6@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.