Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'devlink-kernel-region-snapshot-id-allocation'

Jakub Kicinski says:

====================
devlink: kernel region snapshot id allocation

currently users have to find a free snapshot id to pass
to the kernel when they are requesting a snapshot to be
taken.

This set extends the kernel so it can allocate the id
on its own and send it back to user space in a response.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+94 -26
+72 -24
net/core/devlink.c
··· 3716 3716 return err; 3717 3717 } 3718 3718 3719 - static void devlink_nl_region_notify(struct devlink_region *region, 3720 - struct devlink_snapshot *snapshot, 3721 - enum devlink_command cmd) 3719 + static struct sk_buff * 3720 + devlink_nl_region_notify_build(struct devlink_region *region, 3721 + struct devlink_snapshot *snapshot, 3722 + enum devlink_command cmd, u32 portid, u32 seq) 3722 3723 { 3723 3724 struct devlink *devlink = region->devlink; 3724 3725 struct sk_buff *msg; 3725 3726 void *hdr; 3726 3727 int err; 3727 3728 3728 - WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3729 3729 3730 3730 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3731 3731 if (!msg) 3732 - return; 3732 + return ERR_PTR(-ENOMEM); 3733 3733 3734 - hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3735 - if (!hdr) 3734 + hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd); 3735 + if (!hdr) { 3736 + err = -EMSGSIZE; 3736 3737 goto out_free_msg; 3738 + } 3737 3739 3738 3740 err = devlink_nl_put_handle(msg, devlink); 3739 3741 if (err) ··· 3759 3757 } 3760 3758 genlmsg_end(msg, hdr); 3761 3759 3762 - genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3763 - msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3764 - 3765 - return; 3760 + return msg; 3766 3761 3767 3762 out_cancel_msg: 3768 3763 genlmsg_cancel(msg, hdr); 3769 3764 out_free_msg: 3770 3765 nlmsg_free(msg); 3766 + return ERR_PTR(err); 3767 + } 3768 + 3769 + static void devlink_nl_region_notify(struct devlink_region *region, 3770 + struct devlink_snapshot *snapshot, 3771 + enum devlink_command cmd) 3772 + { 3773 + struct devlink *devlink = region->devlink; 3774 + struct sk_buff *msg; 3775 + 3776 + WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3777 + 3778 + msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0); 3779 + if (IS_ERR(msg)) 3780 + return; 3781 + 3782 + genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3783 + msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3771 3784 } 3772 3785 3773 3786 /** ··· 4086 4069 devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) 4087 4070 { 4088 4071 struct devlink *devlink = info->user_ptr[0]; 4072 + struct devlink_snapshot *snapshot; 4073 + struct nlattr *snapshot_id_attr; 4089 4074 struct devlink_region *region; 4090 4075 const char *region_name; 4091 4076 u32 snapshot_id; ··· 4096 4077 4097 4078 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) { 4098 4079 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided"); 4099 - return -EINVAL; 4100 - } 4101 - 4102 - if (!info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { 4103 - NL_SET_ERR_MSG_MOD(info->extack, "No snapshot id provided"); 4104 4080 return -EINVAL; 4105 4081 } 4106 4082 ··· 4116 4102 return -ENOSPC; 4117 4103 } 4118 4104 4119 - snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 4105 + snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; 4106 + if (snapshot_id_attr) { 4107 + snapshot_id = nla_get_u32(snapshot_id_attr); 4120 4108 4121 - if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4122 - NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use"); 4123 - return -EEXIST; 4109 + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4110 + NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use"); 4111 + return -EEXIST; 4112 + } 4113 + 4114 + err = __devlink_snapshot_id_insert(devlink, snapshot_id); 4115 + if (err) 4116 + return err; 4117 + } else { 4118 + err = __devlink_region_snapshot_id_get(devlink, &snapshot_id); 4119 + if (err) { 4120 + NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id"); 4121 + return err; 4122 + } 4124 4123 } 4125 - 4126 - err = __devlink_snapshot_id_insert(devlink, snapshot_id); 4127 - if (err) 4128 - return err; 4129 4124 4130 4125 err = region->ops->snapshot(devlink, info->extack, &data); 4131 4126 if (err) ··· 4144 4121 if (err) 4145 4122 goto err_snapshot_create; 4146 4123 4124 + if (!snapshot_id_attr) { 4125 + struct sk_buff *msg; 4126 + 4127 + snapshot = devlink_region_snapshot_get_by_id(region, 4128 + snapshot_id); 4129 + if (WARN_ON(!snapshot)) 4130 + return -EINVAL; 4131 + 4132 + msg = devlink_nl_region_notify_build(region, snapshot, 4133 + DEVLINK_CMD_REGION_NEW, 4134 + info->snd_portid, 4135 + info->snd_seq); 4136 + err = PTR_ERR_OR_ZERO(msg); 4137 + if (err) 4138 + goto err_notify; 4139 + 4140 + err = genlmsg_reply(msg, info); 4141 + if (err) 4142 + goto err_notify; 4143 + } 4144 + 4147 4145 return 0; 4148 4146 4149 4147 err_snapshot_create: 4150 4148 region->ops->destructor(data); 4151 4149 err_snapshot_capture: 4152 4150 __devlink_snapshot_id_decrement(devlink, snapshot_id); 4151 + return err; 4152 + 4153 + err_notify: 4154 + devlink_region_snapshot_del(region, snapshot); 4153 4155 return err; 4154 4156 } 4155 4157
+13
tools/testing/selftests/drivers/net/netdevsim/devlink.sh
··· 151 151 152 152 check_region_snapshot_count dummy post-second-delete 2 153 153 154 + sid=$(devlink -j region new $DL_HANDLE/dummy | jq '.[][][][]') 155 + check_err $? "Failed to create a new snapshot with id allocated by the kernel" 156 + 157 + check_region_snapshot_count dummy post-first-request 3 158 + 159 + devlink region dump $DL_HANDLE/dummy snapshot $sid >> /dev/null 160 + check_err $? "Failed to dump a snapshot with id allocated by the kernel" 161 + 162 + devlink region del $DL_HANDLE/dummy snapshot $sid 163 + check_err $? "Failed to delete snapshot with id allocated by the kernel" 164 + 165 + check_region_snapshot_count dummy post-first-request 2 166 + 154 167 log_test "regions test" 155 168 } 156 169