xref: /freebsd/contrib/ofed/infiniband-diags/src/rdma-ndd.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2014 Intel Corporation. All Rights Reserved
3*d6b92ffaSHans Petter Selasky  *
4*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
5*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
6*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
7*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
8*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
9*d6b92ffaSHans Petter Selasky  *
10*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
11*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
12*d6b92ffaSHans Petter Selasky  *     conditions are met:
13*d6b92ffaSHans Petter Selasky  *
14*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
15*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
16*d6b92ffaSHans Petter Selasky  *        disclaimer.
17*d6b92ffaSHans Petter Selasky  *
18*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
19*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
21*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
22*d6b92ffaSHans Petter Selasky  *
23*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*d6b92ffaSHans Petter Selasky  * SOFTWARE.
31*d6b92ffaSHans Petter Selasky  *
32*d6b92ffaSHans Petter Selasky  */
33*d6b92ffaSHans Petter Selasky 
34*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
35*d6b92ffaSHans Petter Selasky #  include <config.h>
36*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
37*d6b92ffaSHans Petter Selasky 
38*d6b92ffaSHans Petter Selasky #include <poll.h>
39*d6b92ffaSHans Petter Selasky #include <sys/types.h>
40*d6b92ffaSHans Petter Selasky #include <sys/stat.h>
41*d6b92ffaSHans Petter Selasky #include <fcntl.h>
42*d6b92ffaSHans Petter Selasky #include <assert.h>
43*d6b92ffaSHans Petter Selasky #include <string.h>
44*d6b92ffaSHans Petter Selasky #include <limits.h>
45*d6b92ffaSHans Petter Selasky #include <stdio.h>
46*d6b92ffaSHans Petter Selasky #include <syslog.h>
47*d6b92ffaSHans Petter Selasky #include <dirent.h>
48*d6b92ffaSHans Petter Selasky #include <errno.h>
49*d6b92ffaSHans Petter Selasky #include <unistd.h>
50*d6b92ffaSHans Petter Selasky #include <getopt.h>
51*d6b92ffaSHans Petter Selasky #include <stdlib.h>
52*d6b92ffaSHans Petter Selasky 
53*d6b92ffaSHans Petter Selasky #include <libudev.h>
54*d6b92ffaSHans Petter Selasky 
55*d6b92ffaSHans Petter Selasky struct udev *udev;
56*d6b92ffaSHans Petter Selasky struct udev_monitor *mon;
57*d6b92ffaSHans Petter Selasky 
58*d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
59*d6b92ffaSHans Petter Selasky 
60*d6b92ffaSHans Petter Selasky #define SYS_HOSTNAME "/proc/sys/kernel/hostname"
61*d6b92ffaSHans Petter Selasky #define DEF_SYS_DIR "/sys"
62*d6b92ffaSHans Petter Selasky char *sys_dir = DEF_SYS_DIR;
63*d6b92ffaSHans Petter Selasky #define SYS_INFINIBAND "class/infiniband"
64*d6b92ffaSHans Petter Selasky #define DEFAULT_RETRY_RATE 60
65*d6b92ffaSHans Petter Selasky #define DEFAULT_RETRY_COUNT 0
66*d6b92ffaSHans Petter Selasky #define DEFAULT_ND_FORMAT "%h %d"
67*d6b92ffaSHans Petter Selasky 
68*d6b92ffaSHans Petter Selasky int failure_retry_rate = DEFAULT_RETRY_RATE;
69*d6b92ffaSHans Petter Selasky int set_retry_cnt = DEFAULT_RETRY_COUNT;
70*d6b92ffaSHans Petter Selasky int foreground = 0;
71*d6b92ffaSHans Petter Selasky char *pidfile = NULL;
72*d6b92ffaSHans Petter Selasky 
newline_to_null(char * str)73*d6b92ffaSHans Petter Selasky static void newline_to_null(char *str)
74*d6b92ffaSHans Petter Selasky {
75*d6b92ffaSHans Petter Selasky 	char *term = index(str, '\n');
76*d6b92ffaSHans Petter Selasky 	if (term)
77*d6b92ffaSHans Petter Selasky 		*term = '\0';
78*d6b92ffaSHans Petter Selasky }
79*d6b92ffaSHans Petter Selasky 
strip_domain(char * str)80*d6b92ffaSHans Petter Selasky static void strip_domain(char *str)
81*d6b92ffaSHans Petter Selasky {
82*d6b92ffaSHans Petter Selasky 	char *term = index(str, '.');
83*d6b92ffaSHans Petter Selasky 	if (term)
84*d6b92ffaSHans Petter Selasky 		*term = '\0';
85*d6b92ffaSHans Petter Selasky }
86*d6b92ffaSHans Petter Selasky 
build_node_desc(char * dest,size_t len,const char * device,const char * hostname)87*d6b92ffaSHans Petter Selasky static void build_node_desc(char *dest, size_t len,
88*d6b92ffaSHans Petter Selasky 		     const char *device, const char *hostname)
89*d6b92ffaSHans Petter Selasky {
90*d6b92ffaSHans Petter Selasky 	char *end = dest + len-1;
91*d6b92ffaSHans Petter Selasky 	const char *field;
92*d6b92ffaSHans Petter Selasky 	char *src = ibd_nd_format;
93*d6b92ffaSHans Petter Selasky 
94*d6b92ffaSHans Petter Selasky 	while (*src && (dest < end)) {
95*d6b92ffaSHans Petter Selasky 		if (*src != '%') {
96*d6b92ffaSHans Petter Selasky 			*dest++ = *src++;
97*d6b92ffaSHans Petter Selasky 		} else {
98*d6b92ffaSHans Petter Selasky 			src++;
99*d6b92ffaSHans Petter Selasky 			switch (*src) {
100*d6b92ffaSHans Petter Selasky 			case 'h':
101*d6b92ffaSHans Petter Selasky 				field = hostname;
102*d6b92ffaSHans Petter Selasky 				while (*field && (*field != '.') && (dest < end))
103*d6b92ffaSHans Petter Selasky 					*dest++ = *field++;
104*d6b92ffaSHans Petter Selasky 				break;
105*d6b92ffaSHans Petter Selasky 			case 'd':
106*d6b92ffaSHans Petter Selasky 				field = device;
107*d6b92ffaSHans Petter Selasky 				while (*field && (dest < end))
108*d6b92ffaSHans Petter Selasky 					*dest++ = *field++;
109*d6b92ffaSHans Petter Selasky 				break;
110*d6b92ffaSHans Petter Selasky 			}
111*d6b92ffaSHans Petter Selasky 			src++;
112*d6b92ffaSHans Petter Selasky 		}
113*d6b92ffaSHans Petter Selasky 	}
114*d6b92ffaSHans Petter Selasky 	*dest = 0;
115*d6b92ffaSHans Petter Selasky }
116*d6b92ffaSHans Petter Selasky 
update_node_desc(const char * device,const char * hostname,int force)117*d6b92ffaSHans Petter Selasky static int update_node_desc(const char *device, const char *hostname, int force)
118*d6b92ffaSHans Petter Selasky {
119*d6b92ffaSHans Petter Selasky 	int rc;
120*d6b92ffaSHans Petter Selasky 	char nd[128];
121*d6b92ffaSHans Petter Selasky 	char new_nd[64];
122*d6b92ffaSHans Petter Selasky 	char nd_file[PATH_MAX];
123*d6b92ffaSHans Petter Selasky 	FILE *f;
124*d6b92ffaSHans Petter Selasky 
125*d6b92ffaSHans Petter Selasky 	snprintf(nd_file, sizeof(nd_file), "%s/%s/%s/node_desc",
126*d6b92ffaSHans Petter Selasky 			sys_dir, SYS_INFINIBAND, device);
127*d6b92ffaSHans Petter Selasky 	nd_file[sizeof(nd_file)-1] = '\0';
128*d6b92ffaSHans Petter Selasky 
129*d6b92ffaSHans Petter Selasky 	f = fopen(nd_file, "r+");
130*d6b92ffaSHans Petter Selasky 	if (!f) {
131*d6b92ffaSHans Petter Selasky 		syslog(LOG_ERR, "Failed to open %s\n", nd_file);
132*d6b92ffaSHans Petter Selasky 		return -EIO;
133*d6b92ffaSHans Petter Selasky 	}
134*d6b92ffaSHans Petter Selasky 
135*d6b92ffaSHans Petter Selasky 	if (!fgets(nd, sizeof(nd), f)) {
136*d6b92ffaSHans Petter Selasky 		syslog(LOG_ERR, "Failed to read %s\n", nd_file);
137*d6b92ffaSHans Petter Selasky 		rc = -EIO;
138*d6b92ffaSHans Petter Selasky 		goto error;
139*d6b92ffaSHans Petter Selasky 	}
140*d6b92ffaSHans Petter Selasky 	newline_to_null(nd);
141*d6b92ffaSHans Petter Selasky 
142*d6b92ffaSHans Petter Selasky 	build_node_desc(new_nd, sizeof(new_nd), device, hostname);
143*d6b92ffaSHans Petter Selasky 
144*d6b92ffaSHans Petter Selasky 	if (!force && strncmp(new_nd, nd, sizeof(new_nd)) == 0) {
145*d6b92ffaSHans Petter Selasky 		syslog(LOG_INFO, "%s: no change (%s)\n", device, new_nd);
146*d6b92ffaSHans Petter Selasky 	} else {
147*d6b92ffaSHans Petter Selasky 		syslog(LOG_INFO, "%s: change (%s) -> (%s)\n",
148*d6b92ffaSHans Petter Selasky 			device, nd, new_nd);
149*d6b92ffaSHans Petter Selasky 		rewind(f);
150*d6b92ffaSHans Petter Selasky 		fprintf(f, new_nd);
151*d6b92ffaSHans Petter Selasky 	}
152*d6b92ffaSHans Petter Selasky 
153*d6b92ffaSHans Petter Selasky 	rc = 0;
154*d6b92ffaSHans Petter Selasky error:
155*d6b92ffaSHans Petter Selasky 	fclose(f);
156*d6b92ffaSHans Petter Selasky 	return rc;
157*d6b92ffaSHans Petter Selasky }
158*d6b92ffaSHans Petter Selasky 
set_rdma_node_desc(const char * hostname,int force)159*d6b92ffaSHans Petter Selasky static int set_rdma_node_desc(const char *hostname, int force)
160*d6b92ffaSHans Petter Selasky {
161*d6b92ffaSHans Petter Selasky 	DIR *class_dir;
162*d6b92ffaSHans Petter Selasky 	struct dirent *dent;
163*d6b92ffaSHans Petter Selasky 	char dev_dir[PATH_MAX];
164*d6b92ffaSHans Petter Selasky 
165*d6b92ffaSHans Petter Selasky 	snprintf(dev_dir, sizeof(dev_dir), "%s/%s", sys_dir, SYS_INFINIBAND);
166*d6b92ffaSHans Petter Selasky 	dev_dir[sizeof(dev_dir)-1] = '\0';
167*d6b92ffaSHans Petter Selasky 
168*d6b92ffaSHans Petter Selasky 	class_dir = opendir(dev_dir);
169*d6b92ffaSHans Petter Selasky 	if (!class_dir) {
170*d6b92ffaSHans Petter Selasky 		syslog(LOG_INFO, "Failed to open %s", dev_dir);
171*d6b92ffaSHans Petter Selasky 		return -ENOSYS;
172*d6b92ffaSHans Petter Selasky 	}
173*d6b92ffaSHans Petter Selasky 
174*d6b92ffaSHans Petter Selasky 	while ((dent = readdir(class_dir))) {
175*d6b92ffaSHans Petter Selasky 		int retry = set_retry_cnt;
176*d6b92ffaSHans Petter Selasky 		if (dent->d_name[0] == '.')
177*d6b92ffaSHans Petter Selasky 			continue;
178*d6b92ffaSHans Petter Selasky 
179*d6b92ffaSHans Petter Selasky 		while (update_node_desc(dent->d_name, hostname, force) && retry > 0) {
180*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR, "retrying set Node Description on %s\n",
181*d6b92ffaSHans Petter Selasky 				dent->d_name);
182*d6b92ffaSHans Petter Selasky 			retry--;
183*d6b92ffaSHans Petter Selasky 		}
184*d6b92ffaSHans Petter Selasky 	}
185*d6b92ffaSHans Petter Selasky 
186*d6b92ffaSHans Petter Selasky 	closedir(class_dir);
187*d6b92ffaSHans Petter Selasky 	return 0;
188*d6b92ffaSHans Petter Selasky }
189*d6b92ffaSHans Petter Selasky 
read_hostname(int fd,char * name,size_t len)190*d6b92ffaSHans Petter Selasky static int read_hostname(int fd, char *name, size_t len)
191*d6b92ffaSHans Petter Selasky {
192*d6b92ffaSHans Petter Selasky 	int rc;
193*d6b92ffaSHans Petter Selasky 	memset(name, 0, len);
194*d6b92ffaSHans Petter Selasky 	if (read(fd, name, len-1) >= 0) {
195*d6b92ffaSHans Petter Selasky 		newline_to_null(name);
196*d6b92ffaSHans Petter Selasky 		strip_domain(name);
197*d6b92ffaSHans Petter Selasky 		rc = 0;
198*d6b92ffaSHans Petter Selasky 	} else {
199*d6b92ffaSHans Petter Selasky 		syslog(LOG_ERR, "Read %s Failed\n", SYS_HOSTNAME);
200*d6b92ffaSHans Petter Selasky 		rc = -EIO;
201*d6b92ffaSHans Petter Selasky 	}
202*d6b92ffaSHans Petter Selasky 	return rc;
203*d6b92ffaSHans Petter Selasky }
204*d6b92ffaSHans Petter Selasky 
process_opts(void * context,int ch,char * optarg)205*d6b92ffaSHans Petter Selasky static int process_opts(void *context, int ch, char *optarg)
206*d6b92ffaSHans Petter Selasky {
207*d6b92ffaSHans Petter Selasky 	unsigned long tmp;
208*d6b92ffaSHans Petter Selasky 	switch (ch) {
209*d6b92ffaSHans Petter Selasky 	case 0:
210*d6b92ffaSHans Petter Selasky 		pidfile = optarg;
211*d6b92ffaSHans Petter Selasky 		break;
212*d6b92ffaSHans Petter Selasky 	case 'f':
213*d6b92ffaSHans Petter Selasky 		foreground = 1;
214*d6b92ffaSHans Petter Selasky 		break;
215*d6b92ffaSHans Petter Selasky 	case 't':
216*d6b92ffaSHans Petter Selasky 		tmp = strtoul(optarg, NULL, 0);
217*d6b92ffaSHans Petter Selasky 		if (tmp >= INT_MAX) {
218*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR,
219*d6b92ffaSHans Petter Selasky 				"Invalid retry rate specified: %lu s\n",
220*d6b92ffaSHans Petter Selasky 				tmp);
221*d6b92ffaSHans Petter Selasky 		} else {
222*d6b92ffaSHans Petter Selasky 			failure_retry_rate = (int)tmp;
223*d6b92ffaSHans Petter Selasky 		}
224*d6b92ffaSHans Petter Selasky 		break;
225*d6b92ffaSHans Petter Selasky 	case 'r':
226*d6b92ffaSHans Petter Selasky 		tmp = strtoul(optarg, NULL, 0);
227*d6b92ffaSHans Petter Selasky 		if (tmp >= INT_MAX) {
228*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR,
229*d6b92ffaSHans Petter Selasky 				"Invalid retry count specified: %lu\n",
230*d6b92ffaSHans Petter Selasky 				tmp);
231*d6b92ffaSHans Petter Selasky 		} else {
232*d6b92ffaSHans Petter Selasky 			set_retry_cnt = (int)tmp;
233*d6b92ffaSHans Petter Selasky 		}
234*d6b92ffaSHans Petter Selasky 		break;
235*d6b92ffaSHans Petter Selasky 	default:
236*d6b92ffaSHans Petter Selasky 		return -1;
237*d6b92ffaSHans Petter Selasky 	}
238*d6b92ffaSHans Petter Selasky 	return 0;
239*d6b92ffaSHans Petter Selasky }
240*d6b92ffaSHans Petter Selasky 
241*d6b92ffaSHans Petter Selasky #define MSG_MAX 2048
udev_log_fn(struct udev * ud,int priority,const char * file,int line,const char * fn,const char * format,va_list args)242*d6b92ffaSHans Petter Selasky static void udev_log_fn(struct udev *ud, int priority, const char *file, int line,
243*d6b92ffaSHans Petter Selasky 		const char *fn, const char *format, va_list args)
244*d6b92ffaSHans Petter Selasky {
245*d6b92ffaSHans Petter Selasky 	int off = 0;
246*d6b92ffaSHans Petter Selasky 	char msg[MSG_MAX];
247*d6b92ffaSHans Petter Selasky 	off = snprintf(msg, MSG_MAX, "libudev: %s:%d %s",
248*d6b92ffaSHans Petter Selasky 			file, line, fn);
249*d6b92ffaSHans Petter Selasky 	if (off < MSG_MAX-1)
250*d6b92ffaSHans Petter Selasky 		vsnprintf(msg+off, MSG_MAX-off, format, args);
251*d6b92ffaSHans Petter Selasky 	syslog(LOG_ERR, msg);
252*d6b92ffaSHans Petter Selasky }
253*d6b92ffaSHans Petter Selasky 
setup_udev(void)254*d6b92ffaSHans Petter Selasky static void setup_udev(void)
255*d6b92ffaSHans Petter Selasky {
256*d6b92ffaSHans Petter Selasky 	udev = udev_new();
257*d6b92ffaSHans Petter Selasky 	if (!udev) {
258*d6b92ffaSHans Petter Selasky 		syslog(LOG_ERR, "udev_new failed\n");
259*d6b92ffaSHans Petter Selasky 		return;
260*d6b92ffaSHans Petter Selasky 	}
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	udev_set_log_fn(udev, udev_log_fn);
263*d6b92ffaSHans Petter Selasky 	udev_set_log_priority(udev, LOG_INFO);
264*d6b92ffaSHans Petter Selasky #if HAVE_UDEV_GET_SYS_PATH
265*d6b92ffaSHans Petter Selasky 	sys_dir = (char *)udev_get_sys_path(udev);
266*d6b92ffaSHans Petter Selasky #endif
267*d6b92ffaSHans Petter Selasky }
268*d6b92ffaSHans Petter Selasky 
get_udev_fd(void)269*d6b92ffaSHans Petter Selasky static int get_udev_fd(void)
270*d6b92ffaSHans Petter Selasky {
271*d6b92ffaSHans Petter Selasky 	mon = udev_monitor_new_from_netlink(udev, "udev");
272*d6b92ffaSHans Petter Selasky 	if (!mon) {
273*d6b92ffaSHans Petter Selasky 		syslog(LOG_ERR, "udev monitoring failed\n");
274*d6b92ffaSHans Petter Selasky 		return -1;
275*d6b92ffaSHans Petter Selasky 	}
276*d6b92ffaSHans Petter Selasky 
277*d6b92ffaSHans Petter Selasky 	udev_monitor_filter_add_match_subsystem_devtype(mon, "infiniband", NULL);
278*d6b92ffaSHans Petter Selasky 	udev_monitor_enable_receiving(mon);
279*d6b92ffaSHans Petter Selasky 	return udev_monitor_get_fd(mon);
280*d6b92ffaSHans Petter Selasky }
281*d6b92ffaSHans Petter Selasky 
process_udev_event(int ud_fd,const char * hostname)282*d6b92ffaSHans Petter Selasky static void process_udev_event(int ud_fd, const char *hostname)
283*d6b92ffaSHans Petter Selasky {
284*d6b92ffaSHans Petter Selasky 	struct udev_device *dev;
285*d6b92ffaSHans Petter Selasky 
286*d6b92ffaSHans Petter Selasky 	dev = udev_monitor_receive_device(mon);
287*d6b92ffaSHans Petter Selasky 	if (dev) {
288*d6b92ffaSHans Petter Selasky 		const char *device = udev_device_get_sysname(dev);
289*d6b92ffaSHans Petter Selasky 		const char *action = udev_device_get_action(dev);
290*d6b92ffaSHans Petter Selasky 
291*d6b92ffaSHans Petter Selasky 		syslog(LOG_INFO, "Device event: %s, %s, %s\n",
292*d6b92ffaSHans Petter Selasky 			udev_device_get_subsystem(dev),
293*d6b92ffaSHans Petter Selasky 			device, action);
294*d6b92ffaSHans Petter Selasky 
295*d6b92ffaSHans Petter Selasky 		if (device && action
296*d6b92ffaSHans Petter Selasky 		    && strncmp(action, "add", sizeof("add")) == 0)
297*d6b92ffaSHans Petter Selasky 			update_node_desc(device, hostname, 1);
298*d6b92ffaSHans Petter Selasky 
299*d6b92ffaSHans Petter Selasky 		udev_device_unref(dev);
300*d6b92ffaSHans Petter Selasky 	}
301*d6b92ffaSHans Petter Selasky }
302*d6b92ffaSHans Petter Selasky 
monitor(void)303*d6b92ffaSHans Petter Selasky static void monitor(void)
304*d6b92ffaSHans Petter Selasky {
305*d6b92ffaSHans Petter Selasky 	char hostname[128];
306*d6b92ffaSHans Petter Selasky 	int hn_fd;
307*d6b92ffaSHans Petter Selasky 	int rc;
308*d6b92ffaSHans Petter Selasky 	struct pollfd fds[2];
309*d6b92ffaSHans Petter Selasky 	int numfds = 1;
310*d6b92ffaSHans Petter Selasky 	int ud_fd;
311*d6b92ffaSHans Petter Selasky 
312*d6b92ffaSHans Petter Selasky 	ud_fd = get_udev_fd();
313*d6b92ffaSHans Petter Selasky 	if (ud_fd >= 0)
314*d6b92ffaSHans Petter Selasky 		numfds = 2;
315*d6b92ffaSHans Petter Selasky 
316*d6b92ffaSHans Petter Selasky 	while (1) {
317*d6b92ffaSHans Petter Selasky 		hn_fd = open(SYS_HOSTNAME, O_RDONLY);
318*d6b92ffaSHans Petter Selasky 		if (hn_fd < 0) {
319*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR,
320*d6b92ffaSHans Petter Selasky 				"Open %s Failed: retry in %d seconds\n",
321*d6b92ffaSHans Petter Selasky 				SYS_HOSTNAME, failure_retry_rate);
322*d6b92ffaSHans Petter Selasky 			sleep(failure_retry_rate);
323*d6b92ffaSHans Petter Selasky 			continue;
324*d6b92ffaSHans Petter Selasky 		}
325*d6b92ffaSHans Petter Selasky 
326*d6b92ffaSHans Petter Selasky 		fds[0].fd = hn_fd;
327*d6b92ffaSHans Petter Selasky 		fds[0].events = 0;
328*d6b92ffaSHans Petter Selasky 		fds[0].revents = 0;
329*d6b92ffaSHans Petter Selasky 
330*d6b92ffaSHans Petter Selasky 		fds[1].fd = ud_fd;
331*d6b92ffaSHans Petter Selasky 		fds[1].events = POLLIN;
332*d6b92ffaSHans Petter Selasky 		fds[1].revents = 0;
333*d6b92ffaSHans Petter Selasky 
334*d6b92ffaSHans Petter Selasky 		rc = poll(fds, numfds, -1);
335*d6b92ffaSHans Petter Selasky 
336*d6b92ffaSHans Petter Selasky 		if (rc > 0) {
337*d6b92ffaSHans Petter Selasky 			if (read_hostname(hn_fd, hostname, sizeof(hostname)) != 0)
338*d6b92ffaSHans Petter Selasky 				hostname[0] = '\0';
339*d6b92ffaSHans Petter Selasky 
340*d6b92ffaSHans Petter Selasky 			if (fds[0].revents != 0)
341*d6b92ffaSHans Petter Selasky 				syslog(LOG_ERR, "Hostname change: %s\n", hostname);
342*d6b92ffaSHans Petter Selasky 
343*d6b92ffaSHans Petter Selasky 			if (fds[1].revents != 0)
344*d6b92ffaSHans Petter Selasky 				process_udev_event(ud_fd, hostname);
345*d6b92ffaSHans Petter Selasky 
346*d6b92ffaSHans Petter Selasky 			rc = set_rdma_node_desc((const char *)hostname, 0);
347*d6b92ffaSHans Petter Selasky 		} else {
348*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR, "Poll %s Failed\n", SYS_HOSTNAME);
349*d6b92ffaSHans Petter Selasky 			rc = -EIO;
350*d6b92ffaSHans Petter Selasky 		}
351*d6b92ffaSHans Petter Selasky 
352*d6b92ffaSHans Petter Selasky 		close(hn_fd);
353*d6b92ffaSHans Petter Selasky 
354*d6b92ffaSHans Petter Selasky 		if (rc)
355*d6b92ffaSHans Petter Selasky 			sleep(failure_retry_rate);
356*d6b92ffaSHans Petter Selasky 	}
357*d6b92ffaSHans Petter Selasky }
358*d6b92ffaSHans Petter Selasky 
remove_pidfile(void)359*d6b92ffaSHans Petter Selasky static void remove_pidfile(void)
360*d6b92ffaSHans Petter Selasky {
361*d6b92ffaSHans Petter Selasky         if (pidfile)
362*d6b92ffaSHans Petter Selasky 		unlink(pidfile);
363*d6b92ffaSHans Petter Selasky }
364*d6b92ffaSHans Petter Selasky 
write_pidfile(void)365*d6b92ffaSHans Petter Selasky static void write_pidfile(void)
366*d6b92ffaSHans Petter Selasky {
367*d6b92ffaSHans Petter Selasky 	FILE *f;
368*d6b92ffaSHans Petter Selasky 	if (pidfile) {
369*d6b92ffaSHans Petter Selasky 		remove_pidfile();
370*d6b92ffaSHans Petter Selasky 		f = fopen(pidfile, "w");
371*d6b92ffaSHans Petter Selasky 		if (f) {
372*d6b92ffaSHans Petter Selasky 			fprintf(f, "%d\n", getpid());
373*d6b92ffaSHans Petter Selasky 			fclose(f);
374*d6b92ffaSHans Petter Selasky 		} else {
375*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR, "Failed to write pidfile : %s\n",
376*d6b92ffaSHans Petter Selasky 				pidfile);
377*d6b92ffaSHans Petter Selasky 			exit(errno);
378*d6b92ffaSHans Petter Selasky 		}
379*d6b92ffaSHans Petter Selasky 	}
380*d6b92ffaSHans Petter Selasky }
381*d6b92ffaSHans Petter Selasky 
main(int argc,char * argv[])382*d6b92ffaSHans Petter Selasky int main(int argc, char *argv[])
383*d6b92ffaSHans Petter Selasky {
384*d6b92ffaSHans Petter Selasky 	int fd;
385*d6b92ffaSHans Petter Selasky 	char hostname[128];
386*d6b92ffaSHans Petter Selasky 
387*d6b92ffaSHans Petter Selasky 	openlog("rdma-ndd", LOG_PID | LOG_PERROR, LOG_DAEMON);
388*d6b92ffaSHans Petter Selasky 
389*d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
390*d6b92ffaSHans Petter Selasky 		{"retry_timer", 't', 1, "<retry_timer>",
391*d6b92ffaSHans Petter Selasky 			"Length of time to sleep when system errors occur "
392*d6b92ffaSHans Petter Selasky 			"when attempting to poll and or read the hostname "
393*d6b92ffaSHans Petter Selasky 			"from the system.\n"},
394*d6b92ffaSHans Petter Selasky 		{"retry_count", 'r', 1, "<retry_count>",
395*d6b92ffaSHans Petter Selasky 			"Number of times to attempt to retry setting "
396*d6b92ffaSHans Petter Selasky 			"of the node description on failure\n"},
397*d6b92ffaSHans Petter Selasky 		{"foreground", 'f', 0, NULL, "run in the foreground instead of as a daemon\n"},
398*d6b92ffaSHans Petter Selasky 		{"pidfile", 0, 1, "<pidfile>", "specify a pid file (daemon mode only)\n"},
399*d6b92ffaSHans Petter Selasky 		{0}
400*d6b92ffaSHans Petter Selasky 	};
401*d6b92ffaSHans Petter Selasky 
402*d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, NULL, "CPDLGtsKyevd", opts,
403*d6b92ffaSHans Petter Selasky 			    process_opts, "", NULL);
404*d6b92ffaSHans Petter Selasky 
405*d6b92ffaSHans Petter Selasky 	if (!ibd_nd_format)
406*d6b92ffaSHans Petter Selasky 		ibd_nd_format = DEFAULT_ND_FORMAT;
407*d6b92ffaSHans Petter Selasky 
408*d6b92ffaSHans Petter Selasky 	if (!foreground) {
409*d6b92ffaSHans Petter Selasky 		closelog();
410*d6b92ffaSHans Petter Selasky 		openlog("rdma-ndd", LOG_PID, LOG_DAEMON);
411*d6b92ffaSHans Petter Selasky 		if (daemon(0, 0) != 0) {
412*d6b92ffaSHans Petter Selasky 			syslog(LOG_ERR, "Failed to daemonize\n");
413*d6b92ffaSHans Petter Selasky 			exit(errno);
414*d6b92ffaSHans Petter Selasky 		}
415*d6b92ffaSHans Petter Selasky 		write_pidfile();
416*d6b92ffaSHans Petter Selasky 	}
417*d6b92ffaSHans Petter Selasky 
418*d6b92ffaSHans Petter Selasky 	setup_udev();
419*d6b92ffaSHans Petter Selasky 
420*d6b92ffaSHans Petter Selasky 	syslog(LOG_INFO, "Node Descriptor format (%s)\n", ibd_nd_format);
421*d6b92ffaSHans Petter Selasky 
422*d6b92ffaSHans Petter Selasky 	fd = open(SYS_HOSTNAME, O_RDONLY);
423*d6b92ffaSHans Petter Selasky 	if (read_hostname(fd, hostname, sizeof(hostname)) != 0)
424*d6b92ffaSHans Petter Selasky 		hostname[0] = '\0';
425*d6b92ffaSHans Petter Selasky 	set_rdma_node_desc((const char *)hostname, 1);
426*d6b92ffaSHans Petter Selasky 	close(fd);
427*d6b92ffaSHans Petter Selasky 
428*d6b92ffaSHans Petter Selasky 	monitor();
429*d6b92ffaSHans Petter Selasky 
430*d6b92ffaSHans Petter Selasky 	remove_pidfile();
431*d6b92ffaSHans Petter Selasky 
432*d6b92ffaSHans Petter Selasky 	return 0;
433*d6b92ffaSHans Petter Selasky }
434