ACK: [SRU] [B] [PATCH v2 1/1] fuse: fix initial parallel dirops

Stefan Bader stefan.bader at canonical.com
Wed Apr 17 17:01:30 UTC 2019


On 12.04.19 16:35, Andrea Righi wrote:
> From: Miklos Szeredi <mszeredi at redhat.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1823972
> 
> If parallel dirops are enabled in FUSE_INIT reply, then first operation may
> leave fi->mutex held.
> 
> Reported-by: syzbot <syzbot+3f7b29af1baa9d0a55be at syzkaller.appspotmail.com>
> Fixes: 5c672ab3f0ee ("fuse: serialize dirops by default")
> Cc: <stable at vger.kernel.org> # v4.7
> Signed-off-by: Miklos Szeredi <mszeredi at redhat.com>
> (cherry picked from commit 63576c13bd17848376c8ba4a98f5d5151140c4ac)
> Signed-off-by: Andrea Righi <andrea.righi at canonical.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---
>  fs/fuse/dir.c    | 10 ++++++----
>  fs/fuse/fuse_i.h |  4 ++--
>  fs/fuse/inode.c  | 14 ++++++++++----
>  3 files changed, 18 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
> index fa4009761a7a..69524ba8551b 100644
> --- a/fs/fuse/dir.c
> +++ b/fs/fuse/dir.c
> @@ -355,11 +355,12 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
>  	struct inode *inode;
>  	struct dentry *newent;
>  	bool outarg_valid = true;
> +	bool locked;
>  
> -	fuse_lock_inode(dir);
> +	locked = fuse_lock_inode(dir);
>  	err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
>  			       &outarg, &inode);
> -	fuse_unlock_inode(dir);
> +	fuse_unlock_inode(dir, locked);
>  	if (err == -ENOENT) {
>  		outarg_valid = false;
>  		err = 0;
> @@ -1332,6 +1333,7 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
>  	struct fuse_conn *fc = get_fuse_conn(inode);
>  	struct fuse_req *req;
>  	u64 attr_version = 0;
> +	bool locked;
>  
>  	if (is_bad_inode(inode))
>  		return -EIO;
> @@ -1359,9 +1361,9 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
>  		fuse_read_fill(req, file, ctx->pos, PAGE_SIZE,
>  			       FUSE_READDIR);
>  	}
> -	fuse_lock_inode(inode);
> +	locked = fuse_lock_inode(inode);
>  	fuse_request_send(fc, req);
> -	fuse_unlock_inode(inode);
> +	fuse_unlock_inode(inode, locked);
>  	nbytes = req->out.args[0].size;
>  	err = req->out.h.error;
>  	fuse_put_request(fc, req);
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index b5594a978d5b..a6a33272c153 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -969,8 +969,8 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
>  
>  void fuse_set_initialized(struct fuse_conn *fc);
>  
> -void fuse_unlock_inode(struct inode *inode);
> -void fuse_lock_inode(struct inode *inode);
> +void fuse_unlock_inode(struct inode *inode, bool locked);
> +bool fuse_lock_inode(struct inode *inode);
>  
>  int fuse_setxattr(struct inode *inode, const char *name, const void *value,
>  		  size_t size, int flags);
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index fea6ea8cd568..9fb5b37152e5 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -357,15 +357,21 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid,
>  	return 0;
>  }
>  
> -void fuse_lock_inode(struct inode *inode)
> +bool fuse_lock_inode(struct inode *inode)
>  {
> -	if (!get_fuse_conn(inode)->parallel_dirops)
> +	bool locked = false;
> +
> +	if (!get_fuse_conn(inode)->parallel_dirops) {
>  		mutex_lock(&get_fuse_inode(inode)->mutex);
> +		locked = true;
> +	}
> +
> +	return locked;
>  }
>  
> -void fuse_unlock_inode(struct inode *inode)
> +void fuse_unlock_inode(struct inode *inode, bool locked)
>  {
> -	if (!get_fuse_conn(inode)->parallel_dirops)
> +	if (locked)
>  		mutex_unlock(&get_fuse_inode(inode)->mutex);
>  }
>  
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20190417/0a052d08/attachment.sig>


More information about the kernel-team mailing list