2 * Copyright 2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and
30 * documentation are those of the authors and should not be
31 * interpreted as representing official policies, either expressed
32 * or implied, of GRNET S.A.
42 #include <sys/types.h>
51 #include <xseg/xseg.h>
54 #include <xseg/protocol.h>
56 #include "common.h" /* Please fix me */
58 #define MAX_PATH_SIZE 255
59 #define MAX_FILENAME_SIZE 255
61 #define DEFAULT_NR_OPS 16
63 #define MAPPER_SANITY_CHECKS 1
66 * Globals, holding command-line arguments
68 long cmdline_mportno = -1;
69 long cmdline_bportno = -1;
70 char *cmdline_xseg_spec = NULL;
71 long cmdline_nr_ops = DEFAULT_NR_OPS;
75 struct xseg_port *mport;
76 uint32_t mportno, bportno;
79 static int usage(char *argv0)
82 "Usage: %s [-p MAPPERD_PORT]"
83 "[-b BLOCKD_POART] [-g XSEG_SPEC] [-n NR_OPS]\n\n"
85 "\tMAPPERD_PORT: xseg port to listen for requests on\n"
86 "\tBLOCKD_PORT: xseg port where blockd/filed/sosd lives\n"
87 "\tXSEG_SPEC: xseg spec as 'type:name:nr_ports:nr_requests:"
88 "request_size:extra_size:page_shift'\n"
89 "\tNR_OPS: number of outstanding xseg requests\n",
95 static int safe_atoi(char *s)
100 l = strtol(s, &endp, 10);
101 if (s != endp && *endp == '\0')
107 static void parse_cmdline(int argc, char **argv)
113 c = getopt(argc, argv, "+:hp:b:n:g:");
119 perr(PFE, 0, "Unknown option: -%c", optopt);
122 perr(PFE, 0, "Option -%c requires an argument",
130 cmdline_mportno = safe_atoi(optarg);
133 cmdline_bportno = safe_atoi(optarg);
136 cmdline_nr_ops = safe_atoi(optarg);
139 /* FIXME: Max length of spec? strdup, eww */
140 cmdline_xseg_spec = strdup(optarg);
141 if (!cmdline_xseg_spec)
142 perr(PFE, 0, "out of memory");
150 /* Sanity check for all arguments */
151 if (cmdline_mportno < 0)
152 perr(PFE, 0, "no or invalid port specified for mapperd");
153 if (cmdline_bportno != -1)
154 perr(PFE, 0, "This is a no-op 1-1 mapper. Cannot specify a blocker port");
155 //no or invalid port specified for blockd/filed/sosd");
156 if (cmdline_nr_ops < 1)
157 perr(PFE, 0, "specified outstanding request count is invalid");
158 if (!cmdline_xseg_spec)
159 perr(PFE, 0, "xseg specification is mandatory");
162 perr(PFE, 0, "Non-option arguments specified on command line");
165 static struct xseg *join_or_create(char *spec)
167 struct xseg_config config;
170 (void)xseg_parse_spec(spec, &config);
171 xseg = xseg_join(config.type, config.name, "posix", NULL);
175 (void)xseg_create(&config);
176 return xseg_join(config.type, config.name, "posix", NULL);
179 static int mapperd_loop(struct mapperd *mapperd)
182 struct xseg_request *xreq;
183 struct xseg *xseg = mapperd->xseg;
184 uint32_t mportno = mapperd->mportno;
185 char *target, buf[MAX_FILENAME_SIZE];
191 ret = xseg_prepare_wait(xseg, mportno);
192 always_assert(ret == 0);
194 xreq = xseg_accept(xseg, mportno, 0);
196 xseg_cancel_wait(xseg, mportno);
198 * Construct a 1-1 reply immediately, make sure it fits
199 * Verify the initiator has allocated enough space for
200 * the reply and the target name fits in the map reply.
202 size_t s = sizeof(struct xseg_reply_map) +
203 2 * sizeof(struct xseg_reply_map_scatterlist);
204 target = xseg_get_target(xseg, xreq);
205 strncpy(buf, target, xreq->targetlen);
206 xseg_resize_request(xseg, xreq, xreq->targetlen, s);
207 target = xseg_get_target(xseg, xreq);
208 strncpy(target, buf, xreq->targetlen);
210 struct xseg_reply_map *mreply = (void *)xseg_get_data(xseg, xreq);
212 mreply->segs[0].offset = xreq->offset;
213 mreply->segs[0].size = xreq->size/2;
214 /* FIXME: strlcpy() would work nicely here */
215 strncpy(mreply->segs[0].target, target, xreq->targetlen);
216 mreply->segs[0].target[xreq->targetlen] = '_';
217 mreply->segs[0].target[xreq->targetlen + 1] = '1';
218 mreply->segs[0].target[xreq->targetlen + 2] = '\0';
220 mreply->segs[1].offset = xreq->offset;
221 mreply->segs[1].size = xreq->size/2;
222 /* FIXME: strlcpy() would work nicely here */
223 strncpy(mreply->segs[1].target, target, xreq->targetlen);
224 mreply->segs[1].target[xreq->targetlen] = '_';
225 mreply->segs[1].target[xreq->targetlen + 1] = '2';
226 mreply->segs[1].target[xreq->targetlen + 2] = '\0';
228 /* Respond to the initiator, signal the source port */
229 // perr(PI, 0, "completed io");
230 xreq->state |= XS_SERVED;
231 p = xseg_respond(xseg, xreq, mportno, X_ALLOC);
232 ret = xseg_signal(xseg, p);
233 // always_assert(ret == 1);
236 * If things are OK, no timeout should ever be needed.
237 * Otherwise, it's a mapperd or xseg bug.
239 xseg_wait_signal(xseg, 1000000UL);
243 /* Shouldn't reach this point */
249 * FIXME: Initialize the mapperd struct based on cmdline_* vars
251 static int mapperd_init(struct mapperd *mapperd)
255 mapperd->mportno = cmdline_mportno;
256 mapperd->bportno = cmdline_bportno;
258 /* FIXME: If xseg library fails, is errno set? */
259 if (xseg_initialize()) {
260 perr(PE, 0, "could not initialize xseg library");
265 if (! (mapperd->xseg = join_or_create(cmdline_xseg_spec))) {
266 perr(PE, 0, "could not join or create xseg with spec '%s'\n",
269 goto out_with_xseginit;
272 if (! (mapperd->mport = xseg_bind_port(mapperd->xseg, mapperd->mportno, NULL))) {
273 perr(PE, 0, "cannot bind to xseg port %ld", (long)mapperd->mportno);
275 goto out_with_xsegjoin;
278 mapperd->mportno = xseg_portno(mapperd->xseg, mapperd->mport);
279 xseg_init_local_signal(mapperd->xseg, mapperd->mportno);
280 perr(PI, 0, "mapperd on port %u of %u",
281 mapperd->mportno, mapperd->xseg->config.nr_ports);
287 xseg_leave(mapperd->xseg);
294 int main(int argc, char *argv[])
296 struct mapperd mapper;
298 init_perr("mapperd");
299 parse_cmdline(argc, argv);
301 perr(PI, 0, "v = %ld, m = %ld, b = %ld, nr_ops = %lu\n",
302 cmdline_mportno, cmdline_mportno, cmdline_bportno, cmdline_nr_ops);
304 if (mapperd_init(&mapper) < 0) {
305 perr(PFE, 0, "failed to initialize mapperd.");
306 exit(1); /* This is just to quiesce gcc's control flow analysis */
309 return mapperd_loop(&mapper);