debuggers.hg

view tools/xenbackendd/xenbackendd.c @ 21067:b4a1832a916f

Update Xen version to 4.0.0-rc6
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 09 18:18:05 2010 +0000 (2010-03-09)
parents 9ced12c28e05
children
line source
1 /* $NetBSD: xenbackendd.c,v 1.1.1.1 2008/08/07 20:26:57 cegger Exp $ */
2 /*
3 * Copyright (C) 2006 Manuel Bouyer <bouyer@netbsd.org>
4 * Copyright (C) 2009 Christoph Egger <Christoph.Egger@amd.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; under version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <syslog.h>
31 #include <xs.h>
33 #define DEVTYPE_UNKNOWN 0
34 #define DEVTYPE_VIF 1
35 #define DEVTYPE_VBD 2
37 #define DOMAIN_PATH "/local/domain/0"
39 #ifndef XEN_SCRIPT_DIR
40 #error XEN_SCRIPT_DIR not defined
41 #endif
43 #ifndef VBD_SCRIPT
44 #define VBD_SCRIPT XEN_SCRIPT_DIR"/block"
45 #endif
46 #ifndef LOG_FILE
47 #define LOG_FILE "/var/log/xen/xenbackendd.log"
48 #endif
49 #ifndef PID_FILE
50 #define PID_FILE "/var/run/xenbackendd.pid"
51 #endif
54 struct xs_handle *xs;
56 int fflag = 0;
57 int dflag = 0;
59 const char *vbd_script = NULL;
60 const char *log_file = NULL;
61 const char *pidfile = NULL;
63 static void
64 dolog(int pri, const char *fmt, ...)
65 {
66 va_list ap;
67 va_start(ap, fmt);
68 vfprintf(stderr, fmt, ap);
69 va_end(ap);
70 fprintf(stderr, "\n");
71 fflush(stderr);
72 va_start(ap, fmt);
73 vsyslog(pri, fmt, ap);
74 va_end(ap);
75 }
77 static void
78 dodebug(const char *fmt, ...)
79 {
80 va_list ap;
82 if (dflag == 0)
83 return;
84 va_start(ap, fmt);
85 vfprintf(stdout, fmt, ap);
86 va_end(ap);
87 printf("\n");
88 fflush(stdout);
89 }
91 static void
92 doexec(const char *cmd, const char *arg1, const char *arg2)
93 {
94 dodebug("exec %s %s %s", cmd, arg1, arg2);
95 switch(vfork()) {
96 case -1:
97 dolog(LOG_ERR, "can't vfork: %s", strerror(errno));
98 break;
99 case 0:
100 execl(cmd, cmd, arg1, arg2, NULL);
101 dolog(LOG_ERR, "can't exec %s: %s", cmd, strerror(errno));
102 exit(EXIT_FAILURE);
103 /* NOTREACHED */
104 break;
105 default:
106 wait(NULL);
107 break;
108 }
109 }
111 static void
112 usage(void)
113 {
114 fprintf(stderr,
115 "usage: %s [-d] [-f] [-l log_file] [-p pif_file] [-s vbd_script]\n",
116 getprogname());
117 exit(EXIT_FAILURE);
118 }
120 static int
121 xen_setup(void)
122 {
123 xs = xs_daemon_open();
124 if (xs == NULL) {
125 dolog(LOG_ERR,
126 "Failed to contact xenstore (%s). Is it running?",
127 strerror(errno));
128 goto out;
129 }
131 if (!xs_watch(xs, DOMAIN_PATH, "backend")) {
132 dolog(LOG_ERR, "xenstore watch on backend fails.");
133 goto out;
134 }
135 return 0;
137 out:
138 if (xs) {
139 xs_daemon_close(xs);
140 xs = NULL;
141 }
142 return -1;
143 }
145 int
146 main(int argc, char * const argv[])
147 {
148 char **vec;
149 unsigned int num;
150 char *s;
151 int state;
152 char *sstate;
153 char *p;
154 char buf[80];
155 int type = DEVTYPE_UNKNOWN;
156 int ch;
157 int debug_fd;
158 FILE *pidfile_f;
160 while ((ch = getopt(argc, argv, "dfl:p:s:")) != -1) {
161 switch (ch) {
162 case 'd':
163 dflag = 1;
164 break;
165 case 'f':
166 fflag = 1;
167 break;
168 case 'l':
169 log_file = optarg;
170 break;
171 case 'p':
172 pidfile = pidfile;
173 case 's':
174 vbd_script = optarg;
175 break;
176 default:
177 usage();
178 }
179 }
181 if (vbd_script == NULL)
182 vbd_script = VBD_SCRIPT;
183 if (pidfile == NULL)
184 pidfile = PID_FILE;
185 if (log_file == NULL)
186 log_file = LOG_FILE;
188 openlog("xenbackendd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
190 if (fflag == 0) {
191 /* open log file */
192 debug_fd = open(log_file, O_RDWR | O_CREAT | O_TRUNC, 0644);
193 if (debug_fd == -1) {
194 dolog(LOG_ERR, "can't open %s: %s",
195 log_file, strerror(errno));
196 exit(EXIT_FAILURE);
197 }
198 }
200 if (fflag == 0) {
201 /* daemonize */
202 pidfile_f = fopen(pidfile, "w");
203 if (pidfile_f == NULL) {
204 dolog(LOG_ERR, "can't open %s: %s",
205 pidfile, strerror(errno));
206 exit(EXIT_FAILURE);
207 }
208 if (daemon(0, 0) < 0) {
209 dolog(LOG_ERR, "can't daemonize: %s",
210 strerror(errno));
211 exit(EXIT_FAILURE);
212 }
213 fprintf(pidfile_f, "%d\n", (int)getpid());
214 fclose(pidfile_f);
216 /* redirect stderr to log file */
217 if (dup2(debug_fd, STDERR_FILENO) < 0) {
218 dolog(LOG_ERR, "can't redirect stderr to %s: %s\n",
219 log_file, strerror(errno));
220 exit(EXIT_FAILURE);
221 }
223 /* also redirect stdout if we're in debug mode */
224 if (dflag) {
225 if (dup2(debug_fd, STDOUT_FILENO) < 0) {
226 dolog(LOG_ERR,
227 "can't redirect stdout to %s: %s\n",
228 log_file, strerror(errno));
229 exit(EXIT_FAILURE);
230 }
231 }
233 close(debug_fd);
234 debug_fd = -1;
235 }
237 if (xen_setup() < 0)
238 exit(EXIT_FAILURE);
240 for (;;) {
241 vec = xs_read_watch(xs, &num);
242 if (!vec) {
243 dolog(LOG_ERR, "xs_read_watch: NULL\n");
244 continue;
245 }
247 if (strlen(vec[XS_WATCH_PATH]) < sizeof("state"))
248 goto next1;
250 /* find last component of path, check if it's "state" */
251 p = &vec[XS_WATCH_PATH][
252 strlen(vec[XS_WATCH_PATH]) - sizeof("state")];
253 if (p[0] != '/')
254 goto next1;
255 p[0] = '\0';
256 p++;
257 if (strcmp(p, "state") != 0)
258 goto next1;
260 snprintf(buf, sizeof(buf), "%s/state", vec[XS_WATCH_PATH]);
261 sstate = xs_read(xs, XBT_NULL, buf, 0);
262 if (sstate == NULL) {
263 dolog(LOG_ERR,
264 "Failed to read %s (%s)", buf, strerror(errno));
265 goto next1;
266 }
268 state = atoi(sstate);
269 snprintf(buf, sizeof(buf), "%s/hotplug-status",
270 vec[XS_WATCH_PATH]);
271 s = xs_read(xs, XBT_NULL, buf, 0);
272 if (s != NULL && state != 6 /* XenbusStateClosed */)
273 goto next2;
275 if (strncmp(vec[XS_WATCH_PATH],
276 DOMAIN_PATH "/backend/vif",
277 strlen(DOMAIN_PATH "/backend/vif")) == 0)
278 type = DEVTYPE_VIF;
280 if (strncmp(vec[XS_WATCH_PATH],
281 DOMAIN_PATH "/backend/vbd",
282 strlen(DOMAIN_PATH "/backend/vbd")) == 0)
283 type = DEVTYPE_VBD;
285 switch(type) {
286 case DEVTYPE_VIF:
287 if (s)
288 free(s);
289 snprintf(buf, sizeof(buf), "%s/script",
290 vec[XS_WATCH_PATH]);
291 s = xs_read(xs, XBT_NULL, buf, 0);
292 if (s == NULL) {
293 dolog(LOG_ERR,
294 "Failed to read %s (%s)", buf,
295 strerror(errno));
296 goto next2;
297 }
298 doexec(s, vec[XS_WATCH_PATH], sstate);
299 break;
301 case DEVTYPE_VBD:
302 doexec(vbd_script, vec[XS_WATCH_PATH], sstate);
303 break;
305 default:
306 break;
307 }
309 next2:
310 if (s)
311 free(s);
312 free(sstate);
314 next1:
315 free(vec);
316 }
318 return 0;
319 }