From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
To: Niklas Cassel <Niklas.Cassel@wdc.com>
Cc: "linux-scsi@vger.kernel.org" <linux-scsi@vger.kernel.org>,
"Martin K . Petersen" <martin.petersen@oracle.com>,
Douglas Gilbert <dgilbert@interlog.com>
Subject: Re: [PATCH] scsi: scsi_debug: fix zone transition to full condition
Date: Tue, 7 Jun 2022 18:40:14 +0900 [thread overview]
Message-ID: <65a28eb4-31ea-486b-2f77-a7d11418169c@opensource.wdc.com> (raw)
In-Reply-To: <Yp8cRb77m3f7zZTH@x1-carbon>
On 6/7/22 18:37, Niklas Cassel wrote:
> On Tue, Jun 07, 2022 at 06:25:45PM +0900, Damien Le Moal wrote:
>> On 6/7/22 18:16, Niklas Cassel wrote:
>>> On Tue, Jun 07, 2022 at 10:49:42AM +0900, Damien Le Moal wrote:
>>>> When a write command to a sequential write required or sequential write
>>>> preferred zone result in the zone write pointer reaching the end of the
>>>> zone, the zone condition must be set to full AND the number of
>>>> implicitly or explicitly open zones updated to have a correct accounting
>>>> for zone resources. However, the function zbc_inc_wp() only sets the
>>>> zone condition to full without updating the open zone counters,
>>>> resulting in a zone state machine breakage.
>>>>
>>>> Factor out the correct code from zbc_finish_zone() to transition a zone
>>>> to the full condition and introduce the helper zbc_set_zone_full(). Use
>>>> this helper in zbc_finish_zone() and zbc_inc_wp() to correctly
>>>> transition zones to the full condition.
>>>>
>>>> Fixes: 0d1cf9378bd4 ("scsi: scsi_debug: Add ZBC zone commands")
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
>>>> ---
>>>> drivers/scsi/scsi_debug.c | 27 +++++++++++++++++----------
>>>> 1 file changed, 17 insertions(+), 10 deletions(-)
>>>>
>>>> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
>>>> index 1f423f723d06..6c2bb02a42d8 100644
>>>> --- a/drivers/scsi/scsi_debug.c
>>>> +++ b/drivers/scsi/scsi_debug.c
>>>> @@ -2826,6 +2826,19 @@ static void zbc_open_zone(struct sdebug_dev_info *devip,
>>>> }
>>>> }
>>>>
>>>> +static inline void zbc_set_zone_full(struct sdebug_dev_info *devip,
>>>> + struct sdeb_zone_state *zsp)
>>>> +{
>>>> + enum sdebug_z_cond zc = zsp->z_cond;
>>>> +
>>>> + if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)
>>>> + zbc_close_zone(devip, zsp);
>>>> + if (zsp->z_cond == ZC4_CLOSED)
>>>> + devip->nr_closed--;
>>>> + zsp->z_wp = zsp->z_start + zsp->z_size;
>>>> + zsp->z_cond = ZC5_FULL;
>>>> +}
>>>> +
>>>> static void zbc_inc_wp(struct sdebug_dev_info *devip,
>>>> unsigned long long lba, unsigned int num)
>>>> {
>>>> @@ -2838,7 +2851,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
>>>> if (zsp->z_type == ZBC_ZTYPE_SWR) {
>>>> zsp->z_wp += num;
>>>> if (zsp->z_wp >= zend)
>>>> - zsp->z_cond = ZC5_FULL;
>>>> + zbc_set_zone_full(devip, zsp);
>>>> return;
>>>> }
>>>>
>>>> @@ -2857,7 +2870,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
>>>> n = num;
>>>> }
>>>> if (zsp->z_wp >= zend)
>>>> - zsp->z_cond = ZC5_FULL;
>>>> + zbc_set_zone_full(devip, zsp);
>>>
>>> Hello Damien,
>>>
>>> In the equivalent function (null_zone_write()) in null_blk,
>>> we instead do this:
>>>
>>> if (zone->wp == zone->start + zone->capacity) {
>>> null_lock_zone_res(dev);
>>> if (zone->cond == BLK_ZONE_COND_EXP_OPEN)
>>> dev->nr_zones_exp_open--;
>>> else if (zone->cond == BLK_ZONE_COND_IMP_OPEN)
>>> dev->nr_zones_imp_open--;
>>> zone->cond = BLK_ZONE_COND_FULL;
>>> null_unlock_zone_res(dev);
>>> }
>>>
>>> Isn't it more clear to do the same here?
>>> i.e. set the state to FULL, like before, and simply decrease the
>>> imp/exp open counters.
>>>
>>> zbc_set_zone_full() does some things that are not applicable in
>>> the write path, specifically this:
>>>> + if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)
>>>> + zbc_close_zone(devip, zsp);
>>>> + if (zsp->z_cond == ZC4_CLOSED)
>>>> + devip->nr_closed--;
>>>
>>> e.g. with this new helper, if we are in e.g. IMP OPEN, we will now
>>> set the zone state first to CLOSED, increase the nr_closed counter,
>>> decrease the nr_closed counter, and then set the zone state to FULL.
>>
>> Yes. I am aware of this. It is indeed a bit inefficient, but this makes for
>> a simple bug fix by covering all call sites (finish and write). If you look
>> at zbc_rwp_zone() for zone reset, something similar end up being done, the
>> closed condition is used as an intermediate one. So that one should be
>> cleaned up too.
>>
>> We should improve this, but I think this should be done in a followup
>> patch(es) and I prefer to keep this bug fix patch small.
>> Unless you insist :)
>
> I just saw that zbc_rwp_zone() does the same after sending my email.
>
> I also saw that zbc_close_zone() does a:
>
> if (!zbc_zone_is_seq(zsp))
> return;
>
> (Although I don't see a similar check in zbc_finish_zone())
>
> So one has to ensure that both SWR and SWP are still handled correctly
> when doing this cleanup, so considering that this fix solves the problem,
> it is probably better to leave the cleanup to remove the extra (and at
> least in my opinion, confusing) state transition in a follow up series.
>
> Therefore:
> Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
Thanks. Could do a fix like this which avoids the closed intermediate state:
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 1f423f723d06..6ff4e03ad521 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -2826,6 +2826,27 @@ static void zbc_open_zone(struct sdebug_dev_info
*devip,
}
}
+static void zbc_set_zone_full(struct sdebug_dev_info *devip,
+ struct sdeb_zone_state *zsp)
+{
+ switch (zsp->z_cond) {
+ case ZC2_IMPLICIT_OPEN:
+ devip->nr_imp_open--;
+ break;
+ case ZC3_EXPLICIT_OPEN:
+ devip->nr_exp_open--;
+ break;
+ case ZC4_CLOSED:
+ devip->nr_closed--;
+ break;
+ default:
+ break;
+ }
+
+ zsp->z_wp = zsp->z_start + zsp->z_size;
+ zsp->z_cond = ZC5_FULL;
+}
+
static void zbc_inc_wp(struct sdebug_dev_info *devip,
unsigned long long lba, unsigned int num)
{
@@ -2838,7 +2859,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
if (zsp->z_type == ZBC_ZTYPE_SWR) {
zsp->z_wp += num;
if (zsp->z_wp >= zend)
- zsp->z_cond = ZC5_FULL;
+ zbc_set_zone_full(devip, zsp);
return;
}
@@ -2857,7 +2878,7 @@ static void zbc_inc_wp(struct sdebug_dev_info *devip,
n = num;
}
if (zsp->z_wp >= zend)
- zsp->z_cond = ZC5_FULL;
+ zbc_set_zone_full(devip, zsp);
num -= n;
lba += n;
@@ -4731,14 +4752,8 @@ static void zbc_finish_zone(struct
sdebug_dev_info *devip,
enum sdebug_z_cond zc = zsp->z_cond;
if (zc == ZC4_CLOSED || zc == ZC2_IMPLICIT_OPEN ||
- zc == ZC3_EXPLICIT_OPEN || (empty && zc == ZC1_EMPTY)) {
- if (zc == ZC2_IMPLICIT_OPEN || zc == ZC3_EXPLICIT_OPEN)
- zbc_close_zone(devip, zsp);
- if (zsp->z_cond == ZC4_CLOSED)
- devip->nr_closed--;
- zsp->z_wp = zsp->z_start + zsp->z_size;
- zsp->z_cond = ZC5_FULL;
- }
+ zc == ZC3_EXPLICIT_OPEN || (empty && zc == ZC1_EMPTY))
+ zbc_set_zone_full(devip, zsp);
}
static void zbc_finish_all(struct sdebug_dev_info *devip)
Can send a v2 with that. Tested. It works fine too.
--
Damien Le Moal
Western Digital Research
next prev parent reply other threads:[~2022-06-07 9:53 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-07 1:49 [PATCH] scsi: scsi_debug: fix zone transition to full condition Damien Le Moal
2022-06-07 9:16 ` Niklas Cassel
2022-06-07 9:25 ` Damien Le Moal
2022-06-07 9:37 ` Niklas Cassel
2022-06-07 9:40 ` Damien Le Moal [this message]
2022-06-07 10:05 ` Niklas Cassel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=65a28eb4-31ea-486b-2f77-a7d11418169c@opensource.wdc.com \
--to=damien.lemoal@opensource.wdc.com \
--cc=Niklas.Cassel@wdc.com \
--cc=dgilbert@interlog.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox