* [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