xref: /openbmc/linux/net/devlink/region.c (revision 1aa47ca1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5  */
6 
7 #include "devl_internal.h"
8 
9 struct devlink_region {
10 	struct devlink *devlink;
11 	struct devlink_port *port;
12 	struct list_head list;
13 	union {
14 		const struct devlink_region_ops *ops;
15 		const struct devlink_port_region_ops *port_ops;
16 	};
17 	struct mutex snapshot_lock; /* protects snapshot_list,
18 				     * max_snapshots and cur_snapshots
19 				     * consistency.
20 				     */
21 	struct list_head snapshot_list;
22 	u32 max_snapshots;
23 	u32 cur_snapshots;
24 	u64 size;
25 };
26 
27 struct devlink_snapshot {
28 	struct list_head list;
29 	struct devlink_region *region;
30 	u8 *data;
31 	u32 id;
32 };
33 
34 static struct devlink_region *
devlink_region_get_by_name(struct devlink * devlink,const char * region_name)35 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
36 {
37 	struct devlink_region *region;
38 
39 	list_for_each_entry(region, &devlink->region_list, list)
40 		if (!strcmp(region->ops->name, region_name))
41 			return region;
42 
43 	return NULL;
44 }
45 
46 static struct devlink_region *
devlink_port_region_get_by_name(struct devlink_port * port,const char * region_name)47 devlink_port_region_get_by_name(struct devlink_port *port,
48 				const char *region_name)
49 {
50 	struct devlink_region *region;
51 
52 	list_for_each_entry(region, &port->region_list, list)
53 		if (!strcmp(region->ops->name, region_name))
54 			return region;
55 
56 	return NULL;
57 }
58 
59 static struct devlink_snapshot *
devlink_region_snapshot_get_by_id(struct devlink_region * region,u32 id)60 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
61 {
62 	struct devlink_snapshot *snapshot;
63 
64 	list_for_each_entry(snapshot, &region->snapshot_list, list)
65 		if (snapshot->id == id)
66 			return snapshot;
67 
68 	return NULL;
69 }
70 
devlink_nl_region_snapshot_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_snapshot * snapshot)71 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
72 					     struct devlink *devlink,
73 					     struct devlink_snapshot *snapshot)
74 {
75 	struct nlattr *snap_attr;
76 	int err;
77 
78 	snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
79 	if (!snap_attr)
80 		return -EINVAL;
81 
82 	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
83 	if (err)
84 		goto nla_put_failure;
85 
86 	nla_nest_end(msg, snap_attr);
87 	return 0;
88 
89 nla_put_failure:
90 	nla_nest_cancel(msg, snap_attr);
91 	return err;
92 }
93 
devlink_nl_region_snapshots_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_region * region)94 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
95 					      struct devlink *devlink,
96 					      struct devlink_region *region)
97 {
98 	struct devlink_snapshot *snapshot;
99 	struct nlattr *snapshots_attr;
100 	int err;
101 
102 	snapshots_attr = nla_nest_start_noflag(msg,
103 					       DEVLINK_ATTR_REGION_SNAPSHOTS);
104 	if (!snapshots_attr)
105 		return -EINVAL;
106 
107 	list_for_each_entry(snapshot, &region->snapshot_list, list) {
108 		err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
109 		if (err)
110 			goto nla_put_failure;
111 	}
112 
113 	nla_nest_end(msg, snapshots_attr);
114 	return 0;
115 
116 nla_put_failure:
117 	nla_nest_cancel(msg, snapshots_attr);
118 	return err;
119 }
120 
devlink_nl_region_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct devlink_region * region)121 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
122 				  enum devlink_command cmd, u32 portid,
123 				  u32 seq, int flags,
124 				  struct devlink_region *region)
125 {
126 	void *hdr;
127 	int err;
128 
129 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
130 	if (!hdr)
131 		return -EMSGSIZE;
132 
133 	err = devlink_nl_put_handle(msg, devlink);
134 	if (err)
135 		goto nla_put_failure;
136 
137 	if (region->port) {
138 		err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
139 				  region->port->index);
140 		if (err)
141 			goto nla_put_failure;
142 	}
143 
144 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
145 	if (err)
146 		goto nla_put_failure;
147 
148 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
149 				region->size,
150 				DEVLINK_ATTR_PAD);
151 	if (err)
152 		goto nla_put_failure;
153 
154 	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
155 			  region->max_snapshots);
156 	if (err)
157 		goto nla_put_failure;
158 
159 	err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
160 	if (err)
161 		goto nla_put_failure;
162 
163 	genlmsg_end(msg, hdr);
164 	return 0;
165 
166 nla_put_failure:
167 	genlmsg_cancel(msg, hdr);
168 	return err;
169 }
170 
171 static struct sk_buff *
devlink_nl_region_notify_build(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd,u32 portid,u32 seq)172 devlink_nl_region_notify_build(struct devlink_region *region,
173 			       struct devlink_snapshot *snapshot,
174 			       enum devlink_command cmd, u32 portid, u32 seq)
175 {
176 	struct devlink *devlink = region->devlink;
177 	struct sk_buff *msg;
178 	void *hdr;
179 	int err;
180 
181 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
182 	if (!msg)
183 		return ERR_PTR(-ENOMEM);
184 
185 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
186 	if (!hdr) {
187 		err = -EMSGSIZE;
188 		goto out_free_msg;
189 	}
190 
191 	err = devlink_nl_put_handle(msg, devlink);
192 	if (err)
193 		goto out_cancel_msg;
194 
195 	if (region->port) {
196 		err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
197 				  region->port->index);
198 		if (err)
199 			goto out_cancel_msg;
200 	}
201 
202 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
203 			     region->ops->name);
204 	if (err)
205 		goto out_cancel_msg;
206 
207 	if (snapshot) {
208 		err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
209 				  snapshot->id);
210 		if (err)
211 			goto out_cancel_msg;
212 	} else {
213 		err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
214 					region->size, DEVLINK_ATTR_PAD);
215 		if (err)
216 			goto out_cancel_msg;
217 	}
218 	genlmsg_end(msg, hdr);
219 
220 	return msg;
221 
222 out_cancel_msg:
223 	genlmsg_cancel(msg, hdr);
224 out_free_msg:
225 	nlmsg_free(msg);
226 	return ERR_PTR(err);
227 }
228 
devlink_nl_region_notify(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd)229 static void devlink_nl_region_notify(struct devlink_region *region,
230 				     struct devlink_snapshot *snapshot,
231 				     enum devlink_command cmd)
232 {
233 	struct devlink *devlink = region->devlink;
234 	struct sk_buff *msg;
235 
236 	WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
237 	if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
238 		return;
239 
240 	msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
241 	if (IS_ERR(msg))
242 		return;
243 
244 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
245 				0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
246 }
247 
devlink_regions_notify_register(struct devlink * devlink)248 void devlink_regions_notify_register(struct devlink *devlink)
249 {
250 	struct devlink_region *region;
251 
252 	list_for_each_entry(region, &devlink->region_list, list)
253 		devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
254 }
255 
devlink_regions_notify_unregister(struct devlink * devlink)256 void devlink_regions_notify_unregister(struct devlink *devlink)
257 {
258 	struct devlink_region *region;
259 
260 	list_for_each_entry_reverse(region, &devlink->region_list, list)
261 		devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
262 }
263 
264 /**
265  * __devlink_snapshot_id_increment - Increment number of snapshots using an id
266  *	@devlink: devlink instance
267  *	@id: the snapshot id
268  *
269  *	Track when a new snapshot begins using an id. Load the count for the
270  *	given id from the snapshot xarray, increment it, and store it back.
271  *
272  *	Called when a new snapshot is created with the given id.
273  *
274  *	The id *must* have been previously allocated by
275  *	devlink_region_snapshot_id_get().
276  *
277  *	Returns 0 on success, or an error on failure.
278  */
__devlink_snapshot_id_increment(struct devlink * devlink,u32 id)279 static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
280 {
281 	unsigned long count;
282 	void *p;
283 	int err;
284 
285 	xa_lock(&devlink->snapshot_ids);
286 	p = xa_load(&devlink->snapshot_ids, id);
287 	if (WARN_ON(!p)) {
288 		err = -EINVAL;
289 		goto unlock;
290 	}
291 
292 	if (WARN_ON(!xa_is_value(p))) {
293 		err = -EINVAL;
294 		goto unlock;
295 	}
296 
297 	count = xa_to_value(p);
298 	count++;
299 
300 	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
301 				GFP_ATOMIC));
302 unlock:
303 	xa_unlock(&devlink->snapshot_ids);
304 	return err;
305 }
306 
307 /**
308  * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
309  *	@devlink: devlink instance
310  *	@id: the snapshot id
311  *
312  *	Track when a snapshot is deleted and stops using an id. Load the count
313  *	for the given id from the snapshot xarray, decrement it, and store it
314  *	back.
315  *
316  *	If the count reaches zero, erase this id from the xarray, freeing it
317  *	up for future re-use by devlink_region_snapshot_id_get().
318  *
319  *	Called when a snapshot using the given id is deleted, and when the
320  *	initial allocator of the id is finished using it.
321  */
__devlink_snapshot_id_decrement(struct devlink * devlink,u32 id)322 static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
323 {
324 	unsigned long count;
325 	void *p;
326 
327 	xa_lock(&devlink->snapshot_ids);
328 	p = xa_load(&devlink->snapshot_ids, id);
329 	if (WARN_ON(!p))
330 		goto unlock;
331 
332 	if (WARN_ON(!xa_is_value(p)))
333 		goto unlock;
334 
335 	count = xa_to_value(p);
336 
337 	if (count > 1) {
338 		count--;
339 		__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
340 			   GFP_ATOMIC);
341 	} else {
342 		/* If this was the last user, we can erase this id */
343 		__xa_erase(&devlink->snapshot_ids, id);
344 	}
345 unlock:
346 	xa_unlock(&devlink->snapshot_ids);
347 }
348 
349 /**
350  *	__devlink_snapshot_id_insert - Insert a specific snapshot ID
351  *	@devlink: devlink instance
352  *	@id: the snapshot id
353  *
354  *	Mark the given snapshot id as used by inserting a zero value into the
355  *	snapshot xarray.
356  *
357  *	This must be called while holding the devlink instance lock. Unlike
358  *	devlink_snapshot_id_get, the initial reference count is zero, not one.
359  *	It is expected that the id will immediately be used before
360  *	releasing the devlink instance lock.
361  *
362  *	Returns zero on success, or an error code if the snapshot id could not
363  *	be inserted.
364  */
__devlink_snapshot_id_insert(struct devlink * devlink,u32 id)365 static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
366 {
367 	int err;
368 
369 	xa_lock(&devlink->snapshot_ids);
370 	if (xa_load(&devlink->snapshot_ids, id)) {
371 		xa_unlock(&devlink->snapshot_ids);
372 		return -EEXIST;
373 	}
374 	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
375 				GFP_ATOMIC));
376 	xa_unlock(&devlink->snapshot_ids);
377 	return err;
378 }
379 
380 /**
381  *	__devlink_region_snapshot_id_get - get snapshot ID
382  *	@devlink: devlink instance
383  *	@id: storage to return snapshot id
384  *
385  *	Allocates a new snapshot id. Returns zero on success, or a negative
386  *	error on failure. Must be called while holding the devlink instance
387  *	lock.
388  *
389  *	Snapshot IDs are tracked using an xarray which stores the number of
390  *	users of the snapshot id.
391  *
392  *	Note that the caller of this function counts as a 'user', in order to
393  *	avoid race conditions. The caller must release its hold on the
394  *	snapshot by using devlink_region_snapshot_id_put.
395  */
__devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)396 static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
397 {
398 	return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
399 			xa_limit_32b, GFP_KERNEL);
400 }
401 
402 /**
403  *	__devlink_region_snapshot_create - create a new snapshot
404  *	This will add a new snapshot of a region. The snapshot
405  *	will be stored on the region struct and can be accessed
406  *	from devlink. This is useful for future analyses of snapshots.
407  *	Multiple snapshots can be created on a region.
408  *	The @snapshot_id should be obtained using the getter function.
409  *
410  *	Must be called only while holding the region snapshot lock.
411  *
412  *	@region: devlink region of the snapshot
413  *	@data: snapshot data
414  *	@snapshot_id: snapshot id to be created
415  */
416 static int
__devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)417 __devlink_region_snapshot_create(struct devlink_region *region,
418 				 u8 *data, u32 snapshot_id)
419 {
420 	struct devlink *devlink = region->devlink;
421 	struct devlink_snapshot *snapshot;
422 	int err;
423 
424 	lockdep_assert_held(&region->snapshot_lock);
425 
426 	/* check if region can hold one more snapshot */
427 	if (region->cur_snapshots == region->max_snapshots)
428 		return -ENOSPC;
429 
430 	if (devlink_region_snapshot_get_by_id(region, snapshot_id))
431 		return -EEXIST;
432 
433 	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
434 	if (!snapshot)
435 		return -ENOMEM;
436 
437 	err = __devlink_snapshot_id_increment(devlink, snapshot_id);
438 	if (err)
439 		goto err_snapshot_id_increment;
440 
441 	snapshot->id = snapshot_id;
442 	snapshot->region = region;
443 	snapshot->data = data;
444 
445 	list_add_tail(&snapshot->list, &region->snapshot_list);
446 
447 	region->cur_snapshots++;
448 
449 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
450 	return 0;
451 
452 err_snapshot_id_increment:
453 	kfree(snapshot);
454 	return err;
455 }
456 
devlink_region_snapshot_del(struct devlink_region * region,struct devlink_snapshot * snapshot)457 static void devlink_region_snapshot_del(struct devlink_region *region,
458 					struct devlink_snapshot *snapshot)
459 {
460 	struct devlink *devlink = region->devlink;
461 
462 	lockdep_assert_held(&region->snapshot_lock);
463 
464 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
465 	region->cur_snapshots--;
466 	list_del(&snapshot->list);
467 	region->ops->destructor(snapshot->data);
468 	__devlink_snapshot_id_decrement(devlink, snapshot->id);
469 	kfree(snapshot);
470 }
471 
devlink_nl_region_get_doit(struct sk_buff * skb,struct genl_info * info)472 int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info)
473 {
474 	struct devlink *devlink = info->user_ptr[0];
475 	struct devlink_port *port = NULL;
476 	struct devlink_region *region;
477 	const char *region_name;
478 	struct sk_buff *msg;
479 	unsigned int index;
480 	int err;
481 
482 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
483 		return -EINVAL;
484 
485 	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
486 		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
487 
488 		port = devlink_port_get_by_index(devlink, index);
489 		if (!port)
490 			return -ENODEV;
491 	}
492 
493 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
494 	if (port)
495 		region = devlink_port_region_get_by_name(port, region_name);
496 	else
497 		region = devlink_region_get_by_name(devlink, region_name);
498 
499 	if (!region)
500 		return -EINVAL;
501 
502 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
503 	if (!msg)
504 		return -ENOMEM;
505 
506 	err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
507 				     info->snd_portid, info->snd_seq, 0,
508 				     region);
509 	if (err) {
510 		nlmsg_free(msg);
511 		return err;
512 	}
513 
514 	return genlmsg_reply(msg, info);
515 }
516 
devlink_nl_cmd_region_get_port_dumpit(struct sk_buff * msg,struct netlink_callback * cb,struct devlink_port * port,int * idx,int start,int flags)517 static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
518 						 struct netlink_callback *cb,
519 						 struct devlink_port *port,
520 						 int *idx, int start, int flags)
521 {
522 	struct devlink_region *region;
523 	int err = 0;
524 
525 	list_for_each_entry(region, &port->region_list, list) {
526 		if (*idx < start) {
527 			(*idx)++;
528 			continue;
529 		}
530 		err = devlink_nl_region_fill(msg, port->devlink,
531 					     DEVLINK_CMD_REGION_GET,
532 					     NETLINK_CB(cb->skb).portid,
533 					     cb->nlh->nlmsg_seq,
534 					     flags, region);
535 		if (err)
536 			goto out;
537 		(*idx)++;
538 	}
539 
540 out:
541 	return err;
542 }
543 
devlink_nl_region_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)544 static int devlink_nl_region_get_dump_one(struct sk_buff *msg,
545 					  struct devlink *devlink,
546 					  struct netlink_callback *cb,
547 					  int flags)
548 {
549 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
550 	struct devlink_region *region;
551 	struct devlink_port *port;
552 	unsigned long port_index;
553 	int idx = 0;
554 	int err;
555 
556 	list_for_each_entry(region, &devlink->region_list, list) {
557 		if (idx < state->idx) {
558 			idx++;
559 			continue;
560 		}
561 		err = devlink_nl_region_fill(msg, devlink,
562 					     DEVLINK_CMD_REGION_GET,
563 					     NETLINK_CB(cb->skb).portid,
564 					     cb->nlh->nlmsg_seq, flags,
565 					     region);
566 		if (err) {
567 			state->idx = idx;
568 			return err;
569 		}
570 		idx++;
571 	}
572 
573 	xa_for_each(&devlink->ports, port_index, port) {
574 		err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx,
575 							    state->idx, flags);
576 		if (err) {
577 			state->idx = idx;
578 			return err;
579 		}
580 	}
581 
582 	return 0;
583 }
584 
devlink_nl_region_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)585 int devlink_nl_region_get_dumpit(struct sk_buff *skb,
586 				 struct netlink_callback *cb)
587 {
588 	return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one);
589 }
590 
devlink_nl_cmd_region_del(struct sk_buff * skb,struct genl_info * info)591 int devlink_nl_cmd_region_del(struct sk_buff *skb, struct genl_info *info)
592 {
593 	struct devlink *devlink = info->user_ptr[0];
594 	struct devlink_snapshot *snapshot;
595 	struct devlink_port *port = NULL;
596 	struct devlink_region *region;
597 	const char *region_name;
598 	unsigned int index;
599 	u32 snapshot_id;
600 
601 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
602 	    GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
603 		return -EINVAL;
604 
605 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
606 	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
607 
608 	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
609 		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
610 
611 		port = devlink_port_get_by_index(devlink, index);
612 		if (!port)
613 			return -ENODEV;
614 	}
615 
616 	if (port)
617 		region = devlink_port_region_get_by_name(port, region_name);
618 	else
619 		region = devlink_region_get_by_name(devlink, region_name);
620 
621 	if (!region)
622 		return -EINVAL;
623 
624 	mutex_lock(&region->snapshot_lock);
625 	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
626 	if (!snapshot) {
627 		mutex_unlock(&region->snapshot_lock);
628 		return -EINVAL;
629 	}
630 
631 	devlink_region_snapshot_del(region, snapshot);
632 	mutex_unlock(&region->snapshot_lock);
633 	return 0;
634 }
635 
devlink_nl_cmd_region_new(struct sk_buff * skb,struct genl_info * info)636 int devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
637 {
638 	struct devlink *devlink = info->user_ptr[0];
639 	struct devlink_snapshot *snapshot;
640 	struct devlink_port *port = NULL;
641 	struct nlattr *snapshot_id_attr;
642 	struct devlink_region *region;
643 	const char *region_name;
644 	unsigned int index;
645 	u32 snapshot_id;
646 	u8 *data;
647 	int err;
648 
649 	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
650 		NL_SET_ERR_MSG(info->extack, "No region name provided");
651 		return -EINVAL;
652 	}
653 
654 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
655 
656 	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
657 		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
658 
659 		port = devlink_port_get_by_index(devlink, index);
660 		if (!port)
661 			return -ENODEV;
662 	}
663 
664 	if (port)
665 		region = devlink_port_region_get_by_name(port, region_name);
666 	else
667 		region = devlink_region_get_by_name(devlink, region_name);
668 
669 	if (!region) {
670 		NL_SET_ERR_MSG(info->extack, "The requested region does not exist");
671 		return -EINVAL;
672 	}
673 
674 	if (!region->ops->snapshot) {
675 		NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot");
676 		return -EOPNOTSUPP;
677 	}
678 
679 	mutex_lock(&region->snapshot_lock);
680 
681 	if (region->cur_snapshots == region->max_snapshots) {
682 		NL_SET_ERR_MSG(info->extack, "The region has reached the maximum number of stored snapshots");
683 		err = -ENOSPC;
684 		goto unlock;
685 	}
686 
687 	snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
688 	if (snapshot_id_attr) {
689 		snapshot_id = nla_get_u32(snapshot_id_attr);
690 
691 		if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
692 			NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use");
693 			err = -EEXIST;
694 			goto unlock;
695 		}
696 
697 		err = __devlink_snapshot_id_insert(devlink, snapshot_id);
698 		if (err)
699 			goto unlock;
700 	} else {
701 		err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
702 		if (err) {
703 			NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id");
704 			goto unlock;
705 		}
706 	}
707 
708 	if (port)
709 		err = region->port_ops->snapshot(port, region->port_ops,
710 						 info->extack, &data);
711 	else
712 		err = region->ops->snapshot(devlink, region->ops,
713 					    info->extack, &data);
714 	if (err)
715 		goto err_snapshot_capture;
716 
717 	err = __devlink_region_snapshot_create(region, data, snapshot_id);
718 	if (err)
719 		goto err_snapshot_create;
720 
721 	if (!snapshot_id_attr) {
722 		struct sk_buff *msg;
723 
724 		snapshot = devlink_region_snapshot_get_by_id(region,
725 							     snapshot_id);
726 		if (WARN_ON(!snapshot)) {
727 			err = -EINVAL;
728 			goto unlock;
729 		}
730 
731 		msg = devlink_nl_region_notify_build(region, snapshot,
732 						     DEVLINK_CMD_REGION_NEW,
733 						     info->snd_portid,
734 						     info->snd_seq);
735 		err = PTR_ERR_OR_ZERO(msg);
736 		if (err)
737 			goto err_notify;
738 
739 		err = genlmsg_reply(msg, info);
740 		if (err)
741 			goto err_notify;
742 	}
743 
744 	mutex_unlock(&region->snapshot_lock);
745 	return 0;
746 
747 err_snapshot_create:
748 	region->ops->destructor(data);
749 err_snapshot_capture:
750 	__devlink_snapshot_id_decrement(devlink, snapshot_id);
751 	mutex_unlock(&region->snapshot_lock);
752 	return err;
753 
754 err_notify:
755 	devlink_region_snapshot_del(region, snapshot);
756 unlock:
757 	mutex_unlock(&region->snapshot_lock);
758 	return err;
759 }
760 
devlink_nl_cmd_region_read_chunk_fill(struct sk_buff * msg,u8 * chunk,u32 chunk_size,u64 addr)761 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
762 						 u8 *chunk, u32 chunk_size,
763 						 u64 addr)
764 {
765 	struct nlattr *chunk_attr;
766 	int err;
767 
768 	chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
769 	if (!chunk_attr)
770 		return -EINVAL;
771 
772 	err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
773 	if (err)
774 		goto nla_put_failure;
775 
776 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
777 				DEVLINK_ATTR_PAD);
778 	if (err)
779 		goto nla_put_failure;
780 
781 	nla_nest_end(msg, chunk_attr);
782 	return 0;
783 
784 nla_put_failure:
785 	nla_nest_cancel(msg, chunk_attr);
786 	return err;
787 }
788 
789 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
790 
791 typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
792 				 u64 curr_offset,
793 				 struct netlink_ext_ack *extack);
794 
795 static int
devlink_nl_region_read_fill(struct sk_buff * skb,devlink_chunk_fill_t * cb,void * cb_priv,u64 start_offset,u64 end_offset,u64 * new_offset,struct netlink_ext_ack * extack)796 devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb,
797 			    void *cb_priv, u64 start_offset, u64 end_offset,
798 			    u64 *new_offset, struct netlink_ext_ack *extack)
799 {
800 	u64 curr_offset = start_offset;
801 	int err = 0;
802 	u8 *data;
803 
804 	/* Allocate and re-use a single buffer */
805 	data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL);
806 	if (!data)
807 		return -ENOMEM;
808 
809 	*new_offset = start_offset;
810 
811 	while (curr_offset < end_offset) {
812 		u32 data_size;
813 
814 		data_size = min_t(u32, end_offset - curr_offset,
815 				  DEVLINK_REGION_READ_CHUNK_SIZE);
816 
817 		err = cb(cb_priv, data, data_size, curr_offset, extack);
818 		if (err)
819 			break;
820 
821 		err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset);
822 		if (err)
823 			break;
824 
825 		curr_offset += data_size;
826 	}
827 	*new_offset = curr_offset;
828 
829 	kfree(data);
830 
831 	return err;
832 }
833 
834 static int
devlink_region_snapshot_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack __always_unused * extack)835 devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
836 			     u64 curr_offset,
837 			     struct netlink_ext_ack __always_unused *extack)
838 {
839 	struct devlink_snapshot *snapshot = cb_priv;
840 
841 	memcpy(chunk, &snapshot->data[curr_offset], chunk_size);
842 
843 	return 0;
844 }
845 
846 static int
devlink_region_port_direct_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack * extack)847 devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
848 				u64 curr_offset, struct netlink_ext_ack *extack)
849 {
850 	struct devlink_region *region = cb_priv;
851 
852 	return region->port_ops->read(region->port, region->port_ops, extack,
853 				      curr_offset, chunk_size, chunk);
854 }
855 
856 static int
devlink_region_direct_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack * extack)857 devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
858 			   u64 curr_offset, struct netlink_ext_ack *extack)
859 {
860 	struct devlink_region *region = cb_priv;
861 
862 	return region->ops->read(region->devlink, region->ops, extack,
863 				 curr_offset, chunk_size, chunk);
864 }
865 
devlink_nl_cmd_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)866 int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
867 				      struct netlink_callback *cb)
868 {
869 	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
870 	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
871 	struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
872 	u64 ret_offset, start_offset, end_offset = U64_MAX;
873 	struct nlattr **attrs = info->info.attrs;
874 	struct devlink_port *port = NULL;
875 	devlink_chunk_fill_t *region_cb;
876 	struct devlink_region *region;
877 	const char *region_name;
878 	struct devlink *devlink;
879 	unsigned int index;
880 	void *region_cb_priv;
881 	void *hdr;
882 	int err;
883 
884 	start_offset = state->start_offset;
885 
886 	devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs);
887 	if (IS_ERR(devlink))
888 		return PTR_ERR(devlink);
889 
890 	if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
891 		NL_SET_ERR_MSG(cb->extack, "No region name provided");
892 		err = -EINVAL;
893 		goto out_unlock;
894 	}
895 
896 	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
897 		index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
898 
899 		port = devlink_port_get_by_index(devlink, index);
900 		if (!port) {
901 			err = -ENODEV;
902 			goto out_unlock;
903 		}
904 	}
905 
906 	region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
907 	region_name = nla_data(region_attr);
908 
909 	if (port)
910 		region = devlink_port_region_get_by_name(port, region_name);
911 	else
912 		region = devlink_region_get_by_name(devlink, region_name);
913 
914 	if (!region) {
915 		NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
916 		err = -EINVAL;
917 		goto out_unlock;
918 	}
919 
920 	snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
921 	if (!snapshot_attr) {
922 		if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
923 			NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
924 			err = -EINVAL;
925 			goto out_unlock;
926 		}
927 
928 		if (!region->ops->read) {
929 			NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
930 			err = -EOPNOTSUPP;
931 			goto out_unlock;
932 		}
933 
934 		if (port)
935 			region_cb = &devlink_region_port_direct_fill;
936 		else
937 			region_cb = &devlink_region_direct_fill;
938 		region_cb_priv = region;
939 	} else {
940 		struct devlink_snapshot *snapshot;
941 		u32 snapshot_id;
942 
943 		if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
944 			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
945 			err = -EINVAL;
946 			goto out_unlock;
947 		}
948 
949 		snapshot_id = nla_get_u32(snapshot_attr);
950 		snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
951 		if (!snapshot) {
952 			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
953 			err = -EINVAL;
954 			goto out_unlock;
955 		}
956 		region_cb = &devlink_region_snapshot_fill;
957 		region_cb_priv = snapshot;
958 	}
959 
960 	if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
961 	    attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
962 		if (!start_offset)
963 			start_offset =
964 				nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
965 
966 		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
967 		end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
968 	}
969 
970 	if (end_offset > region->size)
971 		end_offset = region->size;
972 
973 	/* return 0 if there is no further data to read */
974 	if (start_offset == end_offset) {
975 		err = 0;
976 		goto out_unlock;
977 	}
978 
979 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
980 			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
981 			  DEVLINK_CMD_REGION_READ);
982 	if (!hdr) {
983 		err = -EMSGSIZE;
984 		goto out_unlock;
985 	}
986 
987 	err = devlink_nl_put_handle(skb, devlink);
988 	if (err)
989 		goto nla_put_failure;
990 
991 	if (region->port) {
992 		err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
993 				  region->port->index);
994 		if (err)
995 			goto nla_put_failure;
996 	}
997 
998 	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
999 	if (err)
1000 		goto nla_put_failure;
1001 
1002 	chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
1003 	if (!chunks_attr) {
1004 		err = -EMSGSIZE;
1005 		goto nla_put_failure;
1006 	}
1007 
1008 	err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
1009 					  start_offset, end_offset, &ret_offset,
1010 					  cb->extack);
1011 
1012 	if (err && err != -EMSGSIZE)
1013 		goto nla_put_failure;
1014 
1015 	/* Check if there was any progress done to prevent infinite loop */
1016 	if (ret_offset == start_offset) {
1017 		err = -EINVAL;
1018 		goto nla_put_failure;
1019 	}
1020 
1021 	state->start_offset = ret_offset;
1022 
1023 	nla_nest_end(skb, chunks_attr);
1024 	genlmsg_end(skb, hdr);
1025 	devl_unlock(devlink);
1026 	devlink_put(devlink);
1027 	return skb->len;
1028 
1029 nla_put_failure:
1030 	genlmsg_cancel(skb, hdr);
1031 out_unlock:
1032 	devl_unlock(devlink);
1033 	devlink_put(devlink);
1034 	return err;
1035 }
1036 
1037 /**
1038  * devl_region_create - create a new address region
1039  *
1040  * @devlink: devlink
1041  * @ops: region operations and name
1042  * @region_max_snapshots: Maximum supported number of snapshots for region
1043  * @region_size: size of region
1044  */
devl_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1045 struct devlink_region *devl_region_create(struct devlink *devlink,
1046 					  const struct devlink_region_ops *ops,
1047 					  u32 region_max_snapshots,
1048 					  u64 region_size)
1049 {
1050 	struct devlink_region *region;
1051 
1052 	devl_assert_locked(devlink);
1053 
1054 	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1055 		return ERR_PTR(-EINVAL);
1056 
1057 	if (devlink_region_get_by_name(devlink, ops->name))
1058 		return ERR_PTR(-EEXIST);
1059 
1060 	region = kzalloc(sizeof(*region), GFP_KERNEL);
1061 	if (!region)
1062 		return ERR_PTR(-ENOMEM);
1063 
1064 	region->devlink = devlink;
1065 	region->max_snapshots = region_max_snapshots;
1066 	region->ops = ops;
1067 	region->size = region_size;
1068 	INIT_LIST_HEAD(&region->snapshot_list);
1069 	mutex_init(&region->snapshot_lock);
1070 	list_add_tail(&region->list, &devlink->region_list);
1071 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1072 
1073 	return region;
1074 }
1075 EXPORT_SYMBOL_GPL(devl_region_create);
1076 
1077 /**
1078  *	devlink_region_create - create a new address region
1079  *
1080  *	@devlink: devlink
1081  *	@ops: region operations and name
1082  *	@region_max_snapshots: Maximum supported number of snapshots for region
1083  *	@region_size: size of region
1084  *
1085  *	Context: Takes and release devlink->lock <mutex>.
1086  */
1087 struct devlink_region *
devlink_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1088 devlink_region_create(struct devlink *devlink,
1089 		      const struct devlink_region_ops *ops,
1090 		      u32 region_max_snapshots, u64 region_size)
1091 {
1092 	struct devlink_region *region;
1093 
1094 	devl_lock(devlink);
1095 	region = devl_region_create(devlink, ops, region_max_snapshots,
1096 				    region_size);
1097 	devl_unlock(devlink);
1098 	return region;
1099 }
1100 EXPORT_SYMBOL_GPL(devlink_region_create);
1101 
1102 /**
1103  *	devlink_port_region_create - create a new address region for a port
1104  *
1105  *	@port: devlink port
1106  *	@ops: region operations and name
1107  *	@region_max_snapshots: Maximum supported number of snapshots for region
1108  *	@region_size: size of region
1109  *
1110  *	Context: Takes and release devlink->lock <mutex>.
1111  */
1112 struct devlink_region *
devlink_port_region_create(struct devlink_port * port,const struct devlink_port_region_ops * ops,u32 region_max_snapshots,u64 region_size)1113 devlink_port_region_create(struct devlink_port *port,
1114 			   const struct devlink_port_region_ops *ops,
1115 			   u32 region_max_snapshots, u64 region_size)
1116 {
1117 	struct devlink *devlink = port->devlink;
1118 	struct devlink_region *region;
1119 	int err = 0;
1120 
1121 	ASSERT_DEVLINK_PORT_INITIALIZED(port);
1122 
1123 	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1124 		return ERR_PTR(-EINVAL);
1125 
1126 	devl_lock(devlink);
1127 
1128 	if (devlink_port_region_get_by_name(port, ops->name)) {
1129 		err = -EEXIST;
1130 		goto unlock;
1131 	}
1132 
1133 	region = kzalloc(sizeof(*region), GFP_KERNEL);
1134 	if (!region) {
1135 		err = -ENOMEM;
1136 		goto unlock;
1137 	}
1138 
1139 	region->devlink = devlink;
1140 	region->port = port;
1141 	region->max_snapshots = region_max_snapshots;
1142 	region->port_ops = ops;
1143 	region->size = region_size;
1144 	INIT_LIST_HEAD(&region->snapshot_list);
1145 	mutex_init(&region->snapshot_lock);
1146 	list_add_tail(&region->list, &port->region_list);
1147 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1148 
1149 	devl_unlock(devlink);
1150 	return region;
1151 
1152 unlock:
1153 	devl_unlock(devlink);
1154 	return ERR_PTR(err);
1155 }
1156 EXPORT_SYMBOL_GPL(devlink_port_region_create);
1157 
1158 /**
1159  * devl_region_destroy - destroy address region
1160  *
1161  * @region: devlink region to destroy
1162  */
devl_region_destroy(struct devlink_region * region)1163 void devl_region_destroy(struct devlink_region *region)
1164 {
1165 	struct devlink *devlink = region->devlink;
1166 	struct devlink_snapshot *snapshot, *ts;
1167 
1168 	devl_assert_locked(devlink);
1169 
1170 	/* Free all snapshots of region */
1171 	mutex_lock(&region->snapshot_lock);
1172 	list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
1173 		devlink_region_snapshot_del(region, snapshot);
1174 	mutex_unlock(&region->snapshot_lock);
1175 
1176 	list_del(&region->list);
1177 	mutex_destroy(&region->snapshot_lock);
1178 
1179 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1180 	kfree(region);
1181 }
1182 EXPORT_SYMBOL_GPL(devl_region_destroy);
1183 
1184 /**
1185  *	devlink_region_destroy - destroy address region
1186  *
1187  *	@region: devlink region to destroy
1188  *
1189  *	Context: Takes and release devlink->lock <mutex>.
1190  */
devlink_region_destroy(struct devlink_region * region)1191 void devlink_region_destroy(struct devlink_region *region)
1192 {
1193 	struct devlink *devlink = region->devlink;
1194 
1195 	devl_lock(devlink);
1196 	devl_region_destroy(region);
1197 	devl_unlock(devlink);
1198 }
1199 EXPORT_SYMBOL_GPL(devlink_region_destroy);
1200 
1201 /**
1202  *	devlink_region_snapshot_id_get - get snapshot ID
1203  *
1204  *	This callback should be called when adding a new snapshot,
1205  *	Driver should use the same id for multiple snapshots taken
1206  *	on multiple regions at the same time/by the same trigger.
1207  *
1208  *	The caller of this function must use devlink_region_snapshot_id_put
1209  *	when finished creating regions using this id.
1210  *
1211  *	Returns zero on success, or a negative error code on failure.
1212  *
1213  *	@devlink: devlink
1214  *	@id: storage to return id
1215  */
devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)1216 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1217 {
1218 	return __devlink_region_snapshot_id_get(devlink, id);
1219 }
1220 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1221 
1222 /**
1223  *	devlink_region_snapshot_id_put - put snapshot ID reference
1224  *
1225  *	This should be called by a driver after finishing creating snapshots
1226  *	with an id. Doing so ensures that the ID can later be released in the
1227  *	event that all snapshots using it have been destroyed.
1228  *
1229  *	@devlink: devlink
1230  *	@id: id to release reference on
1231  */
devlink_region_snapshot_id_put(struct devlink * devlink,u32 id)1232 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1233 {
1234 	__devlink_snapshot_id_decrement(devlink, id);
1235 }
1236 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1237 
1238 /**
1239  *	devlink_region_snapshot_create - create a new snapshot
1240  *	This will add a new snapshot of a region. The snapshot
1241  *	will be stored on the region struct and can be accessed
1242  *	from devlink. This is useful for future analyses of snapshots.
1243  *	Multiple snapshots can be created on a region.
1244  *	The @snapshot_id should be obtained using the getter function.
1245  *
1246  *	@region: devlink region of the snapshot
1247  *	@data: snapshot data
1248  *	@snapshot_id: snapshot id to be created
1249  */
devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)1250 int devlink_region_snapshot_create(struct devlink_region *region,
1251 				   u8 *data, u32 snapshot_id)
1252 {
1253 	int err;
1254 
1255 	mutex_lock(&region->snapshot_lock);
1256 	err = __devlink_region_snapshot_create(region, data, snapshot_id);
1257 	mutex_unlock(&region->snapshot_lock);
1258 	return err;
1259 }
1260 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
1261