public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: Brijesh Singh <brijesh.singh@amd.com>, edk2-devel@lists.01.org
Cc: Jordan Justen <jordan.l.justen@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: Re: [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address
Date: Tue, 22 Aug 2017 18:28:02 +0200	[thread overview]
Message-ID: <f7736294-0368-cddc-3fcd-de76cae5650e@redhat.com> (raw)
In-Reply-To: <fbd66529-3163-8085-8f8c-bb215ef2b83d@amd.com>

On 08/22/17 17:44, Brijesh Singh wrote:
>
>
> On 08/21/2017 09:05 AM, Laszlo Ersek wrote:
>
> [...]
>
>>
>>>     for (Index = 0; Index < RNGValueLength; Index++) {
>>>       RNGValue[Index] = Buffer[Index];
>>>     }
>>>     Status = EFI_SUCCESS;
>>>   +  //
>>> +  // Buffer is already Unmaped(), goto free it.
>>> +  //
>>> +  goto FreeBuffer;
>>
>> (6) We restrict "goto" statements to error handling:
>>
>> https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/5_source_files/57_c_programming.html
>>
>>
>>> 5.7.3.8 Goto Statements should not be used (in general)
>>> [...]
>>> It is common to use goto for error handling and thus, exiting a
>>> routine in an error case is the only legal use of a goto. [...]
>>
>> So please open-code the FreePool() call and the "return" statement
>> here.
>>
>
> I was wondering if something like this is acceptable ? Actually since
> we need to handle the Unmap due to error from VirtioFlush hence I was
> trying to minimize the adding new state variables or additional checks
> inside the for loop.
>
> @@ -178,17 +194,34 @@ VirtioRngGetRNG (
>      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
>          EFI_SUCCESS) {
>        Status = EFI_DEVICE_ERROR;
> -      goto FreeBuffer;
> +      goto UnmapBuffer;
>      }
>      ASSERT (Len > 0);
>      ASSERT (Len <= BufferSize);
>    }
>
> +  //
> +  // Unmap the device buffer before accessing it.
> +  //
> +  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBuffer;
> +  }
> +
>    for (Index = 0; Index < RNGValueLength; Index++) {
>      RNGValue[Index] = Buffer[Index];
>    }
>    Status = EFI_SUCCESS;
>
> +UnmapBuffer:
> +  //
> +  // If we are reached here due to the error then unmap the buffer
> otherwise
> +  // the buffer is already unmapped after VirtioFlush().
> +  //
> +  if (EFI_ERROR (Status)) {
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +  }
> +
>  FreeBuffer:
>    FreePool ((VOID *)Buffer);
>    return Status;
>

This is perfectly fine, as long as it doesn't get overly complex. It
keeps goto's limited to cascading error handling, only part of the error
handling becomes optional if the ownership of Mapping has been
transferred before.

In functions where you have a simple mapping, this doesn't look
difficult, but more care might be required for functions where you have
several mappings (some of which could be optional, dependent on input
parameters or other conditions). IMO, the pattern should work
nonetheless:

>   if (InputCondition1) {
>     Status = Map (&Mapping1);
>     if (EFI_ERROR (Status)) {
>       goto FreeBuffer;
>     }
>   }
>
>   if (InputCondition2) {
>     Status = Map (&Mapping2);
>     if (EFI_ERROR (Status)) {
>       goto Unmap1;
>     }
>   }
>
>   if (InputCondition3) {
>     Status = Map (&Mapping3);
>     if (EFI_ERROR (Status)) {
>       goto Unmap2;
>     }
>   }
>
>   Status = DoSomethingElse ();
>   if (EFI_ERROR (Status)) {
>     goto Unmap3;
>   }
>
>   //
>   // Now unmap stuff for processing results.
>   //
>
>   if (InputCondition3) {
>     Status = Unmap (Mapping3);
>     if (EFI_ERROR (Status)) {
>       goto Unmap2;
>     }
>   }
>
>   if (InputCondition2) {
>     Status = Unmap (Mapping2);
>     if (EFI_ERROR (Status)) {
>       goto Unmap1;
>     }
>   }
>
>   if (InputCondition1) {
>     Status = Unmap (Mapping1);
>     if (EFI_ERROR (Status)) {
>       goto FreeBuffer;
>     }
>   }
>
>   //
>   // Process results.
>   //
>   ...
>
>   Status = EFI_SUCCESS;
>
> Unmap3:
>   if (EFI_ERROR (Status) && InputCondition3) {
>     Unmap (Mapping3);
>   }
>
> Unmap2:
>   if (EFI_ERROR (Status) && InputCondition2) {
>     Unmap (Mapping2);
>   }
>
> Unmap1:
>   if (EFI_ERROR (Status) && InputCondition1) {
>     Unmap (Mapping1);
>   }
>
> FreeBuffer:
>   //
>   // some rollback action that has to be performed unconditionally on
>   // exit
>   //
>   ...
>
>   return Status;

This needs no additional state variables. The depth of the successful
map/unmap sequence is captured with the goto statements and the labels.
And, on the exit path, unmapping of each mapping depends on two
conditions: the exit path being taken due to success or error, and on
the given mapping being relevant in the first place.

Thanks,
Laszlo


  reply	other threads:[~2017-08-22 16:25 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
2017-08-16  0:34   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: " Brijesh Singh
2017-08-16  0:36   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration Brijesh Singh
2017-08-16  0:36   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
2017-08-16  0:37   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style Brijesh Singh
2017-08-16  0:41   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL Brijesh Singh
2017-08-16 14:37   ` Laszlo Ersek
2017-08-16 15:58     ` Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions Brijesh Singh
2017-08-16 14:59   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
2017-08-16 15:32   ` Laszlo Ersek
2017-08-16 15:53     ` Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
2017-08-16 15:58   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function Brijesh Singh
2017-08-16 16:47   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit Brijesh Singh
2017-08-16 16:53   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING Brijesh Singh
2017-08-16 20:56   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress() Brijesh Singh
2017-08-16 21:43   ` Laszlo Ersek
2017-08-16 21:51     ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset Brijesh Singh
2017-08-16 21:57   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages() Brijesh Singh
2017-08-16 22:18   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address Brijesh Singh
2017-08-21 14:05   ` Laszlo Ersek
2017-08-22 15:44     ` Brijesh Singh
2017-08-22 16:28       ` Laszlo Ersek [this message]
2017-08-14 11:36 ` [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: " Brijesh Singh
2017-08-21 15:24   ` Laszlo Ersek
2017-08-22  1:42     ` Brijesh Singh
     [not found]       ` <1387174d-0040-0072-5e36-c133fd7ec934@redhat.com>
2017-08-22 14:29         ` Brijesh Singh
2017-08-22 15:53           ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
2017-08-21 19:08   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 19/23] OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage() Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 20/23] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages() Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 21/23] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 22/23] OvmfPkg/VirtioNetDxe: map transmit buffer host address to device address Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit Brijesh Singh
2017-08-21 15:40   ` Laszlo Ersek

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-list 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=f7736294-0368-cddc-3fcd-de76cae5650e@redhat.com \
    --to=devel@edk2.groups.io \
    /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