From: Caleb Connolly <caleb.connolly@linaro.org>
To: neil.armstrong@linaro.org, Tom Rini <trini@konsulko.com>
Cc: Marek Vasut <marek.vasut+renesas@mailbox.org>,
Quentin Schulz <quentin.schulz@cherry.de>,
u-boot@lists.denx.de, u-boot-qcom@groups.io
Subject: Re: [PATCH 3/3] scsi: sync cache on write
Date: Tue, 25 Mar 2025 18:57:33 +0100 [thread overview]
Message-ID: <d7e2f337-bf71-45cb-b3a3-0ccd8379535b@linaro.org> (raw)
In-Reply-To: <5256bf47-ba7c-4ec8-8757-6d59910176dc@linaro.org>
On 3/25/25 16:18, neil.armstrong@linaro.org wrote:
> On 25/03/2025 14:49, Caleb Connolly wrote:
>>
>>
>> On 3/25/25 14:33, Neil Armstrong wrote:
>>> On 25/03/2025 14:02, Caleb Connolly wrote:
>>>> We don't have a mechanism to safely shutdown block devices prior to a
>>>> baord reset or driver removal. Prevent data loss by synchronizing the
>>>> SCSI cache after every write.
>>>>
>>>> In particular this solves the issue of capsule updates looping on some
>>>> devices because the board resets immediately after deleting the capsule
>>>> file and this write wouldn't be flushed in time.
>>>>
>>>> This may impact NAND wear, but should be negligible given the usecases
>>>> for disk write in U-Boot.
>>>>
>>>> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
>>>> ---
>>>> drivers/scsi/scsi.c | 28 ++++++++++++++++++++++++++++
>>>> 1 file changed, 28 insertions(+)
>>>>
>>>> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
>>>> index
>>>> 1aa7fbdbb5278e387de72a3c3e73d19ea0342fff..1b71e580b89b100395ea132a4976366a713cba8a 100644
>>>> --- a/drivers/scsi/scsi.c
>>>> +++ b/drivers/scsi/scsi.c
>>>> @@ -77,8 +77,25 @@ static void scsi_setup_inquiry(struct scsi_cmd
>>>> *pccb)
>>>> pccb->cmdlen = 6;
>>>> pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
>>>> }
>>>> +static void scsi_setup_sync_cache(struct scsi_cmd *pccb, lbaint_t
>>>> start,
>>>> + unsigned short blocks)
>>>> +{
>>>> + pccb->cmd[0] = SCSI_SYNC_CACHE;
>>>> + pccb->cmd[1] = 0;
>>>> + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff;
>>>> + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff;
>>>> + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff;
>>>> + pccb->cmd[5] = (unsigned char)start & 0xff;
>>>> + pccb->cmd[6] = 0;
>>>> + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff;
>>>> + pccb->cmd[8] = (unsigned char)blocks & 0xff;
>>>> + pccb->cmd[9] = 0;
>>>> + pccb->cmdlen = 10;
>>>> + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */
>>>> +}
>>>> +
>>>> static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t
>>>> start,
>>>> unsigned short blocks)
>>>> {
>>>> pccb->cmd[0] = SCSI_READ10;
>>>> @@ -235,8 +252,19 @@ static ulong scsi_write(struct udevice *dev,
>>>> lbaint_t blknr, lbaint_t blkcnt,
>>>> blkcnt -= blks;
>>>> break;
>>>> }
>>>> + /*
>>>> + * Ensure the writes are flushed to disk so we don't lose data
>>>> + * on board reset.
>>>> + * FIXME: this ought to be in a SCSI shutdown path instead
>>>> + */
>>>> + scsi_setup_sync_cache(pccb, start, smallblks);
>>>
>>> Why can't this be done at the end of scsi_write() ?
>>
>> We have the same limitation that we can only flush SCSI_MAX_BLK blocks
>> at once. It could be done in a second loop at the end but I figured
>> it's more sensible to just interleave them.
>
> Indeed you're right, another solution is to leave count to 0, and it
> will sync all data after start:
> ````
> If the LBA and COUNT arguments are both zero (their defaults) then all
> blocks in the cache are synchronized
> If LBA is greater than zero while COUNT is zero then blocks in the cache
> whose addresses are from and including LBA to the highest lba on the
> device are synchronized.
> ```
>
> And it seems Linux only passes 0 parameters, and just flushes all data
> in cache:
> https://elixir.bootlin.com/linux/v6.13.7/source/drivers/scsi/sd.c#L1145
>
> So either you leave is as is so all data is written as soon as possible,
> or we wait until the end of the write and flush everything.
Ahh, damn I should have checked for that!
>
> I think the last one is just simpler and safer.
You're totally right XD
Thanks
>
> Neil
>
>>>
>>>> + if (scsi_exec(bdev, pccb)) {
>>>> + scsi_print_error(pccb);
>>>> + break;
>>>> + }
>>>> +
>>>> if (blks > max_blks) {
>>>> start += max_blks;
>>>> blks -= max_blks;
>>>> } else {
>>>>
>>>
>>> And perhaps a sync subcommand of the scsi command would be nice to
>>> have !
>>
>> Good idea, that would tie in nicely if/when we get a .sync() op for
>> block devices and call it prior to board reset.
>>>
>>> Neil
>>>
>>
>
--
Caleb (they/them)
prev parent reply other threads:[~2025-03-25 17:57 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-25 13:02 [PATCH 0/3] scsi: ensure writes are flushed to disk Caleb Connolly
2025-03-25 13:02 ` [PATCH 1/3] scsi: fix typo in setup_read_ext() Caleb Connolly
2025-03-25 13:25 ` Neil Armstrong
2025-03-25 13:02 ` [PATCH 2/3] scsi: de-dup calls to scsi_setup_write_ext() Caleb Connolly
2025-03-25 13:38 ` Neil Armstrong
2025-03-25 13:45 ` Caleb Connolly
2025-03-25 13:02 ` [PATCH 3/3] scsi: sync cache on write Caleb Connolly
2025-03-25 13:33 ` Neil Armstrong
2025-03-25 13:49 ` Caleb Connolly
2025-03-25 15:18 ` neil.armstrong
2025-03-25 17:57 ` Caleb Connolly [this message]
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=d7e2f337-bf71-45cb-b3a3-0ccd8379535b@linaro.org \
--to=caleb.connolly@linaro.org \
--cc=marek.vasut+renesas@mailbox.org \
--cc=neil.armstrong@linaro.org \
--cc=quentin.schulz@cherry.de \
--cc=trini@konsulko.com \
--cc=u-boot-qcom@groups.io \
--cc=u-boot@lists.denx.de \
/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