mmc: block: Add new ioctl to send multi commands
PATCH 1/1 mmc: block: Add new ioctl to send multi commands
From: Seshagiri Holi <[email protected]>
Certain eMMC devices allow vendor specific device information to be read via a sequence of vendor commands. These vendor commands must be issued in sequence and an atomic fashion. One way to support this would be to add an ioctl function for sending a sequence of commands to the device atomically as proposed here. These multi commands are simple array of the existing mmc_ioc_cmd structure.
[ [email protected]: Rebased on linux-next from v3.18. Changed
userspace pointer type for multi command to be a u64. Renamed from combo commands to multi commands. Updated patch based upon feedback review comments received. Updated commit message ]
--- drivers/mmc/card/block.c | 198 ++++++++++++++++++++++++++++++++--------- include/uapi/linux/mmc/ioctl.h | 17 +++- 2 files changed, 170 insertions(+), 45 deletions(-)
drivers/mmc/card/block.c +154 -44
@@ -387,6 +387,24 @@ out:return ERR_PTR (err); } +static int mmc_blk_ioctl_copy_to_user (struct mmc_ioc_cmd __user *ic_ptr, +struct mmc_blk_ioc_data *idata) +{ +struct mmc_ioc_cmd *ic = &idata->ic; + +if (copy_to_user (&(ic_ptr->response), ic->response, +sizeof (ic->response))) +return -EFAULT ; + +if (!idata->ic.write_flag) { +if (copy_to_user ((void __user *)(unsigned long )ic->data_ptr, + idata->buf, idata->buf_bytes)) +return -EFAULT ; + } + +return 0 ; +} +static int ioctl_rpmb_card_status_poll (struct mmc_card *card,u32 *status,u32 retries_max) {
@@ -447,12 +465,9 @@ out:return err; } -static int mmc_blk_ioctl_cmd (struct block_device *bdev, -struct mmc_ioc_cmd __user *ic_ptr) +static int __mmc_blk_ioctl_cmd (struct mmc_card *card,struct mmc_blk_data *md, +struct mmc_blk_ioc_data *idata) { -struct mmc_blk_ioc_data *idata; -struct mmc_blk_data *md; -struct mmc_card *card;struct mmc_command cmd = {0 };struct mmc_data data = {0 };struct mmc_request mrq = {NULL };
@@ -461,33 +476,12 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,int is_rpmb = false;u32 status =0 ; -/* -* The caller must have CAP_SYS_RAWIO, and must be calling this on the -* whole block device, not on a partition. This prevents overspray -* between sibling partitions. -*/ -if ((!capable (CAP_SYS_RAWIO )) || (bdev != bdev->bd_contains)) -return -EPERM ; - - idata =mmc_blk_ioctl_copy_from_user (ic_ptr); -if (IS_ERR (idata)) -return PTR_ERR (idata); - - md =mmc_blk_get (bdev->bd_disk); -if (!md) { - err = -EINVAL ; - goto cmd_err; - } +if (!card || !md || !idata) +return -EINVAL ;if (md->area_type &MMC_BLK_DATA_AREA_RPMB ) is_rpmb = true; - card = md->queue.card; -if (IS_ERR (card)) { - err =PTR_ERR (card); - goto cmd_done; - } - cmd.opcode = idata->ic.opcode; cmd.arg = idata->ic.arg; cmd.flags = idata->ic.flags;
@@ -582,18 +576,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,if (idata->ic.postsleep_min_us)usleep_range (idata->ic.postsleep_min_us, idata->ic.postsleep_max_us); -if (copy_to_user (&(ic_ptr->response), cmd.resp,sizeof (cmd.resp))) { - err = -EFAULT ; - goto cmd_rel_host; - } - -if (!idata->ic.write_flag) { -if (copy_to_user ((void __user *)(unsigned long ) idata->ic.data_ptr, - idata->buf, idata->buf_bytes)) { - err = -EFAULT ; - goto cmd_rel_host; - } - } +memcpy (&(idata->ic.response), cmd.resp,sizeof (cmd.resp));if (is_rpmb) {/*
@@ -609,6 +592,46 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev, cmd_rel_host:mmc_put_card (card); +return err; +} + +static int mmc_blk_ioctl_cmd (struct block_device *bdev, +struct mmc_ioc_cmd __user *ic_ptr) +{ +struct mmc_blk_ioc_data *idata; +struct mmc_blk_data *md; +struct mmc_card *card; +int err; + +/* +* The caller must have CAP_SYS_RAWIO, and must be calling this on the +* whole block device, not on a partition. This prevents overspray +* between sibling partitions. +*/ +if ((!capable (CAP_SYS_RAWIO )) || (bdev != bdev->bd_contains)) +return -EPERM ; + + idata =mmc_blk_ioctl_copy_from_user (ic_ptr); +if (IS_ERR (idata)) +return PTR_ERR (idata); + + md =mmc_blk_get (bdev->bd_disk); +if (!md) { + err = -EINVAL ; + goto cmd_err; + } + + card = md->queue.card; +if (IS_ERR (card)) { + err =PTR_ERR (card); + goto cmd_done; + } + + err =__mmc_blk_ioctl_cmd (card, md, idata); +if (err) + goto cmd_done; + + err =mmc_blk_ioctl_copy_to_user (ic_ptr, idata); cmd_done:mmc_blk_put (md);
@@ -618,13 +641,100 @@ cmd_err:return err; } +static int mmc_blk_ioctl_multi_cmd (struct block_device *bdev, +struct mmc_ioc_multi_cmd __user *user) +{ +struct mmc_ioc_multi_cmd mcci = {0 }; +struct mmc_blk_ioc_data **idata =NULL ; +struct mmc_ioc_cmd __user *cmds; +struct mmc_card *card; +struct mmc_blk_data *md; +int i, err = -EFAULT ; +u8 n_cmds =0 ; + +/* +* The caller must have CAP_SYS_RAWIO, and must be calling this on the +* whole block device, not on a partition. This prevents overspray +* between sibling partitions. +*/ +if ((!capable (CAP_SYS_RAWIO )) || (bdev != bdev->bd_contains)) +return -EPERM ; + +if (copy_from_user (&mcci, user,sizeof (struct mmc_ioc_multi_cmd ))) +return -EFAULT ; + +if (!mcci.num_of_cmds) { + err = -EINVAL ; + goto cmd_err; + } + + idata =kcalloc (mcci.num_of_cmds,sizeof (*idata),GFP_KERNEL ); +if (!idata) { + err = -ENOMEM ; + goto cmd_err; + } + + cmds = (struct mmc_ioc_cmd __user *)(unsigned long )mcci.cmds_ptr; +for (n_cmds =0 ; n_cmds < mcci.num_of_cmds; n_cmds++) { + idata[n_cmds] =mmc_blk_ioctl_copy_from_user (&cmds[n_cmds]); +if (IS_ERR (idata[n_cmds])) { + err =PTR_ERR (idata[n_cmds]); + goto cmd_err; + } + } + + md =mmc_blk_get (bdev->bd_disk); +if (!md) + goto cmd_err; + + card = md->queue.card; +if (IS_ERR (card)) { + err =PTR_ERR (card); + goto cmd_done; + } + +mmc_get_card (card); +for (i =0 ; i < n_cmds; i++) { + err =__mmc_blk_ioctl_cmd (card, md, idata[i]); +if (err) { +mmc_release_host (card->host); + goto cmd_done; + } + } + +mmc_put_card (card); + +/* copy to user if data and response */ +for (i =0 ; i < n_cmds; i++) { + err =mmc_blk_ioctl_copy_to_user (&cmds[i], idata[i]); +if (err) +break ; + } + +cmd_done: +mmc_blk_put (md); +cmd_err: +for (i =0 ; i < n_cmds; i++) { +kfree (idata[i]->buf); +kfree (idata[i]); + } +kfree (idata); +return err; +} +static int mmc_blk_ioctl (struct block_device *bdev,fmode_t mode,unsigned int cmd,unsigned long arg) { -int ret = -EINVAL ; -if (cmd ==MMC_IOC_CMD ) - ret =mmc_blk_ioctl_cmd (bdev, (struct mmc_ioc_cmd __user *)arg); -return ret; +switch (cmd) { +case MMC_IOC_CMD : +return mmc_blk_ioctl_cmd (bdev, + (struct mmc_ioc_cmd __user *)arg); +case MMC_IOC_MULTI_CMD : +return mmc_blk_ioctl_multi_cmd (bdev, + (struct mmc_ioc_multi_cmd __user *)arg); +default : +return -EINVAL ; + } }#ifdef CONFIG_COMPAT
include/uapi/linux/mmc/ioctl.h +16 -1
@@ -45,8 +45,23 @@ struct mmc_ioc_cmd { };#define mmc_ioc_cmd_set_data (ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr -#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) +/** +* struct mmc_ioc_multi_cmd - multi command information +* @cmds_ptr: Address of the location where the list of commands resides +* @num_of_cmds: number of commands to send +*/ +struct mmc_ioc_multi_cmd { +__u64 cmds_ptr; +uint8_t num_of_cmds; +}; +#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) +/* +* MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by +* the structure mmc_ioc_multi_cmd. The MMC driver will issue all +* commands in array in sequence to card. +*/ +#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd)/* * Since this ioctl is only meant to enhance (and not replace) normal access * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES
Signature · 1 line
2.1.4
Quoted 6 lines · On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
drivers/mmc/card/block.c +6
-0+ + idata =kcalloc (mcci.num_of_cmds,sizeof (*idata),GFP_KERNEL ); +if (!idata) { + err = -ENOMEM ; + goto cmd_err; + }
drivers/mmc/card/block.c cmd_err: · line 685
Quoted 10 lines
drivers/mmc/card/block.c +10
-0+ + cmds = (struct mmc_ioc_cmd __user *)(unsigned long )mcci.cmds_ptr; +for (n_cmds =0 ; n_cmds < mcci.num_of_cmds; n_cmds++) { + idata[n_cmds] =mmc_blk_ioctl_copy_from_user (&cmds[n_cmds]); +if (IS_ERR (idata[n_cmds])) { + err =PTR_ERR (idata[n_cmds]); + goto cmd_err; + } + } +
You have no upper bound on the number of commands, which means you end up catching overly large arguments only through -ENOMEM. Can you come up with an upper bound that is guaranteed to succeed with the allocation?
Or would it be possible to process the user data one at a time while going through the commands?
include/uapi/linux/mmc/ioctl.h struct mmc_ioc_cmd { · line 56
Quoted 4 lines
include/uapi/linux/mmc/ioctl.h +4
-0+struct mmc_ioc_multi_cmd { +__u64 cmds_ptr; +uint8_t num_of_cmds; +};
complex commands are always nasty in one way or another. Can you describe in the patch description why you picked an indirect pointer over something like
struct mmc_ioc_multi_cmd {
__u64 num_of_cmds;
struct mmc_ioc_cmd cmds[0];
};as I said, both are ugly. My first choice would have been the other one, but I'm sure you have some reasons yourself.
Arnd
Quoted 13 lines · Arnd Bergmann
Quoted 12 lines · On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
drivers/mmc/card/block.c +12
-0+ + idata =kcalloc (mcci.num_of_cmds,sizeof (*idata),GFP_KERNEL ); +if (!idata) { + err = -ENOMEM ; + goto cmd_err; + } + + cmds = (struct mmc_ioc_cmd __user *)(unsigned long )mcci.cmds_ptr; +for (n_cmds =0 ; n_cmds < mcci.num_of_cmds; n_cmds++) { + idata[n_cmds] =mmc_blk_ioctl_copy_from_user (&cmds[n_cmds]); +if (IS_ERR (idata[n_cmds])) { + err =PTR_ERR (idata[n_cmds]);
Quoted 8 lines
drivers/mmc/card/block.c static int mmc_blk_ioctl_cmd(struct block_device *bdev, · line 629
Quoted 4 lines
drivers/mmc/card/block.c +4
-0+ goto cmd_err; + } + } +You have no upper bound on the number of commands, which means you end up catching overly large arguments only through
-ENOMEM. Can you come up with an upper bound that is guaranteed to succeed with the allocation?
The uint8 type would limit you to 256 commands (if you have the memory), although admittedly that is probably overkill.
Quoted 2 lines
Or would it be possible to process the user data one at a time while going through the commands?
Yes, I think that could be a good option, I will take a look.
Quoted 9 lines
include/uapi/linux/mmc/ioctl.h struct mmc_ioc_cmd { · line 56
Quoted 4 lines
include/uapi/linux/mmc/ioctl.h +4
-0+struct mmc_ioc_multi_cmd { +__u64 cmds_ptr; +uint8_t num_of_cmds; +};complex commands are always nasty in one way or another. Can you describe in the patch description why you picked an indirect pointer over something like
Quoted 7 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };as I said, both are ugly. My first choice would have been the other one, but I'm sure you have some reasons yourself.
It was a suggestion from Olof to ensure the structure size is constant for both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a macro similar to the below for this?
#define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long) ptr
However, yes can update the changelog.
Cheers
Jon
Quoted 24 lines · On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
Quoted 13 lines · Arnd Bergmann
Quoted 12 lines · On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
drivers/mmc/card/block.c +12
-0+ + idata =kcalloc (mcci.num_of_cmds,sizeof (*idata),GFP_KERNEL ); +if (!idata) { + err = -ENOMEM ; + goto cmd_err; + } + + cmds = (struct mmc_ioc_cmd __user *)(unsigned long )mcci.cmds_ptr; +for (n_cmds =0 ; n_cmds < mcci.num_of_cmds; n_cmds++) { + idata[n_cmds] =mmc_blk_ioctl_copy_from_user (&cmds[n_cmds]); +if (IS_ERR (idata[n_cmds])) { + err =PTR_ERR (idata[n_cmds]);Quoted 8 lines
drivers/mmc/card/block.c static int mmc_blk_ioctl_cmd(struct block_device *bdev, · line 629
Quoted 4 lines
drivers/mmc/card/block.c +4
-0+ goto cmd_err; + } + } +You have no upper bound on the number of commands, which means you end up catching overly large arguments only through
-ENOMEM. Can you come up with an upper bound that is guaranteed to succeed with the allocation?
Quoted 2 lines
The uint8 type would limit you to 256 commands (if you have the memory), although admittedly that is probably overkill.
Good point.
Please note a few details here:
- in uabi headers, we need to use __u8 instead of uint8, because we cannot rely on libc header file inclusion for kernel headers.
- you have some implicit padding after the structure and should replace that with explictit pad bytes to extend the structure to a multiple of its alignment (8 bytes).
Quoted 17 lines
Quoted 9 lines
include/uapi/linux/mmc/ioctl.h struct mmc_ioc_cmd { · line 56
Quoted 4 lines
include/uapi/linux/mmc/ioctl.h +4
-0+struct mmc_ioc_multi_cmd { +__u64 cmds_ptr; +uint8_t num_of_cmds; +};complex commands are always nasty in one way or another. Can you describe in the patch description why you picked an indirect pointer over something like
Quoted 7 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };as I said, both are ugly. My first choice would have been the other one, but I'm sure you have some reasons yourself.
Quoted 7 lines
It was a suggestion from Olof to ensure the structure size is constant for both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a macro similar to the below for this?
#define
mmc_ioc_cmd_set_data(ic, ptr)ic.data_ptr = (__u64)(unsigned long) ptrHowever, yes can update the changelog.
I was not referring to the use of an __u64 variable to pass a pointer, that is expected (and the macro would make it harder to understand).
What I meant instead was the use of a pointer to an array as opposed to passing the array itself. With the definition I gave above, the size would still be the same on all architectures (you can replace the __u64 with an __u8 plus padding if you like), as sizeof(struct mmc_ioc_multi_cmd) is just '8' here.
Alternatively, you could just use an array of struct mmc_ioc_cmd by itself and encode the length in the ioctl command:
#define MMC_COMBO_IOC_CMD(n) _IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))
This is of course also ugly because the ioctl command number is not fixed, and because the limit for the number of mmc command blocks is architecture dependent, depending on the definition of the _IOC macro that can have either 13 or 14 bits to encode the argument length in bytes.
Arnd
Hi Arnd,
Quoted 28 lines · Arnd Bergmann
Quoted 24 lines · On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
Quoted 13 lines · Arnd Bergmann
Quoted 12 lines · On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
drivers/mmc/card/block.c +12
-0+ + idata =kcalloc (mcci.num_of_cmds,sizeof (*idata),GFP_KERNEL ); +if (!idata) { + err = -ENOMEM ; + goto cmd_err; + } + + cmds = (struct mmc_ioc_cmd __user *)(unsigned long )mcci.cmds_ptr; +for (n_cmds =0 ; n_cmds < mcci.num_of_cmds; n_cmds++) { + idata[n_cmds] =mmc_blk_ioctl_copy_from_user (&cmds[n_cmds]); +if (IS_ERR (idata[n_cmds])) { + err =PTR_ERR (idata[n_cmds]);Quoted 8 lines
drivers/mmc/card/block.c static int mmc_blk_ioctl_cmd(struct block_device *bdev, · line 629
Quoted 4 lines
drivers/mmc/card/block.c +4
-0+ goto cmd_err; + } + } +You have no upper bound on the number of commands, which means you end up catching overly large arguments only through
-ENOMEM. Can you come up with an upper bound that is guaranteed to succeed with the allocation?Quoted 2 lines
The uint8 type would limit you to 256 commands (if you have the memory), although admittedly that is probably overkill.
Quoted 6 lines
Good point.
Please note a few details here:
- in uabi headers, we need to use
__u8instead of uint8, because we cannot rely on libc header file inclusion for kernel headers.
Ok.
Quoted 3 lines
- you have some implicit padding after the structure and should replace that with explictit pad bytes to extend the structure to a multiple of its alignment (8 bytes).
Would padding with __u32 at the end be sufficient here? I assume the __u32 would be 32-bit aligned. However, was not sure if this would always be the case.
Quoted 25 lines
Quoted 17 lines
Quoted 9 lines
include/uapi/linux/mmc/ioctl.h struct mmc_ioc_cmd { · line 56
Quoted 4 lines
include/uapi/linux/mmc/ioctl.h +4
-0+struct mmc_ioc_multi_cmd { +__u64 cmds_ptr; +uint8_t num_of_cmds; +};complex commands are always nasty in one way or another. Can you describe in the patch description why you picked an indirect pointer over something like
Quoted 7 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };as I said, both are ugly. My first choice would have been the other one, but I'm sure you have some reasons yourself.
Quoted 7 lines
It was a suggestion from Olof to ensure the structure size is constant for both 32-bit and 64-bit userspaces. I am not sure if it is worth adding a macro similar to the below for this?
#define
mmc_ioc_cmd_set_data(ic, ptr)ic.data_ptr = (__u64)(unsigned long) ptrHowever, yes can update the changelog.
Quoted 8 lines
I was not referring to the use of an
__u64variable to pass a pointer, that is expected (and the macro would make it harder to understand).What I meant instead was the use of a pointer to an array as opposed to passing the array itself. With the definition I gave above, the size would still be the same on all architectures (you can replace the
__u64with an__u8plus padding if you like), assizeof(struct mmc_ioc_multi_cmd)is just '8' here.
Do you have any strong preference here? I guess I don't and agree neither are ideal.
Quoted 10 lines
Alternatively, you could just use an array of struct
mmc_ioc_cmdby itself and encode the length in the ioctl command:#define
MMC_COMBO_IOC_CMD(n)_IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))This is of course also ugly because the ioctl command number is not fixed, and because the limit for the number of mmc command blocks is architecture dependent, depending on the definition of the
_IOCmacro that can have either 13 or 14 bits to encode the argument length in bytes.
Interesting idea. However, given your comments above, I think that I would rather place the size in the structure.
Cheers
Jon
Quoted 5 lines · On Thursday 10 September 2015 09:24:19 Jon Hunter wrote:
Quoted 3 lines · Arnd Bergmann
Quoted 2 lines · On Wednesday 09 September 2015 17:44:54 Jon Hunter wrote:
Quoted 1 line · Arnd Bergmann
On Wednesday 09 September 2015 16:06:01 Jon Hunter wrote:
Quoted 7 lines
Quoted 3 lines
- you have some implicit padding after the structure and should replace that with explictit pad bytes to extend the structure to a multiple of its alignment (8 bytes).
Would padding with
__u32at the end be sufficient here? I assume the__u32would be 32-bit aligned. However, was not sure if this would always be the case.
If you have a layout of
__u64 pointer; __u8 size; __u32 pad;
you still get three bytes of implied padding between size and pad. It's better to just have '__u8 __pad[7]' in that case.
Quoted 17 lines
Quoted 8 lines
I was not referring to the use of an
__u64variable to pass a pointer, that is expected (and the macro would make it harder to understand).What I meant instead was the use of a pointer to an array as opposed to passing the array itself. With the definition I gave above, the size would still be the same on all architectures (you can replace the
__u64with an__u8plus padding if you like), assizeof(struct mmc_ioc_multi_cmd)is just '8' here.Do you have any strong preference here? I guess I don't and agree neither are ideal.
Quoted 5 lines
Alternatively, you could just use an array of struct
mmc_ioc_cmdby itself and encode the length in the ioctl command:#define
MMC_COMBO_IOC_CMD(n)_IOC(_IOC_READ|_IOC_WRITE, 1, sizeof(struct mmc_ioc_cmd) * (n))
Quoted 8 lines
Quoted 5 lines
This is of course also ugly because the ioctl command number is not fixed, and because the limit for the number of mmc command blocks is architecture dependent, depending on the definition of the
_IOCmacro that can have either 13 or 14 bits to encode the argument length in bytes.Interesting idea. However, given your comments above, I think that I would rather place the size in the structure.
I don't have a strong preference here. If there is a slight chance that you might need more than ((1<<13) / sizeof(struct mmc_ioc_cmd)) mmc commands in one ioctl, you can rule out that last solution.
If you can prove that this length would always be sufficient, I'd probably pick that approach. Otherwise, I'd pick the one the size followed by an an open array.
Arnd
On Thu, Sep 10, 2015 at 1:24 AM, Jon Hunter <[email protected]> wrote:
...
Quoted 7 lines
Quoted 3 lines
- you have some implicit padding after the structure and should replace that with explictit pad bytes to extend the structure to a multiple of its alignment (8 bytes).
Would padding with
__u32at the end be sufficient here? I assume the__u32would be 32-bit aligned. However, was not sure if this would always be the case.
Is there something wrong with implicit padding?
Only one copy of the structure is passed to the kernel for any given call.
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };
I think this would work just as well. But doesn't "pointer to an array" require 32-bit ioctl compat handling?
We were trying to avoid a 32-bit user space compatibility handler.
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
as I said, both are ugly. My first choice would have been the other one, but I'm sure you have some reasons yourself.
Why do you prefer the alternative you proposed?
My guess is better type checking (and I would like that too). But maybe there is something else?
cheers,
grant
Quoted 13 lines · Grant Grundler
On Thu, Sep 10, 2015 at 1:24 AM, Jon Hunter <[email protected]> wrote:
...Quoted 7 lines
Quoted 3 lines
- you have some implicit padding after the structure and should replace that with explictit pad bytes to extend the structure to a multiple of its alignment (8 bytes).
Would padding with
__u32at the end be sufficient here? I assume the__u32would be 32-bit aligned. However, was not sure if this would always be the case.Is there something wrong with implicit padding?
Only one copy of the structure is passed to the kernel for any given call.
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };I think this would work just as well. But doesn't "pointer to an array" require 32-bit ioctl compat handling?
We were trying to avoid a 32-bit user space compatibility handler.
I think that this is fine as it is a zero length array [0] and not a pointer.
Cheers
Jon
Quoted 2 lines · Jon Hunter
On 10/09/15 18:10, Grant Grundler wrote:
...
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
struct mmc_ioc_multi_cmd { __u64 num_of_cmds; struct mmc_ioc_cmd cmds[0]; };I think this would work just as well. But doesn't "pointer to an array" require 32-bit ioctl compat handling?
We were trying to avoid a 32-bit user space compatibility handler.I think that this is fine as it is a zero length array [0] and not a pointer.
Doh, yes. Thanks for correcting. I knew this was a gcc special but forgot it's not actually allocating any space.
cheers,
grant
Quoted 5 lines
Cheers
Jon