From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex Vesker Subject: [PATCH net-next 3/9] devlink: Add support for creating region snapshots Date: Thu, 29 Mar 2018 19:07:46 +0300 Message-ID: <1522339672-18273-4-git-send-email-valex@mellanox.com> References: <1522339672-18273-1-git-send-email-valex@mellanox.com> Cc: netdev@vger.kernel.org, Tariq Toukan , Jiri Pirko , Alex Vesker To: "David S. Miller" Return-path: Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:45423 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752201AbeC2QaD (ORCPT ); Thu, 29 Mar 2018 12:30:03 -0400 In-Reply-To: <1522339672-18273-1-git-send-email-valex@mellanox.com> Sender: netdev-owner@vger.kernel.org List-ID: Each device address region can store multiple snapshots, each snapshot is identified using a different numerical ID. This ID is used when deleting a snapshot or showing an address region specific snapshot. This patch exposes a callback to add a new snapshot (data, data length and ID) to an address region. The snapshot are can be deleted from devlink user tool or when destroying a region. Signed-off-by: Alex Vesker Signed-off-by: Jiri Pirko --- include/net/devlink.h | 9 +++++ net/core/devlink.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/include/net/devlink.h b/include/net/devlink.h index 5697c55..83e569f 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -429,6 +429,8 @@ struct devlink_region *devlink_region_create(struct devlink *devlink, u64 region_size); void devlink_region_destroy(struct devlink_region *region); u32 devlink_region_shapshot_id_get(struct devlink *devlink); +int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, + u8 *data, u32 snapshot_id); #else @@ -619,6 +621,13 @@ static inline bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, return 0; } +static inline int +devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, + u8 *data, u32 snapshot_id) +{ + return 0; +} + #endif #endif /* _NET_DEVLINK_H_ */ diff --git a/net/core/devlink.c b/net/core/devlink.c index 4822a08..785e87d 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -336,6 +336,14 @@ struct devlink_region { u64 size; }; +struct devlink_snapshot { + struct list_head list; + struct devlink_region *region; + u64 data_len; + u8 *data; + u32 id; +}; + static struct devlink_region * devlink_region_get_by_name(struct devlink *devlink, const char *region_name) { @@ -348,6 +356,26 @@ struct devlink_region { return NULL; } +static struct devlink_snapshot * +devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) +{ + struct devlink_snapshot *snapshot; + + list_for_each_entry(snapshot, ®ion->snapshot_list, list) + if (snapshot->id == id) + return snapshot; + + return NULL; +} + +static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot) +{ + snapshot->region->cur_snapshots--; + list_del(&snapshot->list); + kfree(snapshot->data); + kfree(snapshot); +} + #define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) #define DEVLINK_NL_FLAG_NEED_PORT BIT(1) #define DEVLINK_NL_FLAG_NEED_SB BIT(2) @@ -3391,8 +3419,14 @@ struct devlink_region *devlink_region_create(struct devlink *devlink, void devlink_region_destroy(struct devlink_region *region) { struct devlink *devlink = region->devlink; + struct devlink_snapshot *snapshot, *ts; mutex_lock(&devlink->lock); + + /* Free all snapshots of region */ + list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list) + devlink_region_snapshot_del(snapshot); + list_del(®ion->list); mutex_unlock(&devlink->lock); kfree(region); @@ -3420,6 +3454,71 @@ u32 devlink_region_shapshot_id_get(struct devlink *devlink) } EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); +/** + * devlink_region_snapshot_create - create a new snapshot + * This will add a new snapshot of a region. The snapshot + * will be stored on the region struct and can be accessed + * from devlink. This is useful for future analyses of snapshots. + * Multiple snapshots can be created on a region. + * The @snapshot_id should be obtained using the getter function. + * + * @devlink_region: devlink region of the snapshot + * @data_len: size of snapshot data + * @data: snapshot data + * @snapshot_id: snapshot id to be created + */ +int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, + u8 *data, u32 snapshot_id) +{ + struct devlink *devlink = region->devlink; + struct devlink_snapshot *snapshot; + int err; + + mutex_lock(&devlink->lock); + + /* check if region can hold one more snapshot */ + if (region->cur_snapshots == region->max_snapshots) { + err = -ENOMEM; + goto unlock; + } + + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { + err = -EEXIST; + goto unlock; + } + + snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); + if (!snapshot) { + err = -ENOMEM; + goto unlock; + } + + snapshot->data = kzalloc(data_len, GFP_KERNEL); + if (!snapshot->data) { + err = -ENOMEM; + goto free_snapshot; + } + + snapshot->id = snapshot_id; + snapshot->region = region; + snapshot->data_len = data_len; + memcpy(snapshot->data, data, data_len); + + list_add_tail(&snapshot->list, ®ion->snapshot_list); + + region->cur_snapshots++; + + mutex_unlock(&devlink->lock); + return 0; + +free_snapshot: + kfree(snapshot); +unlock: + mutex_unlock(&devlink->lock); + return err; +} +EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); + static int __init devlink_module_init(void) { return genl_register_family(&devlink_nl_family); -- 1.8.3.1