diff mbox series

[4/4] btrfs: use test_and_clear_bit() in wait_dev_flush()

Message ID 7baf74b071f9d9002d2543cfc4f86bd3ddf7127f.1679910088.git.anand.jain@oracle.com (mailing list archive)
State New, archived
Headers show
Series btrfs: optimize disks flush code | expand

Commit Message

Anand Jain March 27, 2023, 9:53 a.m. UTC
The function wait_dev_flush() tests for the BTRFS_DEV_STATE_FLUSH_SENT
bit and then clears it separately. Instead, use test_and_clear_bit().

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/disk-io.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

Comments

David Sterba March 27, 2023, 5:14 p.m. UTC | #1
On Mon, Mar 27, 2023 at 05:53:10PM +0800, Anand Jain wrote:
> The function wait_dev_flush() tests for the BTRFS_DEV_STATE_FLUSH_SENT
> bit and then clears it separately. Instead, use test_and_clear_bit().

But why would we need to do it like that? The write and wait are
executed in one thread so we don't need atomic change to the status and
thus a separate set/test/clear bit are fine. If not, then please
explain. Thanks.
Anand Jain March 28, 2023, 5:05 a.m. UTC | #2
On 3/28/23 01:14, David Sterba wrote:
> On Mon, Mar 27, 2023 at 05:53:10PM +0800, Anand Jain wrote:
>> The function wait_dev_flush() tests for the BTRFS_DEV_STATE_FLUSH_SENT
>> bit and then clears it separately. Instead, use test_and_clear_bit().
> 
> But why would we need to do it like that? The write and wait are
> executed in one thread so we don't need atomic change to the status and
> thus a separate set/test/clear bit are fine. If not, then please
> explain. Thanks.

It's true that atomic test_and_clear_bit() isn't necessary in this case.
Nonetheless, using it have benefits such as cleaner code and improved
efficiency[1].

  [1]. I was curious, so I made wait_dev_flush() non-inline and checked
  the ASM code for wait_dev_flush(). After the patch, there were 8 fewer
  instructions.

I'm okay with dropping this patch if you prefer to maintain the correct
usage of test_and_clear_bit().

Thanks, Anand
David Sterba March 28, 2023, 6:33 p.m. UTC | #3
On Tue, Mar 28, 2023 at 01:05:12PM +0800, Anand Jain wrote:
> 
> 
> On 3/28/23 01:14, David Sterba wrote:
> > On Mon, Mar 27, 2023 at 05:53:10PM +0800, Anand Jain wrote:
> >> The function wait_dev_flush() tests for the BTRFS_DEV_STATE_FLUSH_SENT
> >> bit and then clears it separately. Instead, use test_and_clear_bit().
> > 
> > But why would we need to do it like that? The write and wait are
> > executed in one thread so we don't need atomic change to the status and
> > thus a separate set/test/clear bit are fine. If not, then please
> > explain. Thanks.
> 
> It's true that atomic test_and_clear_bit() isn't necessary in this case.
> Nonetheless, using it have benefits such as cleaner code and improved
> efficiency[1].
> 
>   [1]. I was curious, so I made wait_dev_flush() non-inline and checked
>   the ASM code for wait_dev_flush(). After the patch, there were 8 fewer
>   instructions.
> 
> I'm okay with dropping this patch if you prefer to maintain the correct
> usage of test_and_clear_bit().

Fewer instructions is a bonus here, but from the logic POV a test_bit in
a condition immediately followed by a clear_bit is not a common
pattern.  So even if we don't need the atomic semantics it's following a
common pattern which is good.
diff mbox series

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 040142f2e76c..1f9e2a2a8267 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4108,10 +4108,9 @@  static bool wait_dev_flush(struct btrfs_device *device)
 {
 	struct bio *bio = &device->flush_bio;
 
-	if (!test_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state))
+	if (!test_and_clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state))
 		return true;
 
-	clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state);
 	wait_for_completion_io(&device->flush_wait);
 
 	if (bio->bi_status) {