public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write
@ 2020-06-15 17:46 fdmanana
  2020-06-16 14:34 ` David Sterba
  2020-06-16 19:26 ` Josef Bacik
  0 siblings, 2 replies; 5+ messages in thread
From: fdmanana @ 2020-06-15 17:46 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

If we do a successful RWF_NOWAIT write we end up locking the snapshot lock
of the inode, through a call to check_can_nocow(), but we never unlock it.

This means the next attempt to create a snapshot on the subvolume will
hang forever.

Trivial reproducer:

  $ mkfs.btrfs -f /dev/sdb
  $ mount /dev/sdb /mnt

  $ touch /mnt/foobar
  $ chattr +C /mnt/foobar
  $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foobar
  $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe 0 64K" /mnt/foobar

  $ btrfs subvolume snapshot -r /mnt /mnt/snap
    --> hangs

Fix this by unlocking the snapshot lock if check_can_nocow() returned
success.

Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
CC: stable@vger.kernel.org # 4.13+
Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/file.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 2c14312b05e8..04faa04fccd1 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1914,6 +1914,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
 			inode_unlock(inode);
 			return -EAGAIN;
 		}
+		/* check_can_nocow() locks the snapshot lock on success */
+		btrfs_drew_write_unlock(&root->snapshot_lock);
 	}
 
 	current->backing_dev_info = inode_to_bdi(inode);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write
  2020-06-15 17:46 [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write fdmanana
@ 2020-06-16 14:34 ` David Sterba
  2020-06-16 15:17   ` Filipe Manana
  2020-06-16 19:26 ` Josef Bacik
  1 sibling, 1 reply; 5+ messages in thread
From: David Sterba @ 2020-06-16 14:34 UTC (permalink / raw)
  To: fdmanana; +Cc: linux-btrfs

On Mon, Jun 15, 2020 at 06:46:01PM +0100, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> If we do a successful RWF_NOWAIT write we end up locking the snapshot lock
> of the inode, through a call to check_can_nocow(), but we never unlock it.
> 
> This means the next attempt to create a snapshot on the subvolume will
> hang forever.
> 
> Trivial reproducer:
> 
>   $ mkfs.btrfs -f /dev/sdb
>   $ mount /dev/sdb /mnt
> 
>   $ touch /mnt/foobar
>   $ chattr +C /mnt/foobar
>   $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foobar
>   $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe 0 64K" /mnt/foobar
> 
>   $ btrfs subvolume snapshot -r /mnt /mnt/snap
>     --> hangs
> 
> Fix this by unlocking the snapshot lock if check_can_nocow() returned
> success.
> 
> Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
> CC: stable@vger.kernel.org # 4.13+
> Signed-off-by: Filipe Manana <fdmanana@suse.com>
> ---
>  fs/btrfs/file.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index 2c14312b05e8..04faa04fccd1 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -1914,6 +1914,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
>  			inode_unlock(inode);
>  			return -EAGAIN;
>  		}
> +		/* check_can_nocow() locks the snapshot lock on success */
> +		btrfs_drew_write_unlock(&root->snapshot_lock);

That's quite ugly that the locking semantics of check_can_nocow is
hidden, this should be cleaned up too.

The whole condition

1909                 if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
1910                                               BTRFS_INODE_PREALLOC)) ||
1911                     check_can_nocow(BTRFS_I(inode), pos, &count) <= 0)

has 2 parts and it's not obvious from the context when the lock actually is
taken. The flags check could be pushed down to check_can_nocow, the
same but negated condition can be found in btrfs_file_write_iter so this
would make it something like:

	if (check_can_nocow(inode, pos, &count) <= 0) {
		/* fallback */
		return ...;
	}
	/*
	 * the lock is taken and needs to be unlocked at the right time
	 */

Suggestions to rename check_can_nocow welcome too.


>  	}
>  
>  	current->backing_dev_info = inode_to_bdi(inode);
> -- 
> 2.26.2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write
  2020-06-16 14:34 ` David Sterba
@ 2020-06-16 15:17   ` Filipe Manana
  2020-06-16 15:23     ` David Sterba
  0 siblings, 1 reply; 5+ messages in thread
From: Filipe Manana @ 2020-06-16 15:17 UTC (permalink / raw)
  To: dsterba, Filipe Manana, linux-btrfs

On Tue, Jun 16, 2020 at 3:34 PM David Sterba <dsterba@suse.cz> wrote:
>
> On Mon, Jun 15, 2020 at 06:46:01PM +0100, fdmanana@kernel.org wrote:
> > From: Filipe Manana <fdmanana@suse.com>
> >
> > If we do a successful RWF_NOWAIT write we end up locking the snapshot lock
> > of the inode, through a call to check_can_nocow(), but we never unlock it.
> >
> > This means the next attempt to create a snapshot on the subvolume will
> > hang forever.
> >
> > Trivial reproducer:
> >
> >   $ mkfs.btrfs -f /dev/sdb
> >   $ mount /dev/sdb /mnt
> >
> >   $ touch /mnt/foobar
> >   $ chattr +C /mnt/foobar
> >   $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foobar
> >   $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe 0 64K" /mnt/foobar
> >
> >   $ btrfs subvolume snapshot -r /mnt /mnt/snap
> >     --> hangs
> >
> > Fix this by unlocking the snapshot lock if check_can_nocow() returned
> > success.
> >
> > Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
> > CC: stable@vger.kernel.org # 4.13+
> > Signed-off-by: Filipe Manana <fdmanana@suse.com>
> > ---
> >  fs/btrfs/file.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> > index 2c14312b05e8..04faa04fccd1 100644
> > --- a/fs/btrfs/file.c
> > +++ b/fs/btrfs/file.c
> > @@ -1914,6 +1914,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
> >                       inode_unlock(inode);
> >                       return -EAGAIN;
> >               }
> > +             /* check_can_nocow() locks the snapshot lock on success */
> > +             btrfs_drew_write_unlock(&root->snapshot_lock);
>
> That's quite ugly that the locking semantics of check_can_nocow is
> hidden, this should be cleaned up too.
>
> The whole condition
>
> 1909                 if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
> 1910                                               BTRFS_INODE_PREALLOC)) ||
> 1911                     check_can_nocow(BTRFS_I(inode), pos, &count) <= 0)
>
> has 2 parts and it's not obvious from the context when the lock actually is
> taken. The flags check could be pushed down to check_can_nocow, the
> same but negated condition can be found in btrfs_file_write_iter so this
> would make it something like:
>
>         if (check_can_nocow(inode, pos, &count) <= 0) {
>                 /* fallback */
>                 return ...;
>         }
>         /*
>          * the lock is taken and needs to be unlocked at the right time
>          */
>
> Suggestions to rename check_can_nocow welcome too.

Sure, I can understand it may look not obvious on first sight at least.

Here I'm only focusing on functional problems and kept this fix as
small as possible to backport to stable releases,
as this is a bug that directly impacts user experience.

Thanks.

>
>
> >       }
> >
> >       current->backing_dev_info = inode_to_bdi(inode);
> > --
> > 2.26.2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write
  2020-06-16 15:17   ` Filipe Manana
@ 2020-06-16 15:23     ` David Sterba
  0 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2020-06-16 15:23 UTC (permalink / raw)
  To: Filipe Manana; +Cc: dsterba, linux-btrfs

On Tue, Jun 16, 2020 at 04:17:19PM +0100, Filipe Manana wrote:
> On Tue, Jun 16, 2020 at 3:34 PM David Sterba <dsterba@suse.cz> wrote:
> > On Mon, Jun 15, 2020 at 06:46:01PM +0100, fdmanana@kernel.org wrote:
> > > From: Filipe Manana <fdmanana@suse.com>
> > > --- a/fs/btrfs/file.c
> > > +++ b/fs/btrfs/file.c
> > > @@ -1914,6 +1914,8 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
> > >                       inode_unlock(inode);
> > >                       return -EAGAIN;
> > >               }
> > > +             /* check_can_nocow() locks the snapshot lock on success */
> > > +             btrfs_drew_write_unlock(&root->snapshot_lock);
> >
> > That's quite ugly that the locking semantics of check_can_nocow is
> > hidden, this should be cleaned up too.
> >
> > The whole condition
> >
> > 1909                 if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
> > 1910                                               BTRFS_INODE_PREALLOC)) ||
> > 1911                     check_can_nocow(BTRFS_I(inode), pos, &count) <= 0)
> >
> > has 2 parts and it's not obvious from the context when the lock actually is
> > taken. The flags check could be pushed down to check_can_nocow, the
> > same but negated condition can be found in btrfs_file_write_iter so this
> > would make it something like:
> >
> >         if (check_can_nocow(inode, pos, &count) <= 0) {
> >                 /* fallback */
> >                 return ...;
> >         }
> >         /*
> >          * the lock is taken and needs to be unlocked at the right time
> >          */
> >
> > Suggestions to rename check_can_nocow welcome too.
> 
> Sure, I can understand it may look not obvious on first sight at least.
> 
> Here I'm only focusing on functional problems and kept this fix as
> small as possible to backport to stable releases,
> as this is a bug that directly impacts user experience.

Ok that makes sense of course, I'll add the four patches to misc-next
and queue them for rc. Thanks.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write
  2020-06-15 17:46 [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write fdmanana
  2020-06-16 14:34 ` David Sterba
@ 2020-06-16 19:26 ` Josef Bacik
  1 sibling, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2020-06-16 19:26 UTC (permalink / raw)
  To: fdmanana, linux-btrfs

On 6/15/20 1:46 PM, fdmanana@kernel.org wrote:
> From: Filipe Manana <fdmanana@suse.com>
> 
> If we do a successful RWF_NOWAIT write we end up locking the snapshot lock
> of the inode, through a call to check_can_nocow(), but we never unlock it.
> 
> This means the next attempt to create a snapshot on the subvolume will
> hang forever.
> 
> Trivial reproducer:
> 
>    $ mkfs.btrfs -f /dev/sdb
>    $ mount /dev/sdb /mnt
> 
>    $ touch /mnt/foobar
>    $ chattr +C /mnt/foobar
>    $ xfs_io -d -c "pwrite -S 0xab 0 64K" /mnt/foobar
>    $ xfs_io -d -c "pwrite -N -V 1 -S 0xfe 0 64K" /mnt/foobar
> 
>    $ btrfs subvolume snapshot -r /mnt /mnt/snap
>      --> hangs
> 
> Fix this by unlocking the snapshot lock if check_can_nocow() returned
> success.
> 
> Fixes: edf064e7c6fec3 ("btrfs: nowait aio support")
> CC: stable@vger.kernel.org # 4.13+
> Signed-off-by: Filipe Manana <fdmanana@suse.com>

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

Thanks,

Josef

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-06-16 19:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-06-15 17:46 [PATCH 1/4] Btrfs: fix hang on snapshot creation after RWF_NOWAIT write fdmanana
2020-06-16 14:34 ` David Sterba
2020-06-16 15:17   ` Filipe Manana
2020-06-16 15:23     ` David Sterba
2020-06-16 19:26 ` Josef Bacik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox