netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jacob Keller <jacob.e.keller@intel.com>
To: netdev@vger.kernel.org
Cc: Jakub Kicinski <kuba@kernel.org>, Jiri Pirko <jiri@resnulli.us>,
	Jacob Keller <jacob.e.keller@intel.com>
Subject: [PATCH 08/10] devlink: implement DEVLINK_CMD_REGION_NEW
Date: Tue, 24 Mar 2020 15:34:43 -0700	[thread overview]
Message-ID: <20200324223445.2077900-9-jacob.e.keller@intel.com> (raw)
In-Reply-To: <20200324223445.2077900-1-jacob.e.keller@intel.com>

Implement support for the DEVLINK_CMD_REGION_NEW command for creating
snapshots. This new command parallels the existing
DEVLINK_CMD_REGION_DEL.

In order for DEVLINK_CMD_REGION_NEW to work for a region, the new
".snapshot" operation must be implemented in the region's ops structure.

The desired snapshot id must be provided. This helps avoid confusion on
the purpose of DEVLINK_CMD_REGION_NEW, and keeps the API simpler.

The requested id will be inserted into the xarray tracking the number of
snapshots using each id. If this id is already used by another snapshot
on any region, an error will be returned.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 .../networking/devlink/devlink-region.rst     |   8 ++
 include/net/devlink.h                         |   6 +
 net/core/devlink.c                            | 103 ++++++++++++++++++
 3 files changed, 117 insertions(+)

diff --git a/Documentation/networking/devlink/devlink-region.rst b/Documentation/networking/devlink/devlink-region.rst
index 8b46e8591fe0..9d2d4c95a5c4 100644
--- a/Documentation/networking/devlink/devlink-region.rst
+++ b/Documentation/networking/devlink/devlink-region.rst
@@ -20,6 +20,11 @@ address regions that are otherwise inaccessible to the user.
 Regions may also be used to provide an additional way to debug complex error
 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.
+
 example usage
 -------------
 
@@ -40,6 +45,9 @@ example usage
     # Delete a snapshot using:
     $ 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
+
     # Dump a snapshot:
     $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1
     0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 30306e62fe73..ae894e073050 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -502,10 +502,16 @@ struct devlink_info_req;
  * struct devlink_region_ops - Region operations
  * @name: region name
  * @destructor: callback used to free snapshot memory when deleting
+ * @snapshot: callback to request an immediate snapshot. On success,
+ *            the data variable must be updated to point to the snapshot data.
+ *            The function will be called while the devlink instance lock is
+ *            held.
  */
 struct devlink_region_ops {
 	const char *name;
 	void (*destructor)(const void *data);
+	int (*snapshot)(struct devlink *devlink, struct netlink_ext_ack *extack,
+			u8 **data);
 };
 
 struct devlink_fmsg;
diff --git a/net/core/devlink.c b/net/core/devlink.c
index b3698228a6ed..16129ec27913 100644
--- a/net/core/devlink.c
+++ b/net/core/devlink.c
@@ -3849,6 +3849,35 @@ static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
 	}
 }
 
+/**
+ *	__devlink_snapshot_id_insert - Insert a specific snapshot ID
+ *	@devlink: devlink instance
+ *	@id: the snapshot id
+ *
+ *	Mark the given snapshot id as used by inserting a zero value into the
+ *	snapshot xarray.
+ *
+ *	Returns zero on success, or an error code if the snapshot id could not
+ *	be inserted.
+ */
+static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
+{
+	int err;
+
+	lockdep_assert_held(&devlink->lock);
+
+	/* Check to make sure it's empty first */
+	if (xa_load(&devlink->snapshot_ids, id))
+		return -EBUSY;
+
+	err = xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
+			      GFP_KERNEL));
+	if (err)
+		return err;
+
+	return 0;
+}
+
 /**
  *	__devlink_region_snapshot_id_get - get snapshot ID
  *	@devlink: devlink instance
@@ -4048,6 +4077,73 @@ static int devlink_nl_cmd_region_del(struct sk_buff *skb,
 	return 0;
 }
 
+static int
+devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
+{
+	struct devlink *devlink = info->user_ptr[0];
+	struct devlink_region *region;
+	const char *region_name;
+	u32 snapshot_id;
+	u8 *data;
+	int err;
+
+	if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) {
+		NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
+		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) {
+		NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist");
+		return -EINVAL;
+	}
+
+	if (!region->ops->snapshot) {
+		NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot");
+		return -EOPNOTSUPP;
+	}
+
+	if (region->cur_snapshots == region->max_snapshots) {
+		NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots");
+		return -ENOMEM;
+	}
+
+	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
+
+	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) {
+		NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in used");
+		return err;
+	}
+
+	err = region->ops->snapshot(devlink, info->extack, &data);
+	if (err)
+		goto err_decrement_snapshot_count;
+
+	err = __devlink_region_snapshot_create(region, data, snapshot_id);
+	if (err)
+		goto err_free_snapshot_data;
+
+	return 0;
+
+err_decrement_snapshot_count:
+	__devlink_snapshot_id_decrement(devlink, snapshot_id);
+err_free_snapshot_data:
+	region->ops->destructor(data);
+	return err;
+}
+
 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
 						 struct devlink *devlink,
 						 u8 *chunk, u32 chunk_size,
@@ -6455,6 +6551,13 @@ static const struct genl_ops devlink_nl_ops[] = {
 		.flags = GENL_ADMIN_PERM,
 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
 	},
+	{
+		.cmd = DEVLINK_CMD_REGION_NEW,
+		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
+		.doit = devlink_nl_cmd_region_new,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
+	},
 	{
 		.cmd = DEVLINK_CMD_REGION_DEL,
 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-- 
2.24.1


  parent reply	other threads:[~2020-03-24 22:35 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-24 22:34 [PATCH 00/10] implement DEVLINK_CMD_REGION_NEW Jacob Keller
2020-03-24 22:34 ` [PATCH 01/10] devlink: prepare to support region operations Jacob Keller
2020-03-24 22:34 ` [PATCH 02/10] devlink: convert snapshot destructor callback to region op Jacob Keller
2020-03-24 22:34 ` [PATCH 03/10] devlink: trivial: fix tab in function documentation Jacob Keller
2020-03-24 22:34 ` [PATCH 04/10] devlink: add function to take snapshot while locked Jacob Keller
2020-03-25 17:56   ` Jakub Kicinski
2020-03-24 22:34 ` [PATCH 05/10] devlink: extract snapshot id allocation to helper function Jacob Keller
2020-03-25 14:08   ` Jiri Pirko
2020-03-24 22:34 ` [PATCH 06/10] devlink: convert snapshot id getter to return an error Jacob Keller
2020-03-25 18:04   ` Jakub Kicinski
2020-03-25 19:13     ` Jiri Pirko
2020-03-26  1:33     ` Jacob Keller
2020-03-24 22:34 ` [PATCH] devlink: track snapshot id usage count using an xarray Jacob Keller
2020-03-25 16:08   ` Jiri Pirko
2020-03-26  1:16     ` Jacob Keller
2020-03-26  1:43     ` Jacob Keller
2020-03-24 22:34 ` Jacob Keller [this message]
2020-03-25 16:46   ` [PATCH 08/10] devlink: implement DEVLINK_CMD_REGION_NEW Jiri Pirko
2020-03-25 17:18     ` Jakub Kicinski
2020-03-25 17:20       ` Jiri Pirko
2020-03-25 17:46         ` Jakub Kicinski
2020-03-25 18:41           ` Jiri Pirko
2020-03-26  1:30     ` Jacob Keller
2020-03-24 22:34 ` [PATCH 09/10] netdevsim: support taking immediate snapshot via devlink Jacob Keller
2020-03-25 16:50   ` Jiri Pirko
2020-03-24 22:34 ` [PATCH 10/10] ice: add a devlink region for dumping NVM contents Jacob Keller
2020-03-25 17:18   ` Jiri Pirko
2020-03-25 13:49 ` [PATCH 00/10] implement DEVLINK_CMD_REGION_NEW Jiri Pirko
2020-03-25 13:50 ` Jiri Pirko

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=20200324223445.2077900-9-jacob.e.keller@intel.com \
    --to=jacob.e.keller@intel.com \
    --cc=jiri@resnulli.us \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.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).