Thu, Apr 30, 2020 at 01:38:13AM CEST, k...@kernel.org wrote: >Currently users have to choose a free snapshot id before >calling DEVLINK_CMD_REGION_NEW. This is potentially racy >and inconvenient. > >Make the DEVLINK_ATTR_REGION_SNAPSHOT_ID optional and try >to allocate id automatically. Send a message back to the >caller with the snapshot info. > >The message carrying id gets sent immediately, but the >allocation is only valid if the entire operation succeeded. >This makes life easier, as sending the notification itself >may fail. > >Example use: >$ devlink region new netdevsim/netdevsim1/dummy >netdevsim/netdevsim1/dummy: snapshot 1 > >$ id=$(devlink -j region new netdevsim/netdevsim1/dummy | \ > jq '.[][][][]') >$ devlink region dump netdevsim/netdevsim1/dummy snapshot $id >[...] >$ devlink region del netdevsim/netdevsim1/dummy snapshot $id > >v2: > - don't wrap the line containing extack; > - add a few sentences to the docs. > >Signed-off-by: Jakub Kicinski <k...@kernel.org> >--- > .../networking/devlink/devlink-region.rst | 10 ++- > net/core/devlink.c | 83 ++++++++++++++++--- > .../drivers/net/netdevsim/devlink.sh | 13 +++ > 3 files changed, 91 insertions(+), 15 deletions(-) > >diff --git a/Documentation/networking/devlink/devlink-region.rst >b/Documentation/networking/devlink/devlink-region.rst >index 04e04d1ff627..b163d09a3d0d 100644 >--- a/Documentation/networking/devlink/devlink-region.rst >+++ b/Documentation/networking/devlink/devlink-region.rst >@@ -23,7 +23,12 @@ states, but see also :doc:`devlink-health` > Regions may optionally support capturing a snapshot on demand via the > ``DEVLINK_CMD_REGION_NEW`` netlink message. A driver wishing to allow > requested snapshots must implement the ``.snapshot`` callback for the region >-in its ``devlink_region_ops`` structure. >+in its ``devlink_region_ops`` structure. If snapshot id is not set in >+the ``DEVLINK_CMD_REGION_NEW`` request kernel will allocate one and send >+the snapshot information to user space. Note that receiving the snapshot >+information does not guarantee that the snapshot creation completed >+successfully, user space must check the status of the operation before >+proceeding. > > example usage > ------------- >@@ -45,7 +50,8 @@ example usage > $ devlink region del pci/0000:00:05.0/cr-space snapshot 1 > > # Request an immediate snapshot, if supported by the region >- $ devlink region new pci/0000:00:05.0/cr-space snapshot 5 >+ $ devlink region new pci/0000:00:05.0/cr-space >+ pci/0000:00:05.0/cr-space: snapshot 5 > > # Dump a snapshot: > $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1 >diff --git a/net/core/devlink.c b/net/core/devlink.c >index 1ec2e9fd8898..82703be1032e 100644 >--- a/net/core/devlink.c >+++ b/net/core/devlink.c >@@ -4065,10 +4065,64 @@ static int devlink_nl_cmd_region_del(struct sk_buff >*skb, > return 0; > } > >+static int >+devlink_nl_alloc_snapshot_id(struct devlink *devlink, struct genl_info *info, >+ struct devlink_region *region, u32 *snapshot_id) >+{ >+ struct sk_buff *msg; >+ void *hdr; >+ int err; >+ >+ err = __devlink_region_snapshot_id_get(devlink, snapshot_id); >+ if (err) { >+ NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new >snapshot id"); >+ return err; >+ } >+ >+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); >+ if (!msg) { >+ err = -ENOMEM; >+ goto err_msg_alloc; >+ } >+ >+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, >+ &devlink_nl_family, 0, DEVLINK_CMD_REGION_NEW); >+ if (!hdr) { >+ err = -EMSGSIZE; >+ goto err_put_failure; >+ } >+ err = devlink_nl_put_handle(msg, devlink); >+ if (err) >+ goto err_attr_failure; >+ err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name); >+ if (err) >+ goto err_attr_failure; >+ err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, *snapshot_id); >+ if (err) >+ goto err_attr_failure; >+ genlmsg_end(msg, hdr); >+ >+ err = genlmsg_reply(msg, info); >+ if (err) >+ goto err_reply; >+ >+ return 0; >+ >+err_attr_failure: >+ genlmsg_cancel(msg, hdr); >+err_put_failure: >+ nlmsg_free(msg); >+err_msg_alloc: >+err_reply: >+ __devlink_snapshot_id_decrement(devlink, *snapshot_id); >+ return err; >+} >+ > static int > devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) > { > struct devlink *devlink = info->user_ptr[0]; >+ struct nlattr *snapshot_id_attr; > struct devlink_region *region; > const char *region_name; > u32 snapshot_id; >@@ -4080,11 +4134,6 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct >genl_info *info) > return -EINVAL; > } > >- if (!info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { >- NL_SET_ERR_MSG_MOD(info->extack, "No snapshot id provided"); >- return -EINVAL; >- } >- > region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); > region = devlink_region_get_by_name(devlink, region_name); > if (!region) { >@@ -4102,16 +4151,24 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct >genl_info *info) > return -ENOSPC; > } > >- snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); >+ snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; >+ if (snapshot_id_attr) { >+ snapshot_id = nla_get_u32(snapshot_id_attr); > >- if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { >- NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is >already in use"); >- return -EEXIST; >- } >+ if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { >+ NL_SET_ERR_MSG_MOD(info->extack, "The requested >snapshot id is already in use"); >+ return -EEXIST; >+ } > >- err = __devlink_snapshot_id_insert(devlink, snapshot_id); >- if (err) >- return err; >+ err = __devlink_snapshot_id_insert(devlink, snapshot_id); >+ if (err) >+ return err; >+ } else { >+ err = devlink_nl_alloc_snapshot_id(devlink, info, >+ region, &snapshot_id); >+ if (err) >+ return err; >+ }
Could you please send the snapshot id just before you return 0 in this function, as you offered in v1? I think it would be great to do it like that. Thanks! > > err = region->ops->snapshot(devlink, info->extack, &data); > if (err) >diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh >b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh >index 9f9741444549..ad539eccddcb 100755 >--- a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh >+++ b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh >@@ -151,6 +151,19 @@ regions_test() > > check_region_snapshot_count dummy post-second-delete 2 > >+ sid=$(devlink -j region new $DL_HANDLE/dummy | jq '.[][][][]') >+ check_err $? "Failed to create a new snapshot with id allocated by the >kernel" >+ >+ check_region_snapshot_count dummy post-first-request 3 >+ >+ devlink region dump $DL_HANDLE/dummy snapshot $sid >> /dev/null >+ check_err $? "Failed to dump a snapshot with id allocated by the kernel" >+ >+ devlink region del $DL_HANDLE/dummy snapshot $sid >+ check_err $? "Failed to delete snapshot with id allocated by the kernel" >+ >+ check_region_snapshot_count dummy post-first-request 2 >+ > log_test "regions test" > } > >-- >2.25.4 >