Re: [PATCH][next] scsi: aacraid: Replace one-element array with flexible-array member

From: Gustavo A. R. Silva
Date: Wed Mar 24 2021 - 22:07:58 EST


Hi Martin,

On 3/24/21 20:18, Martin K. Petersen wrote:
>
> Hi Gustavo!
>
> Your changes and the original code do not appear to be functionally
> equivalent.
>
>> @@ -1235,8 +1235,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3
>> if (ret < 0)
>> return ret;
>> command = ContainerRawIo2;
>> - fibsize = sizeof(struct aac_raw_io2) +
>> - ((le32_to_cpu(readcmd2->sgeCnt)-1) * sizeof(struct sge_ieee1212));
>> + fibsize = struct_size(readcmd2, sge,
>> + le32_to_cpu(readcmd2->sgeCnt));
>
> The old code allocated sgeCnt-1 elements (whether that was a mistake or
> not I do not know) whereas the new code would send a larger fib to the
> ASIC. I don't have any aacraid adapters and I am hesitant to merging
> changes that have not been validated on real hardware.

Precisely this sort of confusion is one of the things we want to avoid
by using flexible-array members instead of one-element arrays.

fibsize is actually the same for both the old and the new code. The
difference is that in the original code, the one-element array _sge_
at the bottom of struct aac_raw_io2, contributes to the size of the
structure, as it occupies at least as much space as a single object
of its type. On the other hand, flexible-array members don't contribute
to the size of the enclosing structure. See below...

Old code:

$ pahole -C aac_raw_io2 drivers/scsi/aacraid/aachba.o
struct aac_raw_io2 {
__le32 blockLow; /* 0 4 */
__le32 blockHigh; /* 4 4 */
__le32 byteCount; /* 8 4 */
__le16 cid; /* 12 2 */
__le16 flags; /* 14 2 */
__le32 sgeFirstSize; /* 16 4 */
__le32 sgeNominalSize; /* 20 4 */
u8 sgeCnt; /* 24 1 */
u8 bpTotal; /* 25 1 */
u8 bpComplete; /* 26 1 */
u8 sgeFirstIndex; /* 27 1 */
u8 unused[4]; /* 28 4 */
struct sge_ieee1212 sge[1]; /* 32 16 */

/* size: 48, cachelines: 1, members: 13 */
/* last cacheline: 48 bytes */
};

New code:

$ pahole -C aac_raw_io2 drivers/scsi/aacraid/aachba.o
struct aac_raw_io2 {
__le32 blockLow; /* 0 4 */
__le32 blockHigh; /* 4 4 */
__le32 byteCount; /* 8 4 */
__le16 cid; /* 12 2 */
__le16 flags; /* 14 2 */
__le32 sgeFirstSize; /* 16 4 */
__le32 sgeNominalSize; /* 20 4 */
u8 sgeCnt; /* 24 1 */
u8 bpTotal; /* 25 1 */
u8 bpComplete; /* 26 1 */
u8 sgeFirstIndex; /* 27 1 */
u8 unused[4]; /* 28 4 */
struct sge_ieee1212 sge[]; /* 32 0 */

/* size: 32, cachelines: 1, members: 13 */
/* last cacheline: 32 bytes */
};

So, the old code allocates sgeCnt-1 elements because sizeof(struct aac_raw_io2) is
already counting one element of the _sge_ array.

Please, let me know if this is clear now.

Thanks!
--
Gustavo