17 #include <xseg/xseg.h>
20 #include <xseg/protocol.h>
22 #include "common.h" /* Please fix me */
24 #define MAX_PATH_SIZE 255
25 #define MAX_FILENAME_SIZE 255
27 #define DEFAULT_NR_OPS 16
29 #define MAPPER_SANITY_CHECKS 1
32 * Globals, holding command-line arguments
34 long cmdline_mportno = -1;
35 long cmdline_bportno = -1;
36 char *cmdline_xseg_spec = NULL;
37 long cmdline_nr_ops = DEFAULT_NR_OPS;
41 struct xseg_port *mport;
42 uint32_t mportno, bportno;
45 static int usage(char *argv0)
48 "Usage: %s [-p MAPPERD_PORT]"
49 "[-b BLOCKD_POART] [-g XSEG_SPEC] [-n NR_OPS]\n\n"
51 "\tMAPPERD_PORT: xseg port to listen for requests on\n"
52 "\tBLOCKD_PORT: xseg port where blockd/filed/sosd lives\n"
53 "\tXSEG_SPEC: xseg spec as 'type:name:nr_ports:nr_requests:"
54 "request_size:extra_size:page_shift'\n"
55 "\tNR_OPS: number of outstanding xseg requests\n",
61 static int safe_atoi(char *s)
66 l = strtol(s, &endp, 10);
67 if (s != endp && *endp == '\0')
73 static void parse_cmdline(int argc, char **argv)
79 c = getopt(argc, argv, "+:hp:b:n:g:");
85 perr(PFE, 0, "Unknown option: -%c", optopt);
88 perr(PFE, 0, "Option -%c requires an argument",
96 cmdline_mportno = safe_atoi(optarg);
99 cmdline_bportno = safe_atoi(optarg);
102 cmdline_nr_ops = safe_atoi(optarg);
105 /* FIXME: Max length of spec? strdup, eww */
106 cmdline_xseg_spec = strdup(optarg);
107 if (!cmdline_xseg_spec)
108 perr(PFE, 0, "out of memory");
116 /* Sanity check for all arguments */
117 if (cmdline_mportno < 0)
118 perr(PFE, 0, "no or invalid port specified for mapperd");
119 if (cmdline_bportno != -1)
120 perr(PFE, 0, "This is a no-op 1-1 mapper. Cannot specify a blocker port");
121 //no or invalid port specified for blockd/filed/sosd");
122 if (cmdline_nr_ops < 1)
123 perr(PFE, 0, "specified outstanding request count is invalid");
124 if (!cmdline_xseg_spec)
125 perr(PFE, 0, "xseg specification is mandatory");
128 perr(PFE, 0, "Non-option arguments specified on command line");
131 static struct xseg *join_or_create(char *spec)
133 struct xseg_config config;
136 (void)xseg_parse_spec(spec, &config);
137 xseg = xseg_join(config.type, config.name, "posix", NULL);
141 (void)xseg_create(&config);
142 return xseg_join(config.type, config.name, "posix", NULL);
145 static int mapperd_loop(struct mapperd *mapperd)
148 struct xseg_request *xreq;
149 struct xseg *xseg = mapperd->xseg;
150 uint32_t mportno = mapperd->mportno;
151 char *target, buf[MAX_FILENAME_SIZE];
157 ret = xseg_prepare_wait(xseg, mportno);
158 always_assert(ret == 0);
160 xreq = xseg_accept(xseg, mportno);
162 xseg_cancel_wait(xseg, mportno);
164 * Construct a 1-1 reply immediately, make sure it fits
165 * Verify the initiator has allocated enough space for
166 * the reply and the target name fits in the map reply.
168 size_t s = sizeof(struct xseg_reply_map) +
169 2 * sizeof(struct xseg_reply_map_scatterlist);
170 target = xseg_get_target(xseg, xreq);
171 strncpy(buf, target, xreq->targetlen);
172 xseg_resize_request(xseg, xreq, xreq->targetlen, s);
173 target = xseg_get_target(xseg, xreq);
174 strncpy(target, buf, xreq->targetlen);
176 struct xseg_reply_map *mreply = (void *)xseg_get_data(xseg, xreq);
178 mreply->segs[0].offset = xreq->offset;
179 mreply->segs[0].size = xreq->size/2;
180 /* FIXME: strlcpy() would work nicely here */
181 strncpy(mreply->segs[0].target, target, xreq->targetlen);
182 mreply->segs[0].target[xreq->targetlen] = '_';
183 mreply->segs[0].target[xreq->targetlen + 1] = '1';
184 mreply->segs[0].target[xreq->targetlen + 2] = '\0';
186 mreply->segs[1].offset = xreq->offset;
187 mreply->segs[1].size = xreq->size/2;
188 /* FIXME: strlcpy() would work nicely here */
189 strncpy(mreply->segs[1].target, target, xreq->targetlen);
190 mreply->segs[1].target[xreq->targetlen] = '_';
191 mreply->segs[1].target[xreq->targetlen + 1] = '2';
192 mreply->segs[1].target[xreq->targetlen + 2] = '\0';
194 /* Respond to the initiator, signal the source port */
195 // perr(PI, 0, "completed io");
196 xreq->state |= XS_SERVED;
197 p = xseg_respond(xseg, xreq, mportno, X_ALLOC);
198 ret = xseg_signal(xseg, p);
199 // always_assert(ret == 1);
202 * If things are OK, no timeout should ever be needed.
203 * Otherwise, it's a mapperd or xseg bug.
205 xseg_wait_signal(xseg, 1000000UL);
209 /* Shouldn't reach this point */
215 * FIXME: Initialize the mapperd struct based on cmdline_* vars
217 static int mapperd_init(struct mapperd *mapperd)
221 mapperd->mportno = cmdline_mportno;
222 mapperd->bportno = cmdline_bportno;
224 /* FIXME: If xseg library fails, is errno set? */
225 if (xseg_initialize()) {
226 perr(PE, 0, "could not initialize xseg library");
231 if (! (mapperd->xseg = join_or_create(cmdline_xseg_spec))) {
232 perr(PE, 0, "could not join or create xseg with spec '%s'\n",
235 goto out_with_xseginit;
238 if (! (mapperd->mport = xseg_bind_port(mapperd->xseg, mapperd->mportno, NULL))) {
239 perr(PE, 0, "cannot bind to xseg port %ld", (long)mapperd->mportno);
241 goto out_with_xsegjoin;
244 mapperd->mportno = xseg_portno(mapperd->xseg, mapperd->mport);
245 xseg_init_local_signal(mapperd->xseg, mapperd->mportno);
246 perr(PI, 0, "mapperd on port %u of %u",
247 mapperd->mportno, mapperd->xseg->config.nr_ports);
253 xseg_leave(mapperd->xseg);
260 int main(int argc, char *argv[])
262 struct mapperd mapper;
264 init_perr("mapperd");
265 parse_cmdline(argc, argv);
267 perr(PI, 0, "v = %ld, m = %ld, b = %ld, nr_ops = %lu\n",
268 cmdline_mportno, cmdline_mportno, cmdline_bportno, cmdline_nr_ops);
270 if (mapperd_init(&mapper) < 0) {
271 perr(PFE, 0, "failed to initialize mapperd.");
272 exit(1); /* This is just to quiesce gcc's control flow analysis */
275 return mapperd_loop(&mapper);