|
1 /* |
|
2 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. |
|
3 * |
|
4 * This software is available to you under a choice of one of two |
|
5 * licenses. You may choose to be licensed under the terms of the GNU |
|
6 * General Public License (GPL) Version 2, available from the file |
|
7 * COPYING in the main directory of this source tree, or the |
|
8 * OpenIB.org BSD license below: |
|
9 * |
|
10 * Redistribution and use in source and binary forms, with or |
|
11 * without modification, are permitted provided that the following |
|
12 * conditions are met: |
|
13 * |
|
14 * - Redistributions of source code must retain the above |
|
15 * copyright notice, this list of conditions and the following |
|
16 * disclaimer. |
|
17 * |
|
18 * - Redistributions in binary form must reproduce the above |
|
19 * copyright notice, this list of conditions and the following |
|
20 * disclaimer in the documentation and/or other materials |
|
21 * provided with the distribution. |
|
22 * |
|
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
30 * SOFTWARE. |
|
31 */ |
|
32 |
|
33 /* |
|
34 * OFED Solaris wrapper |
|
35 */ |
|
36 #if defined(__SVR4) && defined(__sun) |
|
37 |
|
38 #pragma ident "@(#)solaris_set_nodedesc.c 1.2 11/01/25 SMI" |
|
39 |
|
40 #include <stdio.h> |
|
41 #include <stdlib.h> |
|
42 #include <unistd.h> |
|
43 #include <sys/types.h> |
|
44 #include <sys/stat.h> |
|
45 #include <sys/sysmacros.h> |
|
46 #include <sys/queue.h> |
|
47 #include <fcntl.h> |
|
48 #include <ctype.h> |
|
49 #include <string.h> |
|
50 #include <strings.h> |
|
51 #include <getopt.h> |
|
52 #include <libdevinfo.h> |
|
53 #include <sys/utsname.h> |
|
54 |
|
55 #include <infiniband/verbs.h> |
|
56 #include <infiniband/arch.h> |
|
57 |
|
58 #include <sys/ib/adapters/tavor/tavor_ioctl.h> |
|
59 #include <sys/ib/adapters/hermon/hermon_ioctl.h> |
|
60 |
|
61 /* |
|
62 * Local defines for HCA driver IOCTLs, used while |
|
63 * building on build system without the change in |
|
64 * header files. |
|
65 */ |
|
66 #ifdef HERMON_NODEDESC_UPDATE_STR |
|
67 #define HERMON_NODEDESC_UPDATE_STRING 0x00000001 |
|
68 #endif |
|
69 #ifndef HERMON_NODEDESC_UPDATE_HCA_STRING |
|
70 #define HERMON_NODEDESC_UPDATE_HCA_STRING 0x00000002 |
|
71 #undef HERMON_NODEDESC_UPDATE_HCA_MAP |
|
72 #endif |
|
73 #ifndef HERMON_IOCTL_GET_NODEDESC |
|
74 #define HERMON_IOCTL_GET_NODEDESC (('t' << 8) | 0x31) |
|
75 #endif |
|
76 |
|
77 #ifdef TAVOR_NODEDESC_UPDATE_STR |
|
78 #define TAVOR_NODEDESC_UPDATE_STRING 0x00000001 |
|
79 #endif |
|
80 #ifndef TAVOR_NODEDESC_UPDATE_HCA_STRING |
|
81 #define TAVOR_NODEDESC_UPDATE_HCA_STRING 0x00000002 |
|
82 #undef TAVOR_NODEDESC_UPDATE_HCA_MAP |
|
83 #endif |
|
84 #ifndef TAVOR_IOCTL_GET_NODEDESC |
|
85 #define TAVOR_IOCTL_GET_NODEDESC (('t' << 8) | 0x31) |
|
86 #endif |
|
87 |
|
88 #define NODEDESC_UPDATE_STRING 0x00000001 |
|
89 #define NODEDESC_UPDATE_HCA_STRING 0x00000002 |
|
90 #define NODEDESC_READ 0x80000000 |
|
91 |
|
92 #include "ibdiag_common.h" |
|
93 |
|
94 static char *devpath_prefix = "/devices"; |
|
95 static char *devpath_suffix = ":devctl"; |
|
96 static char *ib_hca_driver_list[] = { |
|
97 "tavor", "hermon", NULL |
|
98 }; |
|
99 static di_node_t di_rootnode; |
|
100 char *argv0 = "solaris_set_nodedesc"; |
|
101 |
|
102 #define MAX_HCAS 32 |
|
103 static struct nodedesc_read_info_s { |
|
104 boolean_t info_valid; |
|
105 uint64_t guid; |
|
106 char nd_string[64]; |
|
107 boolean_t ofuv_name_valid; |
|
108 char ofuv_name[64]; |
|
109 } nd_read_info_arr[MAX_HCAS]; |
|
110 int nd_read_info_cnt; |
|
111 |
|
112 static void |
|
113 print_read_info() |
|
114 { |
|
115 int j; |
|
116 |
|
117 for (j = 0; j < nd_read_info_cnt; j++) { |
|
118 if (nd_read_info_arr[j].info_valid == B_FALSE || |
|
119 nd_read_info_arr[j].ofuv_name_valid == B_FALSE) |
|
120 continue; |
|
121 printf("%s: %-16s\n", |
|
122 nd_read_info_arr[j].ofuv_name, |
|
123 nd_read_info_arr[j].nd_string); |
|
124 } |
|
125 } |
|
126 |
|
127 static void |
|
128 update_read_info_hwnames() |
|
129 { |
|
130 struct ibv_device **dev_list; |
|
131 int num_devices, i; |
|
132 uint64_t dev_guid; |
|
133 char *dev_name; |
|
134 size_t dev_name_len; |
|
135 |
|
136 dev_list = ibv_get_device_list(&num_devices); |
|
137 if (!dev_list) { |
|
138 fprintf(stderr, "No IB devices found\n"); |
|
139 return; |
|
140 } |
|
141 |
|
142 for (i = 0; i < num_devices; ++i) { |
|
143 int j; |
|
144 |
|
145 dev_guid = (uint64_t)ntohll(ibv_get_device_guid(dev_list[i])); |
|
146 dev_name = (char *)ibv_get_device_name(dev_list[i]); |
|
147 dev_name_len = strlen(dev_name) + 1; |
|
148 for (j = 0; j < nd_read_info_cnt; j++) { |
|
149 if (nd_read_info_arr[j].info_valid == B_TRUE && |
|
150 nd_read_info_arr[j].guid == dev_guid) { |
|
151 memcpy(nd_read_info_arr[j].ofuv_name, |
|
152 dev_name, dev_name_len); |
|
153 nd_read_info_arr[j].ofuv_name_valid = B_TRUE; |
|
154 break; |
|
155 } |
|
156 } |
|
157 } |
|
158 |
|
159 ibv_free_device_list(dev_list); |
|
160 } |
|
161 |
|
162 static void |
|
163 add_read_info_arr(char *nd_str, uint64_t guid) |
|
164 { |
|
165 size_t nd_len; |
|
166 |
|
167 nd_len = strlen(nd_str) + 1; |
|
168 nd_read_info_arr[nd_read_info_cnt].info_valid = B_TRUE; |
|
169 nd_read_info_arr[nd_read_info_cnt].guid = guid; |
|
170 memcpy(nd_read_info_arr[nd_read_info_cnt].nd_string, nd_str, nd_len); |
|
171 nd_read_info_cnt++; |
|
172 |
|
173 } |
|
174 |
|
175 static void |
|
176 do_driver_read_ioctl(char *drivername) |
|
177 { |
|
178 di_node_t hcanode, childnode; |
|
179 char *devpath; |
|
180 char *access_devname; |
|
181 int devlength, devfd, rc = -1; |
|
182 uint64_t *hca_guid; |
|
183 |
|
184 if ((hcanode = di_drv_first_node(drivername, di_rootnode)) |
|
185 == DI_NODE_NIL) { |
|
186 return; |
|
187 } |
|
188 |
|
189 while (hcanode != DI_NODE_NIL) { |
|
190 childnode = di_child_node(hcanode); |
|
191 while (childnode != DI_NODE_NIL) { |
|
192 if (di_prop_lookup_int64(DDI_DEV_T_ANY, |
|
193 childnode, "hca-guid", |
|
194 (int64_t **)&hca_guid) != 1) { |
|
195 childnode = di_sibling_node(childnode); |
|
196 continue; |
|
197 } else { |
|
198 break; |
|
199 } |
|
200 } |
|
201 if (childnode == DI_NODE_NIL) { |
|
202 hcanode = di_drv_next_node(hcanode); |
|
203 continue; |
|
204 } |
|
205 |
|
206 devpath = di_devfs_path(hcanode); |
|
207 devlength = strlen(devpath_prefix) + strlen(devpath) + |
|
208 strlen(devpath_suffix) + 2; |
|
209 access_devname = malloc(devlength); |
|
210 (void) snprintf(access_devname, devlength, "%s%s%s", |
|
211 devpath_prefix, devpath, devpath_suffix); |
|
212 if ((devfd = open(access_devname, O_RDONLY)) < 0) { |
|
213 IBERROR("open device file %s failed", access_devname); |
|
214 free(access_devname); |
|
215 hcanode = di_drv_next_node(hcanode); |
|
216 continue; |
|
217 } |
|
218 if (strcmp(drivername, "tavor") == 0) { |
|
219 tavor_nodedesc_ioctl_t nodedesc_ioctl; |
|
220 |
|
221 if ((rc = ioctl(devfd, TAVOR_IOCTL_GET_NODEDESC, |
|
222 (void *)&nodedesc_ioctl)) != 0) { |
|
223 IBERROR("tavor ioctl failure"); |
|
224 free(access_devname); |
|
225 close(devfd); |
|
226 hcanode = di_drv_next_node(hcanode); |
|
227 continue; |
|
228 } |
|
229 add_read_info_arr((char *)nodedesc_ioctl.node_desc_str, |
|
230 *hca_guid); |
|
231 } else if (strcmp(drivername, "hermon") == 0) { |
|
232 hermon_nodedesc_ioctl_t nodedesc_ioctl; |
|
233 |
|
234 if ((rc = ioctl(devfd, HERMON_IOCTL_GET_NODEDESC, |
|
235 (void *)&nodedesc_ioctl)) != 0) { |
|
236 IBERROR("hermon ioctl failure"); |
|
237 free(access_devname); |
|
238 close(devfd); |
|
239 hcanode = di_drv_next_node(hcanode); |
|
240 continue; |
|
241 } |
|
242 add_read_info_arr((char *)nodedesc_ioctl.node_desc_str, |
|
243 *hca_guid); |
|
244 } |
|
245 |
|
246 free(access_devname); |
|
247 close(devfd); |
|
248 hcanode = di_drv_next_node(hcanode); |
|
249 } |
|
250 |
|
251 } |
|
252 |
|
253 static int |
|
254 do_driver_update_ioctl(char *drivername, char *node_desc, char *hca_desc, |
|
255 uint64_t inp_hca_guid, uint32_t update_flag) |
|
256 { |
|
257 di_node_t hcanode, childnode; |
|
258 char *devpath; |
|
259 char *access_devname; |
|
260 int devlength, devfd, rc = -1; |
|
261 uint64_t *hca_guid; |
|
262 char *desc_str = (node_desc ? node_desc : hca_desc); |
|
263 |
|
264 if ((hcanode = di_drv_first_node(drivername, di_rootnode)) |
|
265 == DI_NODE_NIL) { |
|
266 return (-1); |
|
267 } |
|
268 |
|
269 while (hca_desc && hcanode != DI_NODE_NIL) { |
|
270 childnode = di_child_node(hcanode); |
|
271 while (childnode != DI_NODE_NIL) { |
|
272 if (di_prop_lookup_int64(DDI_DEV_T_ANY, |
|
273 childnode, "hca-guid", |
|
274 (int64_t **)&hca_guid) != 1) { |
|
275 childnode = di_sibling_node(childnode); |
|
276 continue; |
|
277 } else { |
|
278 break; |
|
279 } |
|
280 } |
|
281 if (*hca_guid == inp_hca_guid) |
|
282 break; |
|
283 hcanode = di_drv_next_node(hcanode); |
|
284 } |
|
285 |
|
286 if ((hca_desc && childnode == DI_NODE_NIL) || |
|
287 hcanode == DI_NODE_NIL) { |
|
288 IBERROR("matching GUID not found"); |
|
289 return (-1); |
|
290 } |
|
291 |
|
292 devpath = di_devfs_path(hcanode); |
|
293 devlength = strlen(devpath_prefix) + strlen(devpath) + |
|
294 strlen(devpath_suffix) + 2; |
|
295 access_devname = malloc(devlength); |
|
296 (void) snprintf(access_devname, devlength, "%s%s%s", |
|
297 devpath_prefix, devpath, devpath_suffix); |
|
298 if ((devfd = open(access_devname, O_RDONLY)) < 0) { |
|
299 IBERROR("open device file %s failed", access_devname); |
|
300 free(access_devname); |
|
301 return (rc); |
|
302 } |
|
303 if (strcmp(drivername, "tavor") == 0) { |
|
304 tavor_nodedesc_ioctl_t nodedesc_ioctl; |
|
305 |
|
306 strncpy(nodedesc_ioctl.node_desc_str, desc_str, 64); |
|
307 if (update_flag & NODEDESC_UPDATE_STRING) |
|
308 nodedesc_ioctl.node_desc_update_flag = |
|
309 TAVOR_NODEDESC_UPDATE_STRING; |
|
310 else if (update_flag & NODEDESC_UPDATE_HCA_STRING) |
|
311 nodedesc_ioctl.node_desc_update_flag = |
|
312 TAVOR_NODEDESC_UPDATE_HCA_STRING; |
|
313 else { |
|
314 IBERROR("Invalid option"); |
|
315 exit(-1); |
|
316 } |
|
317 if ((rc = ioctl(devfd, TAVOR_IOCTL_SET_NODEDESC, |
|
318 (void *)&nodedesc_ioctl)) != 0) { |
|
319 IBERROR("tavor ioctl failure"); |
|
320 } |
|
321 } else if (strcmp(drivername, "hermon") == 0) { |
|
322 hermon_nodedesc_ioctl_t nodedesc_ioctl; |
|
323 |
|
324 strncpy(nodedesc_ioctl.node_desc_str, desc_str, 64); |
|
325 if (update_flag & NODEDESC_UPDATE_STRING) |
|
326 nodedesc_ioctl.node_desc_update_flag = |
|
327 HERMON_NODEDESC_UPDATE_STRING; |
|
328 else if (update_flag & NODEDESC_UPDATE_HCA_STRING) |
|
329 nodedesc_ioctl.node_desc_update_flag = |
|
330 HERMON_NODEDESC_UPDATE_HCA_STRING; |
|
331 else { |
|
332 IBERROR("Invalid option"); |
|
333 exit(-1); |
|
334 } |
|
335 if ((rc = ioctl(devfd, HERMON_IOCTL_SET_NODEDESC, |
|
336 (void *)&nodedesc_ioctl)) != 0) { |
|
337 IBERROR("hermon ioctl failure"); |
|
338 } |
|
339 } |
|
340 |
|
341 free(access_devname); |
|
342 close(devfd); |
|
343 return (rc); |
|
344 } |
|
345 |
|
346 static void |
|
347 read_nodedesc() |
|
348 { |
|
349 int i; |
|
350 |
|
351 if ((di_rootnode = di_init("/", DINFOCPYALL | DINFOFORCE)) |
|
352 == DI_NODE_NIL) { |
|
353 IBERROR("read_nodedesc di_init failure"); |
|
354 return; |
|
355 } |
|
356 for (i = 0; ib_hca_driver_list[i]; i++) |
|
357 do_driver_read_ioctl(ib_hca_driver_list[i]); |
|
358 di_fini(di_rootnode); |
|
359 } |
|
360 |
|
361 static int |
|
362 update_nodedesc(char *cmn_nodedesc, char *hca_nodedesc, uint64_t guid, |
|
363 uint32_t update_flag) |
|
364 { |
|
365 int i, rc = 0; |
|
366 |
|
367 if ((di_rootnode = di_init("/", DINFOCPYALL | DINFOFORCE)) |
|
368 == DI_NODE_NIL) { |
|
369 IBERROR("di_init failure"); |
|
370 return (-1); |
|
371 } |
|
372 for (i = 0; ib_hca_driver_list[i]; i++) { |
|
373 rc = do_driver_update_ioctl(ib_hca_driver_list[i], |
|
374 cmn_nodedesc, hca_nodedesc, guid, |
|
375 update_flag); |
|
376 if (!rc) |
|
377 break; |
|
378 } |
|
379 if (rc) |
|
380 IBERROR("Updated failed for all HCA drivers"); |
|
381 |
|
382 di_fini(di_rootnode); |
|
383 return (rc); |
|
384 } |
|
385 |
|
386 static void |
|
387 usage(void) |
|
388 { |
|
389 char *basename; |
|
390 |
|
391 if (!(basename = strrchr(argv0, '/'))) |
|
392 basename = argv0; |
|
393 else |
|
394 basename++; |
|
395 |
|
396 fprintf(stderr, "Usage: %s \n", basename); |
|
397 fprintf(stderr, "\t\t %s [-N(ode_Descriptor) CmnString]\n", |
|
398 basename); |
|
399 fprintf(stderr, "\t\t %s [-H(CA_Description) HCAString " |
|
400 "-G(UID) HCA_GUID]\n", basename); |
|
401 fprintf(stderr, "\t\t %s [-H(CA_Description) HCAString " |
|
402 "-G(UID) HCA_GUID -N(ode_Descriptor) CmnString]\n", |
|
403 basename); |
|
404 fprintf(stderr, "\t\t %s [-v]\n", basename); |
|
405 } |
|
406 |
|
407 /* |
|
408 * Return the Node descriptor string by concatinating |
|
409 * many substrings. The first substring is "optarg" and |
|
410 * the index of the last sub-string is "optind". |
|
411 * |
|
412 * For common nodedescription, add a space at the end, |
|
413 * if there is none. |
|
414 */ |
|
415 static char * |
|
416 nodedesc_substr_cat(char **argv, int argc, boolean_t space_at_end) |
|
417 { |
|
418 int i, start_opt, end_opt; |
|
419 char *nodedesc_str; |
|
420 |
|
421 /* Get the index for first sub-string. */ |
|
422 for (start_opt = 0, i = optind; i; i--) { |
|
423 if (argv[i] == NULL) |
|
424 continue; |
|
425 |
|
426 if (strcmp(argv[i], optarg) == 0) { |
|
427 start_opt = i; |
|
428 break; |
|
429 } |
|
430 } |
|
431 if (start_opt == 0) |
|
432 return (NULL); |
|
433 |
|
434 /* Get the index for last sub-string */ |
|
435 for (end_opt = 0, i = optind; i <= argc; i++) { |
|
436 if (i == argc || argv[i][0] == '-') { |
|
437 end_opt = i - 1; |
|
438 break; |
|
439 } |
|
440 } |
|
441 if (end_opt == 0) |
|
442 return (NULL); |
|
443 |
|
444 nodedesc_str = malloc(64); |
|
445 strncpy(nodedesc_str, optarg, 64); |
|
446 start_opt++; |
|
447 |
|
448 /* |
|
449 * strcat a space string and then strcat the |
|
450 * next sub-string. |
|
451 */ |
|
452 for (i = start_opt; i <= end_opt; i++) { |
|
453 strncat(nodedesc_str, " ", 64); |
|
454 strncat(nodedesc_str, argv[i], 64); |
|
455 } |
|
456 |
|
457 /* |
|
458 * Add a space at the end, if the caller has set |
|
459 * space_at_end and the nodedesc string doesn't |
|
460 * contain a space at the end. |
|
461 */ |
|
462 if (space_at_end == B_TRUE && |
|
463 nodedesc_str[strlen(nodedesc_str)] != ' ') |
|
464 strncat(nodedesc_str, " ", 64); |
|
465 return (nodedesc_str); |
|
466 } |
|
467 |
|
468 int |
|
469 main(int argc, char **argv) |
|
470 { |
|
471 int rc; |
|
472 char *nodedesc = NULL, *hcadesc = NULL; |
|
473 uint32_t update_flag = 0; |
|
474 struct utsname uts_name; |
|
475 uint64_t hca_guid; |
|
476 boolean_t guid_inited = B_FALSE; |
|
477 extern int ibdebug; |
|
478 |
|
479 static char const str_opts[] = "N:H:G:vd"; |
|
480 static const struct option long_opts[] = { |
|
481 { "Node_Descriptor", 1, 0, 'N'}, |
|
482 { "HCA_Description", 1, 0, 'H'}, |
|
483 { "GUID", 1, 0, 'G'}, |
|
484 { "verbose", 0, 0, 'v'}, |
|
485 { "debug", 0, 0, 'd'}, |
|
486 { } |
|
487 }; |
|
488 |
|
489 argv0 = argv[0]; |
|
490 while (1) { |
|
491 int ch = getopt_long(argc, argv, str_opts, |
|
492 long_opts, NULL); |
|
493 if (ch == -1) |
|
494 break; |
|
495 switch (ch) { |
|
496 case 'N': |
|
497 nodedesc = nodedesc_substr_cat(argv, argc, B_TRUE); |
|
498 if (!nodedesc) { |
|
499 usage(); |
|
500 rc = -1; |
|
501 goto free_and_ret; |
|
502 } |
|
503 update_flag |= NODEDESC_UPDATE_STRING; |
|
504 break; |
|
505 case 'H': |
|
506 hcadesc = nodedesc_substr_cat(argv, argc, B_FALSE); |
|
507 if (!hcadesc) { |
|
508 usage(); |
|
509 rc = -1; |
|
510 goto free_and_ret; |
|
511 } |
|
512 update_flag |= NODEDESC_UPDATE_HCA_STRING; |
|
513 break; |
|
514 case 'G': |
|
515 guid_inited = B_TRUE; |
|
516 hca_guid = (uint64_t)strtoull(optarg, 0, 0); |
|
517 break; |
|
518 case 'v' : |
|
519 update_flag |= NODEDESC_READ; |
|
520 break; |
|
521 case 'd': |
|
522 ibdebug++; |
|
523 break; |
|
524 default: |
|
525 usage(); |
|
526 rc = -1; |
|
527 goto free_and_ret; |
|
528 } |
|
529 } |
|
530 |
|
531 if (update_flag & NODEDESC_READ) { |
|
532 if (nodedesc || hcadesc || guid_inited == B_TRUE) { |
|
533 usage(); |
|
534 rc = -1; |
|
535 goto free_and_ret; |
|
536 } |
|
537 |
|
538 read_nodedesc(); |
|
539 update_read_info_hwnames(); |
|
540 print_read_info(); |
|
541 return (0); |
|
542 } |
|
543 |
|
544 if (hcadesc && guid_inited == B_FALSE) { |
|
545 IBERROR("No GUID specified for HCA Node descriptor"); |
|
546 usage(); |
|
547 rc = -1; |
|
548 goto free_and_ret; |
|
549 } |
|
550 |
|
551 if (nodedesc) { |
|
552 rc = update_nodedesc(nodedesc, NULL, 0, |
|
553 NODEDESC_UPDATE_STRING); |
|
554 if (rc) { |
|
555 IBERROR("write common node descriptor " |
|
556 "failed"); |
|
557 rc = -1; |
|
558 goto free_and_ret; |
|
559 } |
|
560 } |
|
561 |
|
562 if (hcadesc) { |
|
563 rc = update_nodedesc(NULL, hcadesc, hca_guid, |
|
564 NODEDESC_UPDATE_HCA_STRING); |
|
565 if (rc) { |
|
566 IBERROR("update_hca_noddesc failed"); |
|
567 rc = -1; |
|
568 goto free_and_ret; |
|
569 } |
|
570 return (0); |
|
571 } |
|
572 |
|
573 |
|
574 if (nodedesc == NULL) { |
|
575 if (uname(&uts_name) < 0) { |
|
576 IBERROR("Node descriptor unspecified" |
|
577 "& uts_name failed"); |
|
578 rc = -1; |
|
579 goto free_and_ret; |
|
580 } |
|
581 } |
|
582 |
|
583 rc = update_nodedesc((char *)uts_name.nodename, NULL, |
|
584 0, NODEDESC_UPDATE_STRING); |
|
585 |
|
586 free_and_ret: |
|
587 if (nodedesc) |
|
588 free(nodedesc); |
|
589 if (hcadesc) |
|
590 free(hcadesc); |
|
591 |
|
592 return (rc); |
|
593 } |
|
594 |
|
595 #endif |