All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eran Ben Elisha <eranbe@mellanox.com>
To: Jiri Pirko <jiri@resnulli.us>
Cc: "netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	Jiri Pirko <jiri@mellanox.com>,
	"David S. Miller" <davem@davemloft.net>,
	Saeed Mahameed <saeedm@mellanox.com>,
	Moshe Shemesh <moshe@mellanox.com>,
	Wei Yongjun <weiyongjun1@huawei.com>
Subject: Re: [PATCH net-next 1/7] devlink: Add devlink msg API
Date: Thu, 24 Jan 2019 07:31:33 +0000	[thread overview]
Message-ID: <2d891be2-7c5a-55ae-9cb8-71922444acb1@mellanox.com> (raw)
In-Reply-To: <20190123143120.GF2191@nanopsycho>



On 1/23/2019 4:31 PM, Jiri Pirko wrote:
> Tue, Jan 22, 2019 at 04:57:18PM CET, eranbe@mellanox.com wrote:
>> Devlink msg is a mechanism to pass descriptors between drivers and
>> devlink, in json-like format. The API allows the driver to add objects,
>> object pair, value array (nested attributes), value and name.
>>
>> Driver can use this API to fill the msg context in a format which can be
>> translated by the devlink to the netlink message later.
>>
>> With this API, driver does not need to declare the total size per message
>> context, and it dynamically add more messages to the context (bounded by
>> the system memory limitation only).
>> There is an implicit request to have the preliminary main objects size
>> created via this API to be upper bounded by netlink SKB size, as those
>> objects do not get fragmented between different SKBs when passed to the
>> netlink layer.
>>
>> Devlink msg will replace devlink buffers for health reporters. Devlink
>> buffers which will be deprecated and removed in the downstream patch.
>>
>> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
>> CC: Wei Yongjun <weiyongjun1@huawei.com>
>> Reviewed-by: Moshe Shemesh <moshe@mellanox.com>
>> ---
>> include/net/devlink.h        |  70 ++++++
>> include/uapi/linux/devlink.h |   8 +
>> net/core/devlink.c           | 455 +++++++++++++++++++++++++++++++++++
>> 3 files changed, 533 insertions(+)
>>
>> diff --git a/include/net/devlink.h b/include/net/devlink.h
>> index a81a1b7a67d7..fe323e9b14e1 100644
>> --- a/include/net/devlink.h
>> +++ b/include/net/devlink.h
>> @@ -424,6 +424,7 @@ struct devlink_region;
>>
>> typedef void devlink_snapshot_data_dest_t(const void *data);
>>
>> +struct devlink_msg_ctx;
>> struct devlink_health_buffer;
>> struct devlink_health_reporter;
>>
>> @@ -615,6 +616,21 @@ int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
>> 				   u8 *data, u32 snapshot_id,
>> 				   devlink_snapshot_data_dest_t *data_destructor);
>>
>> +int devlink_msg_nest_start(struct devlink_msg_ctx *msg_ctx, int attrtype);
> 
> 
> devlink_msg_*() functions should work with struct devlink_msg.
> devlink_msg_ctx*() functions should work with struct devlink_msg_ctx.
> Please be consistent with the naming.
> 
> I think you can call this just "struct devlink_msg" of maybe "fmsg" as
> for "formatted message" - so it is not confused with any other devlink
> netlink message.

Ack.

> 
> 
> 
>> +int devlink_msg_nest_end(struct devlink_msg_ctx *msg_ctx);
>> +int devlink_msg_put_value(struct devlink_msg_ctx *msg_ctx,
>> +			  void *value, u16 value_len, u8 value_nla_type);
>> +int devlink_msg_put_name(struct devlink_msg_ctx *msg_ctx,
>> +			 char *name);
>> +int devlink_msg_put_name_value_pair(struct devlink_msg_ctx *msg_ctx,
>> +				    char *name, void *value, u16 value_len,
>> +				    u8 value_nla_type);
>> +int devlink_msg_put_name_value_array(struct devlink_msg_ctx *msg_ctx,
>> +				     char *name, void **value, u16 *value_len,
>> +				     u8 *value_nla_type, int array_size);
>> +int devlink_msg_object_start(struct devlink_msg_ctx *msg_ctx, char *name);
>> +int devlink_msg_object_end(struct devlink_msg_ctx *msg_ctx, char *name);
>> +
>> int devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer,
>> 				     int attrtype);
>> void devlink_health_buffer_nest_end(struct devlink_health_buffer *buffer);
>> @@ -903,6 +919,60 @@ devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
>> 	return 0;
>> }
>>
>> +static inline int
>> +devlink_msg_nest_start(struct devlink_msg_ctx *msg_ctx, int attrtype)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_nest_end(struct devlink_msg_ctx *msg_ctx)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_put_value(struct devlink_msg_ctx *msg_ctx,
>> +		      void *value, u16 value_len, u8 value_nla_type)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_put_name(struct devlink_msg_ctx *msg_ctx,
>> +		     char *name)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_put_name_value_pair(struct devlink_msg_ctx *msg_ctx,
>> +				char *name, void *value, u16 value_len,
>> +				u8 value_nla_type)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_put_name_value_array(struct devlink_msg_ctx *msg_ctx,
>> +				 char *name, void **value, u16 *value_len,
>> +				 u8 *value_nla_type, int array_size)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_object_start(struct devlink_msg_ctx *msg_ctx, char *name)
>> +{
>> +	return 0;
>> +}
>> +
>> +static inline int
>> +devlink_msg_object_end(struct devlink_msg_ctx *msg_ctx, char *name)
>> +{
>> +	return 0;
>> +}
>> +
>> static inline int
>> devlink_health_buffer_nest_start(struct devlink_health_buffer *buffer,
>> 				 int attrtype)
>> diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
>> index 6b26bb2ce4dc..68eeda1d0455 100644
>> --- a/include/uapi/linux/devlink.h
>> +++ b/include/uapi/linux/devlink.h
>> @@ -300,6 +300,14 @@ enum devlink_attr {
>> 	DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_TYPE,	/* u8 */
>> 	DEVLINK_ATTR_HEALTH_BUFFER_OBJECT_VALUE_DATA,	/* dynamic */
>>
>> +	DEVLINK_ATTR_MSG_OBJECT,		/* nested */
>> +	DEVLINK_ATTR_MSG_OBJECT_PAIR,		/* nested */
>> +	DEVLINK_ATTR_MSG_OBJECT_NAME,		/* string */
>> +	DEVLINK_ATTR_MSG_OBJECT_VALUE,		/* nested */
>> +	DEVLINK_ATTR_MSG_OBJECT_VALUE_ARRAY,	/* nested */
>> +	DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,	/* u8 */
>> +	DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,	/* dynamic */
>> +
>> 	DEVLINK_ATTR_HEALTH_REPORTER,			/* nested */
>> 	DEVLINK_ATTR_HEALTH_REPORTER_NAME,		/* string */
>> 	DEVLINK_ATTR_HEALTH_REPORTER_STATE,		/* u8 */
>> diff --git a/net/core/devlink.c b/net/core/devlink.c
>> index 60248a53c0ad..57ca096849b3 100644
>> --- a/net/core/devlink.c
>> +++ b/net/core/devlink.c
>> @@ -4098,6 +4098,461 @@ devlink_health_buffer_snd(struct genl_info *info,
>> 	return err;
>> }
>>
>> +struct devlink_msg {
> 
> Let's call this "struct devlink_msg_item"

Ack.

> 
> 
>> +	struct list_head list;
>> +	int attrtype;
>> +	u8 nla_type;
>> +	u16 len;
>> +	int value[0];
>> +};
>> +
>> +struct devlink_msg_ctx {
>> +	struct list_head msg_list;
>> +	int max_nested_depth;
>> +	int curr_nest;
>> +};
>> +
>> +#define DEVLINK_MSG_MAX_SIZE (4096 - GENL_HDRLEN)
>> +
>> +static struct devlink_msg_ctx *devlink_msg_ctx_alloc(void)
>> +{
>> +	struct devlink_msg_ctx *msg_ctx;
>> +
>> +	msg_ctx = kzalloc(sizeof(*msg_ctx), GFP_KERNEL);
>> +	if (!msg_ctx)
>> +		return ERR_PTR(-ENOMEM);
>> +
>> +	INIT_LIST_HEAD(&msg_ctx->msg_list);
>> +
>> +	return msg_ctx;
>> +}
>> +
>> +static void devlink_msg_ctx_free(struct devlink_msg_ctx *msg_ctx)
>> +{
>> +	struct devlink_msg *msg, *tm;
>> +
>> +	list_for_each_entry_safe(msg, tm, &msg_ctx->msg_list, list) {
>> +		list_del(&msg->list);
>> +		kfree(msg);
>> +	}
>> +	kfree(msg_ctx);
>> +}
>> +
>> +int devlink_msg_nest_start(struct devlink_msg_ctx *msg_ctx, int attrtype)
>> +{
>> +	struct devlink_msg *nest_msg;
>> +
>> +	if (attrtype != DEVLINK_ATTR_MSG_OBJECT &&
>> +	    attrtype != DEVLINK_ATTR_MSG_OBJECT_PAIR &&
>> +	    attrtype != DEVLINK_ATTR_MSG_OBJECT_VALUE &&
>> +	    attrtype != DEVLINK_ATTR_MSG_OBJECT_VALUE_ARRAY)
>> +		return -EINVAL;
>> +
>> +	nest_msg = kzalloc(sizeof(*nest_msg), GFP_KERNEL);
>> +	if (!nest_msg)
>> +		return -ENOMEM;
>> +
>> +	nest_msg->attrtype = attrtype;
>> +	msg_ctx->curr_nest++;
>> +	msg_ctx->max_nested_depth = max(msg_ctx->max_nested_depth,
>> +					msg_ctx->curr_nest);
>> +	list_add_tail(&nest_msg->list, &msg_ctx->msg_list);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_nest_start);
>> +
>> +int devlink_msg_nest_end(struct devlink_msg_ctx *msg_ctx)
>> +{
>> +	struct devlink_msg *nest_msg;
>> +
>> +	WARN_ON(!msg_ctx->curr_nest);
>> +	nest_msg = kzalloc(sizeof(*nest_msg), GFP_KERNEL);
>> +	if (!nest_msg)
>> +		return -ENOMEM;
>> +
>> +	msg_ctx->curr_nest--;
>> +	list_add_tail(&nest_msg->list, &msg_ctx->msg_list);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_nest_end);
>> +
>> +int devlink_msg_put_value(struct devlink_msg_ctx *msg_ctx,
>> +			  void *value, u16 value_len, u8 value_nla_type)
>> +{
>> +	struct devlink_msg *value_msg;
>> +
>> +	if (value_len > DEVLINK_MSG_MAX_SIZE)
>> +		return -EMSGSIZE;
>> +
>> +	if (value_nla_type != NLA_U8 &&
>> +	    value_nla_type != NLA_U32 &&
>> +	    value_nla_type != NLA_U64 &&
>> +	    value_nla_type != NLA_NUL_STRING &&
>> +	    value_nla_type != NLA_BINARY)
>> +		return -EINVAL;
>> +
>> +	value_msg = kzalloc(sizeof(*value_msg) + value_len, GFP_KERNEL);
> 
> Looks fine.
> 
> 
>> +	if (!value_msg)
>> +		return -ENOMEM;
>> +
>> +	value_msg->nla_type = value_nla_type;
>> +	value_msg->len = value_len;
>> +	value_msg->attrtype = DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA;
>> +	memcpy(&value_msg->value, value, value_len);
>> +	list_add_tail(&value_msg->list, &msg_ctx->msg_list);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_put_value);
>> +
>> +int devlink_msg_put_name(struct devlink_msg_ctx *msg_ctx, char *name)
>> +{
>> +	struct devlink_msg *name_msg;
>> +
>> +	if (strlen(name) + 1 > DEVLINK_MSG_MAX_SIZE)
>> +		return -EMSGSIZE;
>> +
>> +	name_msg = kzalloc(sizeof(*name_msg) + strlen(name) + 1, GFP_KERNEL);
>> +	if (!name_msg)
>> +		return -ENOMEM;
>> +
>> +	name_msg->nla_type = NLA_NUL_STRING;
>> +	name_msg->len = strlen(name) + 1;
>> +	name_msg->attrtype = DEVLINK_ATTR_MSG_OBJECT_NAME;
>> +	memcpy(&name_msg->value, name, name_msg->len);
>> +	list_add_tail(&name_msg->list, &msg_ctx->msg_list);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_put_name);
>> +
>> +int devlink_msg_put_name_value_pair(struct devlink_msg_ctx *msg_ctx,
>> +				    char *name, void *value, u16 value_len,
>> +				    u8 value_nla_type)
>> +{
>> +	int err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_PAIR);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_put_name(msg_ctx, name);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_VALUE);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_put_value(msg_ctx, value, value_len, value_nla_type);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx);
>> +	if (err)
>> +		return err;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_put_name_value_pair);
>> +
>> +int devlink_msg_put_name_value_array(struct devlink_msg_ctx *msg_ctx,
>> +				     char *name, void **value, u16 *value_len,
>> +				     u8 *value_nla_type, int array_size)
> 
> This is limitting the arrays to plain values. One should be able to nest
> objects inside. If fact, that is what you can to do with sqs:
> 
> object start
>    name sqs
>    array start
>      object start
>        index 0
>        xxx yyy
>      object end
>      object start
>        index 1
>        xxx yyy
>      object end
>    array end
> object end
> 
> So you need to have:
> devlink_msg_put_array_start()
> devlink_msg_put_array_end()

Sounds good, will do.

> 
> 
>> +{
>> +	int err, i;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_PAIR);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_put_name(msg_ctx, name);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_VALUE);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx,
>> +				     DEVLINK_ATTR_MSG_OBJECT_VALUE_ARRAY);
>> +	if (err)
>> +		return err;
>> +
>> +	for (i = 0; i < array_size; i++) {
>> +		err = devlink_msg_nest_start(msg_ctx,
>> +					     DEVLINK_ATTR_MSG_OBJECT_VALUE);
>> +		if (err)
>> +			return err;
>> +
>> +		err = devlink_msg_put_value(msg_ctx, value[i],
>> +					    value_len[i], value_nla_type[i]);
>> +		if (err)
>> +			return err;
>> +		err = devlink_msg_nest_end(msg_ctx);
>> +		if (err)
>> +			return err;
>> +	}
>> +
>> +	err = devlink_msg_nest_end(msg_ctx);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx);
>> +	if (err)
>> +		return err;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_put_name_value_array);
>> +
>> +int devlink_msg_object_start(struct devlink_msg_ctx *msg_ctx, char *name)
>> +{
>> +	int err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT);
>> +	if (err)
>> +		return err;
>> +
>> +	if (!name)
>> +		return 0;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_PAIR);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_put_name(msg_ctx, name);
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_start(msg_ctx, DEVLINK_ATTR_MSG_OBJECT_VALUE);
>> +	if (err)
>> +		return err;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_object_start);
>> +
>> +int devlink_msg_object_end(struct devlink_msg_ctx *msg_ctx, char *name)
>> +{
>> +	int err;
>> +
>> +	if (!name)
>> +		goto end_object;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx); /* DEVLINK_ATTR_MSG_OBJECT_VALUE */
>> +	if (err)
>> +		return err;
>> +
>> +	err = devlink_msg_nest_end(msg_ctx); /* DEVLINK_ATTR_MSG_OBJECT_PAIR */
>> +	if (err)
>> +		return err;
>> +
>> +end_object:
>> +	err = devlink_msg_nest_end(msg_ctx); /* DEVLINK_ATTR_MSG_OBJECT */
>> +	if (err)
>> +		return err;
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(devlink_msg_object_end);
>> +
>> +static int
>> +devlink_msg_fill_data(struct sk_buff *skb, struct devlink_msg *msg)
>> +{
>> +	int err;
>> +
>> +	switch (msg->nla_type) {
>> +	case NLA_U8:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,
>> +				 *(u8 *)msg->value);
>> +		break;
>> +	case NLA_U32:
>> +		err = nla_put_u32(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,
>> +				  *(u32 *)msg->value);
>> +		break;
>> +	case NLA_U64:
>> +		err = nla_put_u64_64bit(skb,
>> +					DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,
>> +					*(u64 *)msg->value, DEVLINK_ATTR_PAD);
>> +		break;
>> +	case NLA_NUL_STRING:
>> +		err = nla_put_string(skb,
>> +				     DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,
>> +				     (char *)&msg->value);
>> +		break;
>> +	case NLA_BINARY:
>> +		err = nla_put(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA,
>> +			      msg->len, (void *)&msg->value);
>> +		break;
>> +	default:
>> +		err = -EINVAL;
>> +		break;
>> +	}
>> +
>> +	return err;
>> +}
>> +
>> +static int
>> +devlink_msg_fill_type(struct sk_buff *skb, struct devlink_msg *msg)
>> +{
>> +	int err;
>> +
>> +	switch (msg->nla_type) {
>> +	case NLA_U8:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,
>> +				 NLA_U8);
>> +		break;
>> +	case NLA_U32:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,
>> +				 NLA_U32);
>> +		break;
>> +	case NLA_U64:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,
>> +				 NLA_U64);
>> +		break;
>> +	case NLA_NUL_STRING:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,
>> +				 NLA_NUL_STRING);
>> +		break;
>> +	case NLA_BINARY:
>> +		err = nla_put_u8(skb, DEVLINK_ATTR_MSG_OBJECT_VALUE_TYPE,
>> +				 NLA_BINARY);
>> +		break;
>> +	default:
>> +		err = -EINVAL;
>> +		break;
>> +	}
>> +
>> +	return err;
>> +}
>> +
>> +static int
>> +devlink_msg_prepare_skb(struct sk_buff *skb, struct devlink_msg_ctx *msg_ctx,
>> +			int *start)
>> +{
>> +	struct nlattr **nlattr_arr;
>> +	struct devlink_msg *msg;
>> +	int j = 0, i = 0;
>> +	int err;
>> +
>> +	nlattr_arr = kcalloc(msg_ctx->max_nested_depth,
>> +			     sizeof(*nlattr_arr), GFP_KERNEL);
>> +	if (!nlattr_arr)
>> +		return -EINVAL;
>> +
>> +	list_for_each_entry(msg, &msg_ctx->msg_list, list) {
>> +		if (j < *start) {
>> +			j++;
>> +			continue;
>> +		}
>> +
>> +		switch (msg->attrtype) {
>> +		case DEVLINK_ATTR_MSG_OBJECT:
>> +		case DEVLINK_ATTR_MSG_OBJECT_PAIR:
>> +		case DEVLINK_ATTR_MSG_OBJECT_VALUE:
>> +		case DEVLINK_ATTR_MSG_OBJECT_VALUE_ARRAY:
>> +			nlattr_arr[i] = nla_nest_start(skb, msg->attrtype);
>> +			if (!nlattr_arr[i]) {
>> +				err = -EMSGSIZE;
>> +				goto nla_put_failure;
>> +			}
>> +			i++;
>> +			break;
>> +		case DEVLINK_ATTR_MSG_OBJECT_VALUE_DATA:
>> +			err = devlink_msg_fill_data(skb, msg);
>> +			if (err)
>> +				goto nla_put_failure;
>> +			err = devlink_msg_fill_type(skb, msg);
>> +			if (err)
>> +				goto nla_put_failure;
>> +			break;
>> +		case DEVLINK_ATTR_MSG_OBJECT_NAME:
>> +			err = nla_put_string(skb, msg->attrtype,
>> +					     (char *)&msg->value);
>> +			if (err)
>> +				goto nla_put_failure;
>> +			break;
>> +		default: /* No attrtype */
>> +			nla_nest_end(skb, nlattr_arr[--i]);
>> +			break;
>> +		}
>> +		j++;
>> +		if (!i)
>> +			*start = j;
>> +	}
>> +
>> +	kfree(nlattr_arr);
>> +	return 0;
>> +
>> +nla_put_failure:
>> +	for (j = 0; j < i; j++)
>> +		nla_nest_cancel(skb, nlattr_arr[j]);
>> +	kfree(nlattr_arr);
>> +	return err;
>> +}
>> +
>> +static int devlink_msg_snd(struct genl_info *info,
>> +			   enum devlink_command cmd, int flags,
>> +			   struct devlink_msg_ctx *msg_ctx)
>> +{
>> +	struct sk_buff *skb;
>> +	struct nlmsghdr *nlh;
>> +	int err, index = 0;
>> +	bool last = false;
>> +	void *hdr;
>> +
>> +	while (!last) {
>> +		int tmp_index = index;
>> +
>> +		skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
>> +		if (!skb)
>> +			return -ENOMEM;
>> +
>> +		hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
>> +				  &devlink_nl_family, NLM_F_MULTI, cmd);
>> +		if (!hdr)
>> +			goto nla_put_failure;
>> +
>> +		err = devlink_msg_prepare_skb(skb, msg_ctx, &index);
>> +		if (!err)
>> +			last = true;
>> +		else if (err != -EMSGSIZE || tmp_index == index)
>> +			goto nla_put_failure;
>> +
>> +		genlmsg_end(skb, hdr);
>> +		err = genlmsg_reply(skb, info);
>> +		if (err)
>> +			return err;
> 
> 
> Looks fine.
> 
> 
>> +	}
>> +
>> +	skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
>> +	if (!skb)
>> +		return -ENOMEM;
>> +	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
>> +			NLMSG_DONE, 0, flags | NLM_F_MULTI);
>> +	err = genlmsg_reply(skb, info);
>> +	if (err)
>> +		return err;
>> +
>> +	return 0;
>> +
>> +nla_put_failure:
>> +	err = -EIO;
>> +	nlmsg_free(skb);
>> +	return err;
>> +}
>> +
>> struct devlink_health_reporter {
>> 	struct list_head list;
>> 	struct devlink_health_buffer **dump_buffers_array;
>> -- 
>> 2.17.1
>>

  reply	other threads:[~2019-01-24  7:31 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-22 15:57 [PATCH net-next 0/7] Devlink health updates Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 1/7] devlink: Add devlink msg API Eran Ben Elisha
2019-01-23 14:31   ` Jiri Pirko
2019-01-24  7:31     ` Eran Ben Elisha [this message]
2019-01-22 15:57 ` [PATCH net-next 2/7] net/mlx5e: Move driver to use " Eran Ben Elisha
2019-01-23 14:39   ` Jiri Pirko
2019-01-24  7:39     ` Eran Ben Elisha
2019-01-24  9:08       ` Jiri Pirko
2019-01-24  9:57         ` Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 3/7] devlink: move devlink health reporter " Eran Ben Elisha
2019-01-23 14:42   ` Jiri Pirko
2019-01-24  7:45     ` Eran Ben Elisha
2019-01-24  9:09       ` Jiri Pirko
2019-01-24  9:57         ` Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 4/7] devlink: Delete depracated health buffers API Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 5/7] devlink: Remove spaces around "=" in the logger print Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 6/7] devlink: Fix use-after-free at reporter destroy Eran Ben Elisha
2019-01-22 15:57 ` [PATCH net-next 7/7] net/mlx5e: Add RTNL lock to TX recover flow Eran Ben Elisha
2019-01-22 16:58 ` [PATCH net-next 0/7] Devlink health updates Jiri Pirko
2019-01-25  6:08   ` David Miller
2019-01-25  9:16     ` Eran Ben Elisha
2019-01-25  9:19       ` Jiri Pirko
2019-01-25 18:56       ` David Miller
2019-01-23 11:44 ` Jiri Pirko
2019-01-23 12:34   ` Eran Ben Elisha

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=2d891be2-7c5a-55ae-9cb8-71922444acb1@mellanox.com \
    --to=eranbe@mellanox.com \
    --cc=davem@davemloft.net \
    --cc=jiri@mellanox.com \
    --cc=jiri@resnulli.us \
    --cc=moshe@mellanox.com \
    --cc=netdev@vger.kernel.org \
    --cc=saeedm@mellanox.com \
    --cc=weiyongjun1@huawei.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.