Skip to content

Commit 340fd60

Browse files
authored
Merge pull request #607 from bgoglin/topo-infos
* add topology-global array of info attrs, available from hwloc_topology_get_infos() * move topology/backend and OS information there instead of in the root object mess
2 parents 6d5614e + 67a36d6 commit 340fd60

File tree

158 files changed

+552
-394
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

158 files changed

+552
-394
lines changed

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ Version 3.0.0
3737
+ The array and count of info attributes are now embedded in the new
3838
struct hwloc_infos_s.
3939
- hwloc_infos_s structures may be modified with hwloc_modify_infos().
40+
- hwloc_topology_get_infos() returns the new topology-global array
41+
of info attributes.
42+
. Several info attributes previously stored in the root object are
43+
now topology attributes (e.g. information about hwloc, about the
44+
discovery, operating system information returned by uname).
45+
See "Custom string infos" in the documentation for details.
4046
- hwloc_cpukinds_get_info() and hwloc_cpukinds_register() now manipulate
4147
infos as such a structure.
4248
* Tools

doc/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ man3_object_info_attrs_DATA = \
356356
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_ADD.3 \
357357
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_ADD_UNIQUE.3 \
358358
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_REPLACE.3 \
359-
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_REMOVE.3
359+
$(DOX_MAN_DIR)/man3/HWLOC_MODIFY_INFOS_OP_REMOVE.3 \
360+
$(DOX_MAN_DIR)/man3/hwloc_topology_get_infos.3
360361

361362
man3_cpubindingdir = $(man3dir)
362363
man3_cpubinding_DATA = \

doc/hwloc.doxy

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,9 @@ or using the hwloc_obj_get_info_by_name().
19721972
The user may additionally add new name-value pairs to any object using
19731973
hwloc_obj_add_info(), hwloc_modify_infos() or the \ref cli_hwloc_annotate program.
19741974

1975+
Some topology-global info attributes (not specific to some objects)
1976+
are also accessible using hwloc_topology_get_infos().
1977+
19751978
Here is a non-exhaustive list of attributes that may be automatically
19761979
added by hwloc.
19771980
Note that these attributes heavily depend on the ability of the
@@ -2020,7 +2023,7 @@ See doc/examples/get-knl-modes.c in the source directory for an example of retri
20202023
\endhtmlonly
20212024
\subsection attributes_info_os Operating System Information
20222025

2023-
These info attributes are attached to the root object (Machine).
2026+
These info attributes are attached to the topology itself.
20242027

20252028
<dl>
20262029
<dt>OSName, OSRelease, OSVersion, HostName, Architecture</dt>
@@ -2040,12 +2043,12 @@ placed.
20402043
\htmlonly
20412044
</div><div class="subsection" id="attributes_info_hwloc">
20422045
\endhtmlonly
2043-
\subsection attributes_info_hwloc hwloc Information
2046+
\subsection attributes_info_hwloc hwloc Topology Information
20442047

2045-
Unless specified, these info attributes are attached to the root object (Machine).
2048+
These info attributes are attached to the topology itself.
20462049

20472050
<dl>
2048-
<dt>Backend (topology root object)</dt>
2051+
<dt>Backend</dt>
20492052
<dd>The name of a hwloc backend/component that added objects in the topology.
20502053
If several components were combined, multiple Backend pairs may exist,
20512054
with different values, for instance <tt>x86</tt>, <tt>Linux</tt> and
@@ -2316,9 +2319,9 @@ that have a special meaning:
23162319
<div class="section">
23172320
\endhtmlonly
23182321

2319-
Besides the hierarchy of objects and individual object attributes
2320-
(see \ref attributes), hwloc may also expose finer information about
2321-
the hardware organization.
2322+
Besides the hierarchy of objects, individual object attributes
2323+
and topology info attributes (see \ref attributes),
2324+
hwloc may also expose finer information about the hardware organization.
23222325

23232326

23242327
\htmlonly

hwloc/diff.c

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ static int hwloc_append_diff_too_complex(hwloc_obj_t obj1,
6666
return 0;
6767
}
6868

69-
static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj,
69+
static int hwloc_append_diff_obj_attr_string(hwloc_topology_t topology,
70+
hwloc_obj_t obj,
7071
hwloc_topology_diff_obj_attr_type_t type,
7172
const char *name,
7273
const char *oldvalue,
@@ -80,8 +81,8 @@ static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj,
8081
return -1;
8182

8283
newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
83-
newdiff->obj_attr.obj_depth = obj->depth;
84-
newdiff->obj_attr.obj_index = obj->logical_index;
84+
newdiff->obj_attr.obj_depth = obj ? obj->depth : (int) topology->nb_levels;
85+
newdiff->obj_attr.obj_index = obj ? obj->logical_index : 0;
8586
newdiff->obj_attr.diff.string.type = type;
8687
newdiff->obj_attr.diff.string.name = name ? strdup(name) : NULL;
8788
newdiff->obj_attr.diff.string.oldvalue = oldvalue ? strdup(oldvalue) : NULL;
@@ -155,7 +156,7 @@ hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1,
155156

156157
if ((!obj1->name) != (!obj2->name)
157158
|| (obj1->name && strcmp(obj1->name, obj2->name))) {
158-
err = hwloc_append_diff_obj_attr_string(obj1,
159+
err = hwloc_append_diff_obj_attr_string(topo1, obj1,
159160
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
160161
NULL,
161162
obj1->name,
@@ -219,7 +220,7 @@ hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1,
219220
if (strcmp(info1->name, info2->name))
220221
goto out_too_complex;
221222
if (strcmp(info1->value, info2->value)) {
222-
err = hwloc_append_diff_obj_attr_string(obj1,
223+
err = hwloc_append_diff_obj_attr_string(topo1, obj1,
223224
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO,
224225
info1->name,
225226
info1->value,
@@ -338,6 +339,27 @@ int hwloc_topology_diff_build(hwloc_topology_t topo1,
338339
goto roottoocomplex;
339340
}
340341

342+
/* topology infos */
343+
if (!err) {
344+
if (topo1->infos.count != topo2->infos.count)
345+
goto roottoocomplex;
346+
for(i=0; i<topo1->infos.count; i++) {
347+
struct hwloc_info_s *info1 = &topo1->infos.array[i], *info2 = &topo2->infos.array[i];
348+
if (strcmp(info1->name, info2->name))
349+
goto roottoocomplex;
350+
if (strcmp(info1->value, info2->value)) {
351+
err = hwloc_append_diff_obj_attr_string(topo1, NULL,
352+
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO,
353+
info1->name,
354+
info1->value,
355+
info2->value,
356+
diffp, &lastdiff);
357+
if (err < 0)
358+
return err;
359+
}
360+
}
361+
}
362+
341363
if (!err) {
342364
/* distances */
343365
hwloc_internal_distances_refresh(topo1);
@@ -458,15 +480,22 @@ hwloc_apply_diff_one(hwloc_topology_t topology,
458480
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: {
459481
struct hwloc_topology_diff_obj_attr_s *obj_attr = &diff->obj_attr;
460482
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, obj_attr->obj_depth, obj_attr->obj_index);
461-
if (!obj)
462-
return -1;
483+
struct hwloc_infos_s *infos;
484+
if (obj)
485+
infos = &obj->infos;
486+
else if (obj_attr->obj_depth == (int) topology->nb_levels)
487+
infos = &topology->infos;
488+
else
489+
return -1;
463490

464491
switch (obj_attr->diff.generic.type) {
465492
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: {
466493
hwloc_obj_t tmpobj;
467494
hwloc_uint64_t oldvalue = reverse ? obj_attr->diff.uint64.newvalue : obj_attr->diff.uint64.oldvalue;
468495
hwloc_uint64_t newvalue = reverse ? obj_attr->diff.uint64.oldvalue : obj_attr->diff.uint64.newvalue;
469496
hwloc_uint64_t valuediff = newvalue - oldvalue;
497+
if (!obj)
498+
return -1;
470499
if (obj->type != HWLOC_OBJ_NUMANODE)
471500
return -1;
472501
if (obj->attr->numanode.local_memory != oldvalue)
@@ -482,7 +511,9 @@ hwloc_apply_diff_one(hwloc_topology_t topology,
482511
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: {
483512
const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
484513
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
485-
if (!obj->name || strcmp(obj->name, oldvalue))
514+
if (!obj)
515+
return -1;
516+
if (!obj->name || strcmp(obj->name, oldvalue))
486517
return -1;
487518
free(obj->name);
488519
obj->name = strdup(newvalue);
@@ -494,8 +525,8 @@ hwloc_apply_diff_one(hwloc_topology_t topology,
494525
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
495526
unsigned i;
496527
int found = 0;
497-
for(i=0; i<obj->infos.count; i++) {
498-
struct hwloc_info_s *info = &obj->infos.array[i];
528+
for(i=0; i<infos->count; i++) {
529+
struct hwloc_info_s *info = &infos->array[i];
499530
if (!strcmp(info->name, name)
500531
&& !strcmp(info->value, oldvalue)) {
501532
free(info->value);

hwloc/hwloc2.dtd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<!--
22
Copyright © 2009 CNRS
3-
Copyright © 2009-2022 Inria. All rights reserved.
3+
Copyright © 2009-2023 Inria. All rights reserved.
44
Copyright © 2009-2011 Université Bordeaux.
55
See COPYING in top-level directory.
66

77
This is the DTD for hwloc v2.x XMLs.
88
-->
99

10-
<!ELEMENT topology (object+,distances2*,distances2hetero*,support*,memattr*,cpukind*)>
10+
<!ELEMENT topology (object+,distances2*,distances2hetero*,support*,memattr*,cpukind*,info*)>
1111
<!ATTLIST topology version CDATA "">
1212

1313
<!ELEMENT object (page_type*,info*,userdata*,object*)>

hwloc/misc.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright © 2009 CNRS
3-
* Copyright © 2009-2022 Inria. All rights reserved.
3+
* Copyright © 2009-2023 Inria. All rights reserved.
44
* Copyright © 2009-2010 Université Bordeaux
55
* Copyright © 2009-2018 Cisco Systems, Inc. All rights reserved.
66
* See COPYING in top-level directory.
@@ -86,7 +86,7 @@ void hwloc_add_uname_info(struct hwloc_topology *topology __hwloc_attribute_unus
8686
#ifdef HAVE_UNAME
8787
struct utsname _utsname, *utsname;
8888

89-
if (hwloc_obj_get_info_by_name(topology->levels[0][0], "OSName"))
89+
if (hwloc_get_info_by_name(&topology->infos, "OSName"))
9090
/* don't annotate twice */
9191
return;
9292

@@ -99,15 +99,15 @@ void hwloc_add_uname_info(struct hwloc_topology *topology __hwloc_attribute_unus
9999
}
100100

101101
if (*utsname->sysname)
102-
hwloc_obj_add_info(topology->levels[0][0], "OSName", utsname->sysname);
102+
hwloc__add_info(&topology->infos, "OSName", utsname->sysname);
103103
if (*utsname->release)
104-
hwloc_obj_add_info(topology->levels[0][0], "OSRelease", utsname->release);
104+
hwloc__add_info(&topology->infos, "OSRelease", utsname->release);
105105
if (*utsname->version)
106-
hwloc_obj_add_info(topology->levels[0][0], "OSVersion", utsname->version);
106+
hwloc__add_info(&topology->infos, "OSVersion", utsname->version);
107107
if (*utsname->nodename)
108-
hwloc_obj_add_info(topology->levels[0][0], "HostName", utsname->nodename);
108+
hwloc__add_info(&topology->infos, "HostName", utsname->nodename);
109109
if (*utsname->machine)
110-
hwloc_obj_add_info(topology->levels[0][0], "Architecture", utsname->machine);
110+
hwloc__add_info(&topology->infos, "Architecture", utsname->machine);
111111
#endif /* HAVE_UNAME */
112112
}
113113

hwloc/topology-aix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ hwloc_look_aix(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)
817817
}
818818
}
819819

820-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "AIX");
820+
hwloc__add_info(&topology->infos, "Backend", "AIX");
821821
hwloc_add_uname_info(topology, NULL);
822822
return 0;
823823
}

hwloc/topology-cuda.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ hwloc_cuda_discover(struct hwloc_backend *backend, struct hwloc_disc_status *dst
142142
}
143143

144144
if (added > 0)
145-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "CUDA");
145+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "CUDA");
146146
return 0;
147147
}
148148

hwloc/topology-darwin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ hwloc_look_darwin(struct hwloc_backend *backend, struct hwloc_disc_status *dstat
903903
else
904904
hwloc__darwin_cpukinds_register(topology, &kinds);
905905

906-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Darwin");
906+
hwloc__add_info(&topology->infos, "Backend", "Darwin");
907907
hwloc_add_uname_info(topology, NULL);
908908
return 0;
909909
}

hwloc/topology-freebsd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ hwloc_look_freebsd(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
553553
}
554554

555555
if (data->need_global_infos) {
556-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "FreeBSD");
556+
hwloc__add_info(&topology->infos, "Backend", "FreeBSD");
557557
hwloc_add_uname_info(topology, NULL);
558558
data->need_global_infos = 0;
559559
}

hwloc/topology-gl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ hwloc_gl_discover(struct hwloc_backend *backend, struct hwloc_disc_status *dstat
142142
}
143143

144144
if (added)
145-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "GL");
145+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "GL");
146146
return 0;
147147
}
148148

hwloc/topology-hardwired.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology)
7373
topology->support.discovery->pu = 1;
7474
hwloc_setup_pu_level(topology, 8);
7575

76-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "hardwired:K-computer");
76+
hwloc__add_info(&topology->infos, "Backend", "hardwired:K-computer");
7777
return 0;
7878
}
7979

@@ -143,7 +143,7 @@ int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology)
143143
topology->support.discovery->pu = 1;
144144
hwloc_setup_pu_level(topology, 16);
145145

146-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "hardwired:FX10");
146+
hwloc__add_info(&topology->infos, "Backend", "hardwired:FX10");
147147
return 0;
148148
}
149149

@@ -223,6 +223,6 @@ int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology)
223223
topology->support.discovery->pu = 1;
224224
hwloc_setup_pu_level(topology, 34);
225225

226-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "hardwired:FX100");
226+
hwloc__add_info(&topology->infos, "Backend", "hardwired:FX100");
227227
return 0;
228228
}

hwloc/topology-hpux.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ hwloc_look_hpux(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus
271271
topology->support.discovery->numa = 1;
272272
/* don't set disallowed_{pu,numa} since we don't set the allowed sets */
273273

274-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "HP-UX");
274+
hwloc__add_info(&topology->infos, "Backend", "HP-UX");
275275
hwloc_add_uname_info(topology, NULL);
276276

277277
free(nodes);

hwloc/topology-levelzero.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ hwloc_levelzero_discover(struct hwloc_backend *backend, struct hwloc_disc_status
828828
free(drh);
829829

830830
if (added)
831-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "LevelZero");
831+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "LevelZero");
832832
return 0;
833833
}
834834

hwloc/topology-linux.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,7 @@ static int hwloc_linux_get_allowed_resources_hook(hwloc_topology_t topology)
21632163

21642164
hwloc_linux__get_allowed_resources(topology, fsroot_path, root_fd, &cpuset_name);
21652165
if (cpuset_name) {
2166-
hwloc__replace_infos(&topology->levels[0][0]->infos,
2166+
hwloc__replace_infos(&topology->infos,
21672167
"LinuxCgroup", cpuset_name);
21682168
free(cpuset_name);
21692169
}
@@ -5869,7 +5869,7 @@ hwloc_linuxfs_look_cpu(struct hwloc_backend *backend, struct hwloc_disc_status *
58695869
nbnodes = 0;
58705870

58715871
if (cpuset_name) {
5872-
hwloc_obj_add_info(topology->levels[0][0], "LinuxCgroup", cpuset_name);
5872+
hwloc__add_info(&topology->infos, "LinuxCgroup", cpuset_name);
58735873
free(cpuset_name);
58745874
}
58755875

@@ -7360,7 +7360,7 @@ hwloc_look_linuxfs(struct hwloc_backend *backend, struct hwloc_disc_status *dsta
73607360
out:
73617361
if (data->need_global_infos) {
73627362
hwloc__get_dmi_id_info(data, topology->levels[0][0]);
7363-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Linux");
7363+
hwloc__add_info(&topology->infos, "Backend", "Linux");
73647364
/* data->utsname was filled with real uname or \0, we can safely pass it */
73657365
hwloc_add_uname_info(topology, &data->utsname);
73667366
data->need_global_infos = 0;

hwloc/topology-netbsd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ hwloc_look_netbsd(struct hwloc_backend *backend, struct hwloc_disc_status *dstat
163163
topology->machine_memory.local_memory = memsize;;
164164

165165
/* Add NetBSD specific information */
166-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "NetBSD");
166+
hwloc__add_info(&topology->infos, "Backend", "NetBSD");
167167
hwloc_add_uname_info(topology, NULL);
168168
return 0;
169169
}

hwloc/topology-noos.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ hwloc_look_noos(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus
3535
nbprocs = 1;
3636
hwloc_alloc_root_sets(topology->levels[0][0]);
3737
hwloc_setup_pu_level(topology, nbprocs);
38-
hwloc_obj_add_info(topology->levels[0][0], "Backend", "noOS");
38+
hwloc__add_info(&topology->infos, "Backend", "noOS");
3939
}
4040

4141
memsize = hwloc_fallback_memsize();

hwloc/topology-nvml.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ hwloc_nvml_discover(struct hwloc_backend *backend, struct hwloc_disc_status *dst
399399
nvmlShutdown();
400400

401401
if (added)
402-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "NVML");
402+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "NVML");
403403
return 0;
404404
}
405405

hwloc/topology-opencl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ hwloc_opencl_discover(struct hwloc_backend *backend, struct hwloc_disc_status *d
185185
free(platform_ids);
186186

187187
if (added)
188-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "OpenCL");
188+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "OpenCL");
189189
return 0;
190190
}
191191

hwloc/topology-pci.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ hwloc_look_pci(struct hwloc_backend *backend, struct hwloc_disc_status *dstatus)
379379
backend->phases &= HWLOC_DISC_PHASE_ANNOTATE;
380380

381381
if (added)
382-
hwloc_obj_add_info(hwloc_get_root_obj(topology), "Backend", "PCI");
382+
hwloc_modify_infos(hwloc_topology_get_infos(topology), HWLOC_MODIFY_INFOS_OP_ADD, "Backend", "PCI");
383383
return 0;
384384
}
385385

0 commit comments

Comments
 (0)