xref: /linux/net/devlink/region.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
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 
238 	if (!__devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
239 		return;
240 
241 	msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
242 	if (IS_ERR(msg))
243 		return;
244 
245 	devlink_nl_notify_send(devlink, msg);
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_region_del_doit(struct sk_buff * skb,struct genl_info * info)591 int devlink_nl_region_del_doit(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_region_new_doit(struct sk_buff * skb,struct genl_info * info)636 int devlink_nl_region_new_doit(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_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)866 int devlink_nl_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 					      false);
888 	if (IS_ERR(devlink))
889 		return PTR_ERR(devlink);
890 
891 	if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
892 		NL_SET_ERR_MSG(cb->extack, "No region name provided");
893 		err = -EINVAL;
894 		goto out_unlock;
895 	}
896 
897 	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
898 		index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
899 
900 		port = devlink_port_get_by_index(devlink, index);
901 		if (!port) {
902 			err = -ENODEV;
903 			goto out_unlock;
904 		}
905 	}
906 
907 	region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
908 	region_name = nla_data(region_attr);
909 
910 	if (port)
911 		region = devlink_port_region_get_by_name(port, region_name);
912 	else
913 		region = devlink_region_get_by_name(devlink, region_name);
914 
915 	if (!region) {
916 		NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
917 		err = -EINVAL;
918 		goto out_unlock;
919 	}
920 
921 	snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
922 	if (!snapshot_attr) {
923 		if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
924 			NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
925 			err = -EINVAL;
926 			goto out_unlock;
927 		}
928 
929 		if (!region->ops->read) {
930 			NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
931 			err = -EOPNOTSUPP;
932 			goto out_unlock;
933 		}
934 
935 		if (port)
936 			region_cb = &devlink_region_port_direct_fill;
937 		else
938 			region_cb = &devlink_region_direct_fill;
939 		region_cb_priv = region;
940 	} else {
941 		struct devlink_snapshot *snapshot;
942 		u32 snapshot_id;
943 
944 		if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
945 			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
946 			err = -EINVAL;
947 			goto out_unlock;
948 		}
949 
950 		snapshot_id = nla_get_u32(snapshot_attr);
951 		snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
952 		if (!snapshot) {
953 			NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
954 			err = -EINVAL;
955 			goto out_unlock;
956 		}
957 		region_cb = &devlink_region_snapshot_fill;
958 		region_cb_priv = snapshot;
959 	}
960 
961 	if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
962 	    attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
963 		if (!start_offset)
964 			start_offset =
965 				nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
966 
967 		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
968 		end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
969 	}
970 
971 	if (end_offset > region->size)
972 		end_offset = region->size;
973 
974 	/* return 0 if there is no further data to read */
975 	if (start_offset == end_offset) {
976 		err = 0;
977 		goto out_unlock;
978 	}
979 
980 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
981 			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
982 			  DEVLINK_CMD_REGION_READ);
983 	if (!hdr) {
984 		err = -EMSGSIZE;
985 		goto out_unlock;
986 	}
987 
988 	err = devlink_nl_put_handle(skb, devlink);
989 	if (err)
990 		goto nla_put_failure;
991 
992 	if (region->port) {
993 		err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
994 				  region->port->index);
995 		if (err)
996 			goto nla_put_failure;
997 	}
998 
999 	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
1000 	if (err)
1001 		goto nla_put_failure;
1002 
1003 	chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
1004 	if (!chunks_attr) {
1005 		err = -EMSGSIZE;
1006 		goto nla_put_failure;
1007 	}
1008 
1009 	err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
1010 					  start_offset, end_offset, &ret_offset,
1011 					  cb->extack);
1012 
1013 	if (err && err != -EMSGSIZE)
1014 		goto nla_put_failure;
1015 
1016 	/* Check if there was any progress done to prevent infinite loop */
1017 	if (ret_offset == start_offset) {
1018 		err = -EINVAL;
1019 		goto nla_put_failure;
1020 	}
1021 
1022 	state->start_offset = ret_offset;
1023 
1024 	nla_nest_end(skb, chunks_attr);
1025 	genlmsg_end(skb, hdr);
1026 	devl_unlock(devlink);
1027 	devlink_put(devlink);
1028 	return skb->len;
1029 
1030 nla_put_failure:
1031 	genlmsg_cancel(skb, hdr);
1032 out_unlock:
1033 	devl_unlock(devlink);
1034 	devlink_put(devlink);
1035 	return err;
1036 }
1037 
1038 /**
1039  * devl_region_create - create a new address region
1040  *
1041  * @devlink: devlink
1042  * @ops: region operations and name
1043  * @region_max_snapshots: Maximum supported number of snapshots for region
1044  * @region_size: size of region
1045  */
devl_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1046 struct devlink_region *devl_region_create(struct devlink *devlink,
1047 					  const struct devlink_region_ops *ops,
1048 					  u32 region_max_snapshots,
1049 					  u64 region_size)
1050 {
1051 	struct devlink_region *region;
1052 
1053 	devl_assert_locked(devlink);
1054 
1055 	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1056 		return ERR_PTR(-EINVAL);
1057 
1058 	if (devlink_region_get_by_name(devlink, ops->name))
1059 		return ERR_PTR(-EEXIST);
1060 
1061 	region = kzalloc(sizeof(*region), GFP_KERNEL);
1062 	if (!region)
1063 		return ERR_PTR(-ENOMEM);
1064 
1065 	region->devlink = devlink;
1066 	region->max_snapshots = region_max_snapshots;
1067 	region->ops = ops;
1068 	region->size = region_size;
1069 	INIT_LIST_HEAD(&region->snapshot_list);
1070 	mutex_init(&region->snapshot_lock);
1071 	list_add_tail(&region->list, &devlink->region_list);
1072 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1073 
1074 	return region;
1075 }
1076 EXPORT_SYMBOL_GPL(devl_region_create);
1077 
1078 /**
1079  *	devlink_region_create - create a new address region
1080  *
1081  *	@devlink: devlink
1082  *	@ops: region operations and name
1083  *	@region_max_snapshots: Maximum supported number of snapshots for region
1084  *	@region_size: size of region
1085  *
1086  *	Context: Takes and release devlink->lock <mutex>.
1087  */
1088 struct devlink_region *
devlink_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1089 devlink_region_create(struct devlink *devlink,
1090 		      const struct devlink_region_ops *ops,
1091 		      u32 region_max_snapshots, u64 region_size)
1092 {
1093 	struct devlink_region *region;
1094 
1095 	devl_lock(devlink);
1096 	region = devl_region_create(devlink, ops, region_max_snapshots,
1097 				    region_size);
1098 	devl_unlock(devlink);
1099 	return region;
1100 }
1101 EXPORT_SYMBOL_GPL(devlink_region_create);
1102 
1103 /**
1104  *	devlink_port_region_create - create a new address region for a port
1105  *
1106  *	@port: devlink port
1107  *	@ops: region operations and name
1108  *	@region_max_snapshots: Maximum supported number of snapshots for region
1109  *	@region_size: size of region
1110  *
1111  *	Context: Takes and release devlink->lock <mutex>.
1112  */
1113 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)1114 devlink_port_region_create(struct devlink_port *port,
1115 			   const struct devlink_port_region_ops *ops,
1116 			   u32 region_max_snapshots, u64 region_size)
1117 {
1118 	struct devlink *devlink = port->devlink;
1119 	struct devlink_region *region;
1120 	int err = 0;
1121 
1122 	ASSERT_DEVLINK_PORT_INITIALIZED(port);
1123 
1124 	if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1125 		return ERR_PTR(-EINVAL);
1126 
1127 	devl_lock(devlink);
1128 
1129 	if (devlink_port_region_get_by_name(port, ops->name)) {
1130 		err = -EEXIST;
1131 		goto unlock;
1132 	}
1133 
1134 	region = kzalloc(sizeof(*region), GFP_KERNEL);
1135 	if (!region) {
1136 		err = -ENOMEM;
1137 		goto unlock;
1138 	}
1139 
1140 	region->devlink = devlink;
1141 	region->port = port;
1142 	region->max_snapshots = region_max_snapshots;
1143 	region->port_ops = ops;
1144 	region->size = region_size;
1145 	INIT_LIST_HEAD(&region->snapshot_list);
1146 	mutex_init(&region->snapshot_lock);
1147 	list_add_tail(&region->list, &port->region_list);
1148 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1149 
1150 	devl_unlock(devlink);
1151 	return region;
1152 
1153 unlock:
1154 	devl_unlock(devlink);
1155 	return ERR_PTR(err);
1156 }
1157 EXPORT_SYMBOL_GPL(devlink_port_region_create);
1158 
1159 /**
1160  * devl_region_destroy - destroy address region
1161  *
1162  * @region: devlink region to destroy
1163  */
devl_region_destroy(struct devlink_region * region)1164 void devl_region_destroy(struct devlink_region *region)
1165 {
1166 	struct devlink *devlink = region->devlink;
1167 	struct devlink_snapshot *snapshot, *ts;
1168 
1169 	devl_assert_locked(devlink);
1170 
1171 	/* Free all snapshots of region */
1172 	mutex_lock(&region->snapshot_lock);
1173 	list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
1174 		devlink_region_snapshot_del(region, snapshot);
1175 	mutex_unlock(&region->snapshot_lock);
1176 
1177 	list_del(&region->list);
1178 	mutex_destroy(&region->snapshot_lock);
1179 
1180 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1181 	kfree(region);
1182 }
1183 EXPORT_SYMBOL_GPL(devl_region_destroy);
1184 
1185 /**
1186  *	devlink_region_destroy - destroy address region
1187  *
1188  *	@region: devlink region to destroy
1189  *
1190  *	Context: Takes and release devlink->lock <mutex>.
1191  */
devlink_region_destroy(struct devlink_region * region)1192 void devlink_region_destroy(struct devlink_region *region)
1193 {
1194 	struct devlink *devlink = region->devlink;
1195 
1196 	devl_lock(devlink);
1197 	devl_region_destroy(region);
1198 	devl_unlock(devlink);
1199 }
1200 EXPORT_SYMBOL_GPL(devlink_region_destroy);
1201 
1202 /**
1203  *	devlink_region_snapshot_id_get - get snapshot ID
1204  *
1205  *	This callback should be called when adding a new snapshot,
1206  *	Driver should use the same id for multiple snapshots taken
1207  *	on multiple regions at the same time/by the same trigger.
1208  *
1209  *	The caller of this function must use devlink_region_snapshot_id_put
1210  *	when finished creating regions using this id.
1211  *
1212  *	Returns zero on success, or a negative error code on failure.
1213  *
1214  *	@devlink: devlink
1215  *	@id: storage to return id
1216  */
devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)1217 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1218 {
1219 	return __devlink_region_snapshot_id_get(devlink, id);
1220 }
1221 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1222 
1223 /**
1224  *	devlink_region_snapshot_id_put - put snapshot ID reference
1225  *
1226  *	This should be called by a driver after finishing creating snapshots
1227  *	with an id. Doing so ensures that the ID can later be released in the
1228  *	event that all snapshots using it have been destroyed.
1229  *
1230  *	@devlink: devlink
1231  *	@id: id to release reference on
1232  */
devlink_region_snapshot_id_put(struct devlink * devlink,u32 id)1233 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1234 {
1235 	__devlink_snapshot_id_decrement(devlink, id);
1236 }
1237 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1238 
1239 /**
1240  *	devlink_region_snapshot_create - create a new snapshot
1241  *	This will add a new snapshot of a region. The snapshot
1242  *	will be stored on the region struct and can be accessed
1243  *	from devlink. This is useful for future analyses of snapshots.
1244  *	Multiple snapshots can be created on a region.
1245  *	The @snapshot_id should be obtained using the getter function.
1246  *
1247  *	@region: devlink region of the snapshot
1248  *	@data: snapshot data
1249  *	@snapshot_id: snapshot id to be created
1250  */
devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)1251 int devlink_region_snapshot_create(struct devlink_region *region,
1252 				   u8 *data, u32 snapshot_id)
1253 {
1254 	int err;
1255 
1256 	mutex_lock(&region->snapshot_lock);
1257 	err = __devlink_region_snapshot_create(region, data, snapshot_id);
1258 	mutex_unlock(&region->snapshot_lock);
1259 	return err;
1260 }
1261 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
1262