linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] btrfs: optimize disks flush code
@ 2023-03-27  9:53 Anand Jain
  2023-03-27  9:53 ` [PATCH 1/4] btrfs: move last_flush_error to write_dev_flush and wait_dev_flush Anand Jain
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Anand Jain @ 2023-03-27  9:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Anand Jain

A few items were identified that could be optimized and simplified in
wait_dev_flush() and wait_dev_flush().

Anand Jain (4):
  btrfs: move last_flush_error to write_dev_flush and wait_dev_flush
  btrfs: opencode check_barrier_error()
  Btrfs: change wait_dev_flush() return type to bool
  btrfs: use test_and_clear_bit() in wait_dev_flush()

 fs/btrfs/disk-io.c | 45 ++++++++++++++++++++-------------------------
 1 file changed, 20 insertions(+), 25 deletions(-)

-- 
2.39.2


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

* [PATCH 1/4] btrfs: move last_flush_error to write_dev_flush and wait_dev_flush
  2023-03-27  9:53 [PATCH 0/4] btrfs: optimize disks flush code Anand Jain
@ 2023-03-27  9:53 ` Anand Jain
  2023-03-27  9:53 ` [PATCH 2/4] btrfs: opencode check_barrier_error() Anand Jain
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Anand Jain @ 2023-03-27  9:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Anand Jain

We parallelize the flush command across devices using our own code,
write_dev_flush() sends the flush command to each device and
wait_dev_flush() waits for the flush to complete on all devices. Errors
from each device are recorded at device->last_flush_error and reset to
BLK_STS_OK in write_dev_flush() and to the error, if any, in
wait_dev_flush(). These functions are called from barrier_all_devices().

This patch consolidates the use of device->last_flush_error in
write_dev_flush() and wait_dev_flush() to remove it from
barrier_all_devices().

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

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b638e27468a7..7f3fa5e2253d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4072,6 +4072,8 @@ static void write_dev_flush(struct btrfs_device *device)
 {
 	struct bio *bio = &device->flush_bio;
 
+	device->last_flush_error = BLK_STS_OK;
+
 #ifndef CONFIG_BTRFS_FS_CHECK_INTEGRITY
 	/*
 	 * When a disk has write caching disabled, we skip submission of a bio
@@ -4111,6 +4113,11 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
 	clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state);
 	wait_for_completion_io(&device->flush_wait);
 
+	if (bio->bi_status) {
+		device->last_flush_error = bio->bi_status;
+		btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_FLUSH_ERRS);
+	}
+
 	return bio->bi_status;
 }
 
@@ -4145,7 +4152,6 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 			continue;
 
 		write_dev_flush(dev);
-		dev->last_flush_error = BLK_STS_OK;
 	}
 
 	/* wait for all the barriers */
@@ -4161,12 +4167,8 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 			continue;
 
 		ret = wait_dev_flush(dev);
-		if (ret) {
-			dev->last_flush_error = ret;
-			btrfs_dev_stat_inc_and_print(dev,
-					BTRFS_DEV_STAT_FLUSH_ERRS);
+		if (ret)
 			errors_wait++;
-		}
 	}
 
 	if (errors_wait) {
-- 
2.39.2


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

* [PATCH 2/4] btrfs: opencode check_barrier_error()
  2023-03-27  9:53 [PATCH 0/4] btrfs: optimize disks flush code Anand Jain
  2023-03-27  9:53 ` [PATCH 1/4] btrfs: move last_flush_error to write_dev_flush and wait_dev_flush Anand Jain
@ 2023-03-27  9:53 ` Anand Jain
  2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
  2023-03-27  9:53 ` [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush() Anand Jain
  3 siblings, 0 replies; 13+ messages in thread
From: Anand Jain @ 2023-03-27  9:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Anand Jain

check_barrier_error() is almost a single line function, and just calls
btrfs_check_rw_degradable(). Instead, opencode it.

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

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7f3fa5e2253d..745be1f4ab6d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4121,13 +4121,6 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
 	return bio->bi_status;
 }
 
-static int check_barrier_error(struct btrfs_fs_info *fs_info)
-{
-	if (!btrfs_check_rw_degradable(fs_info, NULL))
-		return -EIO;
-	return 0;
-}
-
 /*
  * send an empty flush down to each device in parallel,
  * then wait for them
@@ -4171,14 +4164,13 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 			errors_wait++;
 	}
 
-	if (errors_wait) {
-		/*
-		 * At some point we need the status of all disks
-		 * to arrive at the volume status. So error checking
-		 * is being pushed to a separate loop.
-		 */
-		return check_barrier_error(info);
-	}
+	/*
+	 * Checks last_flush_error of disks in order to determine the
+	 * volume state.
+	 */
+	if (errors_wait && !btrfs_check_rw_degradable(info, NULL))
+		return -EIO;
+
 	return 0;
 }
 
-- 
2.39.2


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

* [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool
  2023-03-27  9:53 [PATCH 0/4] btrfs: optimize disks flush code Anand Jain
  2023-03-27  9:53 ` [PATCH 1/4] btrfs: move last_flush_error to write_dev_flush and wait_dev_flush Anand Jain
  2023-03-27  9:53 ` [PATCH 2/4] btrfs: opencode check_barrier_error() Anand Jain
@ 2023-03-27  9:53 ` Anand Jain
  2023-03-27 17:11   ` David Sterba
                     ` (2 more replies)
  2023-03-27  9:53 ` [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush() Anand Jain
  3 siblings, 3 replies; 13+ messages in thread
From: Anand Jain @ 2023-03-27  9:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Anand Jain

The flush error code is maintained in btrfs_device::last_flush_error, so
there is no point in returning it in wait_dev_flush() when it is not being
used. Instead, we can return a boolean value.

Note that even though btrfs_device::last_flush_error may not be used, we
will keep it for now.

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

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 745be1f4ab6d..040142f2e76c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4102,13 +4102,14 @@ static void write_dev_flush(struct btrfs_device *device)
 
 /*
  * If the flush bio has been submitted by write_dev_flush, wait for it.
+ * Return false for any error, and true otherwise.
  */
-static blk_status_t wait_dev_flush(struct btrfs_device *device)
+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))
-		return BLK_STS_OK;
+		return true;
 
 	clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state);
 	wait_for_completion_io(&device->flush_wait);
@@ -4116,9 +4117,10 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
 	if (bio->bi_status) {
 		device->last_flush_error = bio->bi_status;
 		btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_FLUSH_ERRS);
+		return false;
 	}
 
-	return bio->bi_status;
+	return true;
 }
 
 /*
-- 
2.39.2


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

* [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush()
  2023-03-27  9:53 [PATCH 0/4] btrfs: optimize disks flush code Anand Jain
                   ` (2 preceding siblings ...)
  2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
@ 2023-03-27  9:53 ` Anand Jain
  2023-03-27 17:14   ` David Sterba
  3 siblings, 1 reply; 13+ messages in thread
From: Anand Jain @ 2023-03-27  9:53 UTC (permalink / raw)
  To: linux-btrfs; +Cc: Anand Jain

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(-)

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) {
-- 
2.39.2


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

* Re: [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool
  2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
@ 2023-03-27 17:11   ` David Sterba
  2023-03-28  2:58     ` Anand Jain
  2023-03-27 23:52   ` kernel test robot
  2023-03-28  5:31   ` [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2 Anand Jain
  2 siblings, 1 reply; 13+ messages in thread
From: David Sterba @ 2023-03-27 17:11 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs

On Mon, Mar 27, 2023 at 05:53:09PM +0800, Anand Jain wrote:
> The flush error code is maintained in btrfs_device::last_flush_error, so
> there is no point in returning it in wait_dev_flush() when it is not being
> used. Instead, we can return a boolean value.
> 
> Note that even though btrfs_device::last_flush_error may not be used, we
> will keep it for now.
> 
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
>  fs/btrfs/disk-io.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 745be1f4ab6d..040142f2e76c 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -4102,13 +4102,14 @@ static void write_dev_flush(struct btrfs_device *device)
>  
>  /*
>   * If the flush bio has been submitted by write_dev_flush, wait for it.
> + * Return false for any error, and true otherwise.

This does not match how the function is used, originally a zero value
means no error, now zero (false) means an error.

4152         list_for_each_entry(dev, head, dev_list) {
4153                 if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
4154                         continue;
4155                 if (!dev->bdev) {
4156                         errors_wait++;
4157                         continue;
4158                 }
4159                 if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &dev->dev_state) ||
4160                     !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))
4161                         continue;
4162
4163                 ret = wait_dev_flush(dev);
4164                 if (ret)
4165                         errors_wait++;
4166         }

So here it's reversed (with all patches applied). You could keep the
meaning of the retrun value to be true=ok, false=error, it's still
understandable if there conditions looks like

	ret = wait_dev_flush()
	if (!ret)
		errors++;

Another pattern is to return true on errors (typically functions that
check some condition), so it's the conditions are structured as:

	if (error)
		handle();

>   */
> -static blk_status_t wait_dev_flush(struct btrfs_device *device)
> +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))
> -		return BLK_STS_OK;
> +		return true;

This should be 'false'

>  
>  	clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state);
>  	wait_for_completion_io(&device->flush_wait);
> @@ -4116,9 +4117,10 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
>  	if (bio->bi_status) {
>  		device->last_flush_error = bio->bi_status;
>  		btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_FLUSH_ERRS);
> +		return false;
>  	}
>  
> -	return bio->bi_status;
> +	return true;
>  }

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

* Re: [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush()
  2023-03-27  9:53 ` [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush() Anand Jain
@ 2023-03-27 17:14   ` David Sterba
  2023-03-28  5:05     ` Anand Jain
  0 siblings, 1 reply; 13+ messages in thread
From: David Sterba @ 2023-03-27 17:14 UTC (permalink / raw)
  To: Anand Jain; +Cc: linux-btrfs

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.

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

* Re: [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool
  2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
  2023-03-27 17:11   ` David Sterba
@ 2023-03-27 23:52   ` kernel test robot
  2023-03-28  5:31   ` [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2 Anand Jain
  2 siblings, 0 replies; 13+ messages in thread
From: kernel test robot @ 2023-03-27 23:52 UTC (permalink / raw)
  To: Anand Jain, linux-btrfs; +Cc: oe-kbuild-all, Anand Jain

Hi Anand,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on kdave/for-next]
[also build test WARNING on linus/master v6.3-rc4 next-20230327]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Anand-Jain/btrfs-move-last_flush_error-to-write_dev_flush-and-wait_dev_flush/20230327-180139
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next
patch link:    https://lore.kernel.org/r/3e067c8b0956f0134501c8eea2e19c8eb5adcedc.1679910088.git.anand.jain%40oracle.com
patch subject: [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool
config: i386-randconfig-s002 (https://download.01.org/0day-ci/archive/20230328/202303280731.3zPschfL-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/d26d540e470da0010fed61401cf0b7147f175aa1
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Anand-Jain/btrfs-move-last_flush_error-to-write_dev_flush-and-wait_dev_flush/20230327-180139
        git checkout d26d540e470da0010fed61401cf0b7147f175aa1
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 olddefconfig
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303280731.3zPschfL-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> fs/btrfs/disk-io.c:4172:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted blk_status_t [usertype] ret @@     got bool @@
   fs/btrfs/disk-io.c:4172:21: sparse:     expected restricted blk_status_t [usertype] ret
   fs/btrfs/disk-io.c:4172:21: sparse:     got bool

vim +4172 fs/btrfs/disk-io.c

387125fc722a8e Chris Mason       2011-11-18  4133  
387125fc722a8e Chris Mason       2011-11-18  4134  /*
387125fc722a8e Chris Mason       2011-11-18  4135   * send an empty flush down to each device in parallel,
387125fc722a8e Chris Mason       2011-11-18  4136   * then wait for them
387125fc722a8e Chris Mason       2011-11-18  4137   */
387125fc722a8e Chris Mason       2011-11-18  4138  static int barrier_all_devices(struct btrfs_fs_info *info)
387125fc722a8e Chris Mason       2011-11-18  4139  {
387125fc722a8e Chris Mason       2011-11-18  4140  	struct list_head *head;
387125fc722a8e Chris Mason       2011-11-18  4141  	struct btrfs_device *dev;
5af3e8cce8b7ba Stefan Behrens    2012-08-01  4142  	int errors_wait = 0;
4e4cbee93d5613 Christoph Hellwig 2017-06-03  4143  	blk_status_t ret;
387125fc722a8e Chris Mason       2011-11-18  4144  
1538e6c52e1917 David Sterba      2017-06-16  4145  	lockdep_assert_held(&info->fs_devices->device_list_mutex);
387125fc722a8e Chris Mason       2011-11-18  4146  	/* send down all the barriers */
387125fc722a8e Chris Mason       2011-11-18  4147  	head = &info->fs_devices->devices;
1538e6c52e1917 David Sterba      2017-06-16  4148  	list_for_each_entry(dev, head, dev_list) {
e6e674bd4d54fe Anand Jain        2017-12-04  4149  		if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
f88ba6a2a44ee9 Hidetoshi Seto    2014-02-05  4150  			continue;
cea7c8bf77209b Anand Jain        2017-06-13  4151  		if (!dev->bdev)
387125fc722a8e Chris Mason       2011-11-18  4152  			continue;
e12c96214d28f9 Anand Jain        2017-12-04  4153  		if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &dev->dev_state) ||
ebbede42d47dc7 Anand Jain        2017-12-04  4154  		    !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))
387125fc722a8e Chris Mason       2011-11-18  4155  			continue;
387125fc722a8e Chris Mason       2011-11-18  4156  
4fc6441aac7589 Anand Jain        2017-06-13  4157  		write_dev_flush(dev);
387125fc722a8e Chris Mason       2011-11-18  4158  	}
387125fc722a8e Chris Mason       2011-11-18  4159  
387125fc722a8e Chris Mason       2011-11-18  4160  	/* wait for all the barriers */
1538e6c52e1917 David Sterba      2017-06-16  4161  	list_for_each_entry(dev, head, dev_list) {
e6e674bd4d54fe Anand Jain        2017-12-04  4162  		if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
f88ba6a2a44ee9 Hidetoshi Seto    2014-02-05  4163  			continue;
387125fc722a8e Chris Mason       2011-11-18  4164  		if (!dev->bdev) {
5af3e8cce8b7ba Stefan Behrens    2012-08-01  4165  			errors_wait++;
387125fc722a8e Chris Mason       2011-11-18  4166  			continue;
387125fc722a8e Chris Mason       2011-11-18  4167  		}
e12c96214d28f9 Anand Jain        2017-12-04  4168  		if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &dev->dev_state) ||
ebbede42d47dc7 Anand Jain        2017-12-04  4169  		    !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))
387125fc722a8e Chris Mason       2011-11-18  4170  			continue;
387125fc722a8e Chris Mason       2011-11-18  4171  
4fc6441aac7589 Anand Jain        2017-06-13 @4172  		ret = wait_dev_flush(dev);
7b3115dae5a0a2 Anand Jain        2023-03-27  4173  		if (ret)
5af3e8cce8b7ba Stefan Behrens    2012-08-01  4174  			errors_wait++;
387125fc722a8e Chris Mason       2011-11-18  4175  	}
401b41e5a85a63 Anand Jain        2017-05-06  4176  
401b41e5a85a63 Anand Jain        2017-05-06  4177  	/*
a112dad7e3abca Anand Jain        2023-03-27  4178  	 * Checks last_flush_error of disks in order to determine the
a112dad7e3abca Anand Jain        2023-03-27  4179  	 * volume state.
401b41e5a85a63 Anand Jain        2017-05-06  4180  	 */
a112dad7e3abca Anand Jain        2023-03-27  4181  	if (errors_wait && !btrfs_check_rw_degradable(info, NULL))
a112dad7e3abca Anand Jain        2023-03-27  4182  		return -EIO;
a112dad7e3abca Anand Jain        2023-03-27  4183  
387125fc722a8e Chris Mason       2011-11-18  4184  	return 0;
387125fc722a8e Chris Mason       2011-11-18  4185  }
387125fc722a8e Chris Mason       2011-11-18  4186  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

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

* Re: [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool
  2023-03-27 17:11   ` David Sterba
@ 2023-03-28  2:58     ` Anand Jain
  0 siblings, 0 replies; 13+ messages in thread
From: Anand Jain @ 2023-03-28  2:58 UTC (permalink / raw)
  To: dsterba; +Cc: linux-btrfs



On 3/28/23 01:11, David Sterba wrote:
> On Mon, Mar 27, 2023 at 05:53:09PM +0800, Anand Jain wrote:
>> The flush error code is maintained in btrfs_device::last_flush_error, so
>> there is no point in returning it in wait_dev_flush() when it is not being
>> used. Instead, we can return a boolean value.
>>
>> Note that even though btrfs_device::last_flush_error may not be used, we
>> will keep it for now.
>>
>> Signed-off-by: Anand Jain <anand.jain@oracle.com>
>> ---
>>   fs/btrfs/disk-io.c | 8 +++++---
>>   1 file changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
>> index 745be1f4ab6d..040142f2e76c 100644
>> --- a/fs/btrfs/disk-io.c
>> +++ b/fs/btrfs/disk-io.c
>> @@ -4102,13 +4102,14 @@ static void write_dev_flush(struct btrfs_device *device)
>>   
>>   /*
>>    * If the flush bio has been submitted by write_dev_flush, wait for it.
>> + * Return false for any error, and true otherwise.
> 
> This does not match how the function is used, originally a zero value
> means no error, now zero (false) means an error.
> 
> 4152         list_for_each_entry(dev, head, dev_list) {
> 4153                 if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
> 4154                         continue;
> 4155                 if (!dev->bdev) {
> 4156                         errors_wait++;
> 4157                         continue;
> 4158                 }
> 4159                 if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &dev->dev_state) ||
> 4160                     !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))
> 4161                         continue;
> 4162
> 4163                 ret = wait_dev_flush(dev);
> 4164                 if (ret)
> 4165                         errors_wait++;
> 4166         }
> 
> So here it's reversed (with all patches applied). You could keep the
> meaning of the retrun value to be true=ok, false=error, it's still
> understandable if there conditions looks like
> 
> 	ret = wait_dev_flush()
> 	if (!ret)
> 		errors++;
> 

  My bad. Though I knew, it slipped. Thanks for pointing it out.

> Another pattern is to return true on errors (typically functions that
> check some condition), so it's the conditions are structured as:
> 
> 	if (error)
> 		handle();
> 

  Sure. I'll fix it.


>>    */
>> -static blk_status_t wait_dev_flush(struct btrfs_device *device)
>> +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))
>> -		return BLK_STS_OK;
>> +		return true;
> 
> This should be 'false'
Thanks.

>>   
>>   	clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state);
>>   	wait_for_completion_io(&device->flush_wait);
>> @@ -4116,9 +4117,10 @@ static blk_status_t wait_dev_flush(struct btrfs_device *device)
>>   	if (bio->bi_status) {
>>   		device->last_flush_error = bio->bi_status;
>>   		btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_FLUSH_ERRS);
>> +		return false;
>>   	}
>>   
>> -	return bio->bi_status;
>> +	return true;
>>   }

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

* Re: [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush()
  2023-03-27 17:14   ` David Sterba
@ 2023-03-28  5:05     ` Anand Jain
  2023-03-28 18:33       ` David Sterba
  0 siblings, 1 reply; 13+ messages in thread
From: Anand Jain @ 2023-03-28  5:05 UTC (permalink / raw)
  To: dsterba; +Cc: linux-btrfs



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


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

* [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2
  2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
  2023-03-27 17:11   ` David Sterba
  2023-03-27 23:52   ` kernel test robot
@ 2023-03-28  5:31   ` Anand Jain
  2023-03-28 18:28     ` David Sterba
  2 siblings, 1 reply; 13+ messages in thread
From: Anand Jain @ 2023-03-28  5:31 UTC (permalink / raw)
  To: dsterba, linux-btrfs; +Cc: Anand Jain

A fixup for the patch:
 Btrfs: change wait_dev_flush() return type to bool v2

In v2:
Fixes:
 Update write_dev_flush() to return false upon success and true upon errors.
 Remove the local variable ret in barrier_all_devices().
 Correct the bug where errors_wait was incremented upon success.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
Dave,

I am sending this patch as a fix-up while I am still waiting to hear
whether patch 4/4 will be dropped. If you would prefer to have this
series sent as v2 with patch 4/4 removed, I can do that.

 fs/btrfs/disk-io.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1f9e2a2a8267..a240e77448e0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4102,24 +4102,24 @@ static void write_dev_flush(struct btrfs_device *device)
 
 /*
  * If the flush bio has been submitted by write_dev_flush, wait for it.
- * Return false for any error, and true otherwise.
+ * Return true for any error, and false otherwise.
  */
 static bool wait_dev_flush(struct btrfs_device *device)
 {
 	struct bio *bio = &device->flush_bio;
 
 	if (!test_and_clear_bit(BTRFS_DEV_STATE_FLUSH_SENT, &device->dev_state))
-		return true;
+		return false;
 
 	wait_for_completion_io(&device->flush_wait);
 
 	if (bio->bi_status) {
 		device->last_flush_error = bio->bi_status;
 		btrfs_dev_stat_inc_and_print(device, BTRFS_DEV_STAT_FLUSH_ERRS);
-		return false;
+		return true;
 	}
 
-	return true;
+	return false;
 }
 
 /*
@@ -4131,7 +4131,6 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 	struct list_head *head;
 	struct btrfs_device *dev;
 	int errors_wait = 0;
-	blk_status_t ret;
 
 	lockdep_assert_held(&info->fs_devices->device_list_mutex);
 	/* send down all the barriers */
@@ -4160,8 +4159,7 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
 		    !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))
 			continue;
 
-		ret = wait_dev_flush(dev);
-		if (ret)
+		if (wait_dev_flush(dev))
 			errors_wait++;
 	}
 
-- 
2.39.2


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

* Re: [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2
  2023-03-28  5:31   ` [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2 Anand Jain
@ 2023-03-28 18:28     ` David Sterba
  0 siblings, 0 replies; 13+ messages in thread
From: David Sterba @ 2023-03-28 18:28 UTC (permalink / raw)
  To: Anand Jain; +Cc: dsterba, linux-btrfs

On Tue, Mar 28, 2023 at 01:31:27PM +0800, Anand Jain wrote:
> A fixup for the patch:
>  Btrfs: change wait_dev_flush() return type to bool v2
> 
> In v2:
> Fixes:
>  Update write_dev_flush() to return false upon success and true upon errors.
>  Remove the local variable ret in barrier_all_devices().
>  Correct the bug where errors_wait was incremented upon success.
> 
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
> Dave,
> 
> I am sending this patch as a fix-up while I am still waiting to hear
> whether patch 4/4 will be dropped. If you would prefer to have this
> series sent as v2 with patch 4/4 removed, I can do that.

Ok let's do test_and_clear(), I'll fold the fixup and add the series to
misc-next. Thanks.

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

* Re: [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush()
  2023-03-28  5:05     ` Anand Jain
@ 2023-03-28 18:33       ` David Sterba
  0 siblings, 0 replies; 13+ messages in thread
From: David Sterba @ 2023-03-28 18:33 UTC (permalink / raw)
  To: Anand Jain; +Cc: dsterba, linux-btrfs

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.

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

end of thread, other threads:[~2023-03-28 18:40 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-27  9:53 [PATCH 0/4] btrfs: optimize disks flush code Anand Jain
2023-03-27  9:53 ` [PATCH 1/4] btrfs: move last_flush_error to write_dev_flush and wait_dev_flush Anand Jain
2023-03-27  9:53 ` [PATCH 2/4] btrfs: opencode check_barrier_error() Anand Jain
2023-03-27  9:53 ` [PATCH 3/4] Btrfs: change wait_dev_flush() return type to bool Anand Jain
2023-03-27 17:11   ` David Sterba
2023-03-28  2:58     ` Anand Jain
2023-03-27 23:52   ` kernel test robot
2023-03-28  5:31   ` [PATCH] fixup: Btrfs: change wait_dev_flush() return type to bool v2 Anand Jain
2023-03-28 18:28     ` David Sterba
2023-03-27  9:53 ` [PATCH 4/4] btrfs: use test_and_clear_bit() in wait_dev_flush() Anand Jain
2023-03-27 17:14   ` David Sterba
2023-03-28  5:05     ` Anand Jain
2023-03-28 18:33       ` David Sterba

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).