region.c 31 KB

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