From: Matan Barak <matanb-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
To: Yann Droneaud <ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
Cc: Roland Dreier <roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org>,
Igor Ivanov <Igor.Ivanov-wN0M4riKYwLQT0dZR+AlfA@public.gmane.org>,
Hadar Hen Zion <hadarh-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>,
Or Gerlitz <ogerlitz-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>,
linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v2 4/4] IB/core: extended command: add a common extended response header
Date: Tue, 8 Oct 2013 14:58:52 +0300 [thread overview]
Message-ID: <5253F37C.90508@mellanox.com> (raw)
In-Reply-To: <9e111d8215c1fd86b75db17f2c890f0f28e0d076.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
On 7/10/2013 11:49 PM, Yann Droneaud wrote:
> This patch introduces a common response header for extended commands.
>
> This common header is designed to hold
> - the returned comp_mask,
> - the response sizes from core/ (eg. uverbs) and hw/ (eg. provider).
>
> This header is part of the core response buffer, consuming 8 bytes,
> so response buffer should be at least large enough to hold it.
>
> To make the behavior consistent between command and response,
> the command header is taken in account while checking command size,
> just like it was for current commands.
>
> In order to be able to report the size of the response from core/
> and hw/, UDATA structures passed to handler functions are updated
> each time space is used response buffer.
> To report the comp_mask of the response, a pointer to comp_mask is
> given as an input/output parameter of handler functions.
>
> This provide a common framework to handle comp_mask for all extend
> responses, additionally having the response buffer size would help
> userspace to better handle extended response.
>
> The new layout for command and response buffer is:
>
> - command:
>
> +----------------------------------------+
> | flags | 00 00 | command |
> | in_words | out_words |
> +----------------------------------------+
> | response |
> | response |
> | provider_in_words | provider_out_words |
> | comp_mask |
> +----------------------------------------+
> | |
> . <uverbs input> .
> . (in_words * 8) .
> . - sizeof(hdr) - sizeof(ex_hdr) .
> | |
> +----------------------------------------+
> | |
> . <provider input> .
> . (provider_in_words * 8) .
> | |
> +----------------------------------------+
>
> - response, if present:
>
> +----------------------------------------+
> | <extended |
> | response header> |
> +----------------------------------------+
> | |
> . <uverbs output space> .
> . (out_words * 8) .
> . - sizeof(ex_resp) .
> | |
> +----------------------------------------+
> | |
> . <provider output space> .
> . (provider_out_words * 8) .
> | |
> +----------------------------------------+
>
> For a successful command, the response buffer will be
> presented with an updated header:
>
> +----------------------------------------+
> | comp_mask |
> | out_words | provider_out_words |
> +----------------------------------------+
> | |
> . <uverbs output> .
> . (out_words * 8) .
> . - sizeof(ex_resp) .
> | |
> +----------------------------------------+
> | |
> . <provider output> .
> . (provider_out_words * 8) .
> | |
> +----------------------------------------+
>
> The most notable drawbacks of this approach are:
> - increase in complexity,
> - inability to handle error gracefully when writing the response header.
>
> Cc: Igor Ivanov <Igor.Ivanov-wN0M4riKYwLQT0dZR+AlfA@public.gmane.org>
> Cc: Matan Barak <matanb-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Yann Droneaud <ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
> Link: http://marc.info/?i=cover.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org
> Link: http://mid.gmane.org/cover.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org
> ---
> drivers/infiniband/core/uverbs.h | 2 +-
> drivers/infiniband/core/uverbs_cmd.c | 17 +++++++----
> drivers/infiniband/core/uverbs_main.c | 54 +++++++++++++++++++++++++++++------
> include/rdma/ib_verbs.h | 22 ++++++++++++++
> include/uapi/rdma/ib_user_verbs.h | 8 +++++-
> 5 files changed, 87 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
> index 03f6a0a..a1df33f 100644
> --- a/drivers/infiniband/core/uverbs.h
> +++ b/drivers/infiniband/core/uverbs.h
> @@ -230,7 +230,7 @@ IB_UVERBS_DECLARE_CMD(close_xrcd);
> int ib_uverbs_ex_##name(struct ib_uverbs_file *file, \
> struct ib_udata *ucore, \
> struct ib_udata *uhw, \
> - __u32 comp_mask)
> + __u32 *comp_mask)
>
> IB_UVERBS_DECLARE_EX_CMD(create_flow);
> IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
> diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
> index 3b09f1d..3d2f0ad 100644
> --- a/drivers/infiniband/core/uverbs_cmd.c
> +++ b/drivers/infiniband/core/uverbs_cmd.c
> @@ -2634,7 +2634,7 @@ static int kern_spec_to_ib_spec(struct ib_kern_spec *kern_spec,
> int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> struct ib_udata *ucore,
> struct ib_udata *uhw,
> - __u32 comp_mask)
> + __u32 *comp_mask)
> {
> struct ib_uverbs_create_flow cmd;
> struct ib_uverbs_create_flow_resp resp;
> @@ -2649,7 +2649,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> int i;
> int kern_attr_size;
>
> - if (comp_mask)
> + if (*comp_mask)
> return -EINVAL;
>
> if (ucore->inlen != sizeof(cmd))
> @@ -2662,8 +2662,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> if (err)
> return err;
>
> - ucore->inbuf += sizeof(cmd);
> - ucore->inlen -= sizeof(cmd);
> + ib_udata_consume_in(ucore, sizeof(cmd));
>
> if ((cmd.flow_attr.type == IB_FLOW_ATTR_SNIFFER &&
> !capable(CAP_NET_ADMIN)) || !capable(CAP_NET_RAW))
> @@ -2693,6 +2692,7 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> err = -EFAULT;
> goto err_free_attr;
> }
> + ib_udata_consume_in(ucore, kern_attr_size);
> } else {
> kern_flow_attr = &cmd.flow_attr;
> kern_attr_size = sizeof(cmd.flow_attr);
> @@ -2763,6 +2763,8 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> if (err)
> goto err_copy;
>
> + ib_udata_consume_out(ucore, sizeof(resp));
> +
> put_qp_read(qp);
> mutex_lock(&file->mutex);
> list_add_tail(&uobj->list, &file->ucontext->rule_list);
> @@ -2774,6 +2776,9 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
> kfree(flow_attr);
> if (cmd.flow_attr.num_of_specs)
> kfree(kern_flow_attr);
> +
> + *comp_mask = 0;
> +
> return 0;
> err_copy:
> idr_remove_uobj(&ib_uverbs_rule_idr, uobj);
> @@ -2794,14 +2799,14 @@ err_free_attr:
> int ib_uverbs_ex_destroy_flow(struct ib_uverbs_file *file,
> struct ib_udata *ucore,
> struct ib_udata *uhw,
> - __u32 comp_mask)
> + __u32 *comp_mask)
> {
> struct ib_uverbs_destroy_flow cmd;
> struct ib_flow *flow_id;
> struct ib_uobject *uobj;
> int ret;
>
> - if (comp_mask)
> + if (*comp_mask)
> return -EINVAL;
>
> if (ucore->inlen != sizeof(cmd))
> diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
> index a9687dd..12b44a2 100644
> --- a/drivers/infiniband/core/uverbs_main.c
> +++ b/drivers/infiniband/core/uverbs_main.c
> @@ -120,7 +120,7 @@ static ssize_t (*uverbs_cmd_table[])(struct ib_uverbs_file *file,
> static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
> struct ib_udata *ucore,
> struct ib_udata *uhw,
> - __u32 comp_mask) = {
> + __u32 *comp_mask) = {
> [IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
> [IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow
> };
> @@ -636,8 +636,13 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
> __u32 command;
>
> struct ib_uverbs_ex_cmd_hdr ex_hdr;
> + struct ib_uverbs_ex_resp_hdr ex_resp;
> struct ib_udata ucore;
> struct ib_udata uhw;
> + unsigned long response;
> + size_t ucore_outlen = 0;
> + size_t uhw_outlen = 0;
> + __u32 comp_mask;
> int err;
>
> if (hdr.command & ~(__u32)(IB_USER_VERBS_CMD_FLAGS_MASK |
> @@ -662,13 +667,12 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
> if (copy_from_user(&ex_hdr, buf + sizeof(hdr), sizeof(ex_hdr)))
> return -EFAULT;
>
> - count -= sizeof(hdr) + sizeof(ex_hdr);
> - buf += sizeof(hdr) + sizeof(ex_hdr);
> -
> if ((hdr.in_words + ex_hdr.provider_in_words) * 8 != count)
> return -EINVAL;
>
> - if (ex_hdr.response) {
> + response = (unsigned long)ex_hdr.response;
> +
> + if (response) {
> if (!hdr.out_words && !ex_hdr.provider_out_words)
> return -EINVAL;
> } else {
> @@ -678,24 +682,58 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
>
> INIT_UDATA(&ucore,
> (hdr.in_words) ? buf : 0,
> - (unsigned long)ex_hdr.response,
> + response,
> hdr.in_words * 8,
> hdr.out_words * 8);
>
> + ib_udata_consume_in(&ucore, sizeof(hdr) + sizeof(ex_hdr));
> +
> + if (response) {
> +
> + ucore_outlen = ucore.outlen; /* keep in mind total available len
> + (including response header size) */
> +
> + err = ib_udata_consume_out(&ucore, sizeof(ex_resp));
> + if (err)
> + return err;
> +
> + /* fail early to not have to recover from invalid response buffer */
> + memset(&ex_resp, 0, sizeof(ex_resp));
> + if (copy_to_user((void __user *)response,
> + &ex_resp, sizeof(ex_resp)))
> + return -EFAULT;
> + }
> +
> INIT_UDATA(&uhw,
> (ex_hdr.provider_in_words) ? buf + ucore.inlen : 0,
> - (ex_hdr.provider_out_words) ? (unsigned long)ex_hdr.response + ucore.outlen : 0,
> + (ex_hdr.provider_out_words) ? response + ucore.outlen : 0,
> ex_hdr.provider_in_words * 8,
> ex_hdr.provider_out_words * 8);
>
> + if (response)
> + uhw_outlen = uhw.outlen;
> +
> + comp_mask = ex_hdr.comp_mask;
> +
> err = uverbs_ex_cmd_table[command](file,
> &ucore,
> &uhw,
> - ex_hdr.comp_mask);
> + &comp_mask);
>
> if (err)
> return err;
>
> + if (response) {
> +
> + ex_resp.comp_mask = comp_mask;
> + ex_resp.out_words = (ucore_outlen - ucore.outlen) / 8;
> + ex_resp.provider_out_words = (uhw_outlen - uhw.outlen) / 8;
> +
> + if (copy_to_user((void __user *)response,
> + &ex_resp, sizeof(ex_resp)))
> + return -EFAULT;
> + }
> +
> return count;
> }
>
> diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
> index a06fc12..9dd7dad 100644
> --- a/include/rdma/ib_verbs.h
> +++ b/include/rdma/ib_verbs.h
> @@ -1478,6 +1478,28 @@ static inline int ib_copy_to_udata(struct ib_udata *udata, void *src, size_t len
> return copy_to_user(udata->outbuf, src, len) ? -EFAULT : 0;
> }
>
> +static inline int ib_udata_consume_in(struct ib_udata *udata, size_t len)
> +{
> + if (udata->inlen < len)
> + return -EINVAL;
> +
> + udata->inlen -= len;
> + udata->inbuf += len;
> +
> + return 0;
> +}
> +
> +static inline int ib_udata_consume_out(struct ib_udata *udata, size_t len)
> +{
> + if (udata->outlen < len)
> + return -ENOSPC;
> +
> + udata->outlen -= len;
> + udata->outbuf += len;
> +
> + return 0;
> +}
> +
> /**
> * ib_modify_qp_is_ok - Check that the supplied attribute mask
> * contains all required attributes and no attributes not allowed for
> diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
> index 13b3008..0da06d0 100644
> --- a/include/uapi/rdma/ib_user_verbs.h
> +++ b/include/uapi/rdma/ib_user_verbs.h
> @@ -142,6 +142,12 @@ struct ib_uverbs_ex_cmd_hdr {
> __u32 comp_mask;
> };
>
> +struct ib_uverbs_ex_resp_hdr {
> + __u32 comp_mask;
> + __u16 out_words;
> + __u16 provider_out_words;
> +};
> +
> struct ib_uverbs_get_context {
> __u64 response;
> __u64 driver_data[0];
> @@ -778,8 +784,8 @@ struct ib_uverbs_create_flow {
> };
>
> struct ib_uverbs_create_flow_resp {
> - __u32 comp_mask;
> __u32 flow_handle;
> + __u32 reserved;
> };
>
> struct ib_uverbs_destroy_flow {
>
Hi
Nice work on the patches.
Regarding the last patch, you are right that it simplifies things for
creating new uverbs where command parts are in-lined one after another,
but the infrastructure got a bit more complex.
If we're going to this direction, I think the we should also deal with
the problem of extending one of the command parts. Currently, we'll have
to put a comp_mask in the in-lined command part, consume this command
part and then continue with the other parts. It might be better than
using a pointer, but this put the burden of serializing the command
buffer into the kernel structures onto the uverb command writer.
We might want to avoid this.
Furthermore, the comp_mask of the command is different than the
comp_mask of the response. Therefore, I don't think we should pass the
command's comp_mask to the uverb as a pointer, but just pass a pointer
to value 0 that the uverb will set.
Regards,
Matan
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2013-10-08 11:58 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-07 20:49 [PATCH v2 0/4] IB/core: an improved infrastructure for uverbs commands Yann Droneaud
[not found] ` <cover.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
2013-10-07 20:49 ` [PATCH v2 1/4] IB/core: extended command: " Yann Droneaud
[not found] ` <70486466a70aae3e3facf5a12c1d0bb960a9a462.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
2013-10-09 11:38 ` Or Gerlitz
[not found] ` <5255402F.4000806-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2013-10-09 12:42 ` Yann Droneaud
2013-10-07 20:49 ` [PATCH v2 2/4] IB/core: extended command: move comp_mask to the extended header Yann Droneaud
2013-10-07 20:49 ` [PATCH v2 3/4] IB/core: extended command: enforce command size Yann Droneaud
2013-10-07 20:49 ` [PATCH v2 4/4] IB/core: extended command: add a common extended response header Yann Droneaud
[not found] ` <9e111d8215c1fd86b75db17f2c890f0f28e0d076.1381177342.git.ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org>
2013-10-08 11:58 ` Matan Barak [this message]
[not found] ` <5253F37C.90508-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2013-10-09 10:30 ` Or Gerlitz
[not found] ` <52553050.8050501-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2013-10-09 11:29 ` Yann Droneaud
[not found] ` <0d695256ac989e7b1bcccd3a2bfafcbf-zgzEX58YAwA@public.gmane.org>
2013-10-09 11:33 ` Or Gerlitz
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=5253F37C.90508@mellanox.com \
--to=matanb-vpraknaxozvwk0htik3j/w@public.gmane.org \
--cc=Igor.Ivanov-wN0M4riKYwLQT0dZR+AlfA@public.gmane.org \
--cc=hadarh-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org \
--cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=ogerlitz-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org \
--cc=roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org \
--cc=ydroneaud-RlY5vtjFyJ3QT0dZR+AlfA@public.gmane.org \
/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;
as well as URLs for NNTP newsgroup(s).