1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
5 * Author: Robert Read <rread@clusterfs.com>
7 * This file is part of Lustre, http://www.lustre.org.
9 * Lustre is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU General Public
11 * License as published by the Free Software Foundation.
13 * Lustre is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with Lustre; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/mount.h>
36 #include <portals/ptlctl.h>
42 static char *progname = NULL;
50 #define MAX_ROUTES 1024
52 ptl_nid_t lmd_cluster_id = 0;
53 llmount_route_t routes[MAX_ROUTES];
55 static int check_mtab_entry(char *spec, char *mtpt, char *type)
61 fp = setmntent(MOUNTED, "r");
65 while ((mnt = getmntent(fp)) != NULL) {
66 if (strcmp(mnt->mnt_fsname, spec) == 0 &&
67 strcmp(mnt->mnt_dir, mtpt) == 0 &&
68 strcmp(mnt->mnt_type, type) == 0) {
69 fprintf(stderr, "%s: according to %s %s is "
70 "already mounted on %s\n",
71 progname, MOUNTED, spec, mtpt);
72 return(1); /* or should we return an error? */
81 update_mtab_entry(char *spec, char *mtpt, char *type, char *opts,
82 int flags, int freq, int pass)
87 mnt.mnt_fsname = spec;
90 mnt.mnt_opts = opts ? opts : "";
92 mnt.mnt_passno = pass;
95 fp = setmntent(MOUNTED, "a+");
97 fprintf(stderr, "%s: setmntent(%s): %s:",
98 progname, MOUNTED, strerror (errno));
100 if ((addmntent (fp, &mnt)) == 1) {
101 fprintf(stderr, "%s: addmntent: %s:",
102 progname, strerror (errno));
110 init_options(struct lustre_mount_data *lmd)
112 memset(lmd, 0, sizeof(*lmd));
113 lmd->lmd_magic = LMD_MAGIC;
114 lmd->lmd_server_nid = PTL_NID_ANY;
115 lmd->lmd_local_nid = PTL_NID_ANY;
116 lmd->lmd_port = 988; /* XXX define LUSTRE_DEFAULT_PORT */
117 lmd->lmd_nal = SOCKNAL;
122 print_options(struct lustre_mount_data *lmd)
126 printf("mds: %s\n", lmd->lmd_mds);
127 printf("profile: %s\n", lmd->lmd_profile);
128 printf("server_nid: "LPX64"\n", lmd->lmd_server_nid);
129 printf("local_nid: "LPX64"\n", lmd->lmd_local_nid);
130 printf("nal: %d\n", lmd->lmd_nal);
131 printf("server_ipaddr: 0x%x\n", lmd->lmd_server_ipaddr);
132 printf("port: %d\n", lmd->lmd_port);
134 for (i = 0; i < route_index; i++)
135 printf("route: 0x%llx : 0x%llx - 0x%llx\n",
136 routes[i].gw, routes[i].lo, routes[i].hi);
141 static int parse_route(char *opteq, char *opttgts)
143 char *gw_lo_ptr, *gw_hi_ptr, *tgt_lo_ptr, *tgt_hi_ptr;
144 ptl_nid_t gw_lo, gw_hi, tgt_lo, tgt_hi;
147 gw_lo_ptr = opteq + 1;
148 if (!(gw_hi_ptr = strchr(gw_lo_ptr, '-'))) {
149 gw_hi_ptr = gw_lo_ptr;
155 if (ptl_parse_nid(&gw_lo, gw_lo_ptr) != 0) {
156 fprintf(stderr, "%s: can't parse NID %s\n", progname,gw_lo_ptr);
160 if (ptl_parse_nid(&gw_hi, gw_hi_ptr) != 0) {
161 fprintf(stderr, "%s: can't parse NID %s\n", progname,gw_hi_ptr);
165 tgt_lo_ptr = opttgts + 1;
166 if (!(tgt_hi_ptr = strchr(tgt_lo_ptr, '-'))) {
167 tgt_hi_ptr = tgt_lo_ptr;
169 tgt_hi_ptr[0] = '\0';
173 if (ptl_parse_nid(&tgt_lo, tgt_lo_ptr) != 0) {
174 fprintf(stderr, "%s: can't parse NID %s\n",progname,tgt_lo_ptr);
178 if (ptl_parse_nid(&tgt_hi, tgt_hi_ptr) != 0) {
179 fprintf(stderr, "%s: can't parse NID %s\n",progname,tgt_hi_ptr);
183 while (gw_lo <= gw_hi) {
184 if (route_index >= MAX_ROUTES) {
185 fprintf(stderr, "%s: to many routes %d\n",
186 progname, MAX_ROUTES);
190 routes[route_index].gw = gw_lo;
191 routes[route_index].lo = tgt_lo;
192 routes[route_index].hi = tgt_hi;
200 int parse_options(char * options, struct lustre_mount_data *lmd)
202 ptl_nid_t nid = 0, cluster_id = 0;
204 char *opt, *opteq, *opttgts;
206 /* parsing ideas here taken from util-linux/mount/nfsmount.c */
207 for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
208 if ((opteq = strchr(opt, '='))) {
209 val = atoi(opteq + 1);
211 if (!strcmp(opt, "nettype")) {
212 lmd->lmd_nal = ptl_name2nal(opteq + 1);
213 } else if(!strcmp(opt, "cluster_id")) {
214 if (ptl_parse_nid(&cluster_id, opteq+1) != 0) {
215 fprintf (stderr, "%s: can't parse NID "
216 "%s\n", progname, opteq+1);
219 lmd_cluster_id = cluster_id;
220 } else if(!strcmp(opt, "route")) {
221 if (!(opttgts = strchr(opteq + 1, ':'))) {
222 fprintf(stderr, "%s: Route must be "
223 "of the form: route="
224 "<gw>[-<gw>]:<low>[-<high>]\n",
228 parse_route(opteq, opttgts);
229 } else if (!strcmp(opt, "local_nid")) {
230 if (ptl_parse_nid(&nid, opteq + 1) != 0) {
231 fprintf (stderr, "%s: "
232 "can't parse NID %s\n",
237 lmd->lmd_local_nid = nid;
238 } else if (!strcmp(opt, "server_nid")) {
239 if (ptl_parse_nid(&nid, opteq + 1) != 0) {
240 fprintf (stderr, "%s: "
241 "can't parse NID %s\n",
242 progname, opteq + 1);
245 lmd->lmd_server_nid = nid;
246 } else if (!strcmp(opt, "port")) {
249 else if (!strcmp(opt, "clone")) {
250 lmd->lmd_clone_index = val;
254 if (!strncmp(opt, "no", 2)) {
258 if (!strcmp(opt, "debug")) {
267 get_local_elan_id(char *fname, char *buf)
269 FILE *fp = fopen(fname, "r");
275 rc = fscanf(fp, "NodeId %255s", buf);
279 return (rc == 1) ? 0 : -1;
283 set_local(struct lustre_mount_data *lmd)
286 * XXX PtlGetId() will be safer if portals is loaded and
287 * initialised correctly at this time... */
292 if (lmd->lmd_local_nid != PTL_NID_ANY)
295 memset(buf, 0, sizeof(buf));
297 if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
298 rc = gethostname(buf, sizeof(buf) - 1);
300 fprintf (stderr, "%s: can't get local buf: %d\n",
304 } else if (lmd->lmd_nal == QSWNAL) {
305 char *pfiles[] = {"/proc/qsnet/elan3/device0/position",
306 "/proc/qsnet/elan4/device0/position",
307 "/proc/elan/device0/position",
312 rc = get_local_elan_id(pfiles[i], buf);
313 } while (rc != 0 && pfiles[++i] != NULL);
316 fprintf(stderr, "%s: can't read Elan ID from /proc\n",
323 if (ptl_parse_nid (&nid, buf) != 0) {
324 fprintf (stderr, "%s: can't parse NID %s\n", progname, buf);
328 lmd->lmd_local_nid = nid + lmd_cluster_id;
333 set_peer(char *hostname, struct lustre_mount_data *lmd)
338 if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
339 if (lmd->lmd_server_nid == PTL_NID_ANY) {
340 if (ptl_parse_nid (&nid, hostname) != 0) {
341 fprintf (stderr, "%s: can't parse NID %s\n",
345 lmd->lmd_server_nid = nid;
348 if (ptl_parse_ipaddr(&lmd->lmd_server_ipaddr, hostname) != 0) {
349 fprintf (stderr, "%s: can't parse host %s\n",
353 } else if (lmd->lmd_nal == QSWNAL) {
355 rc = sscanf(hostname, "%*[^0-9]%63[0-9]", buf);
357 fprintf (stderr, "%s: can't get elan id from host %s\n",
361 if (ptl_parse_nid (&nid, buf) != 0) {
362 fprintf (stderr, "%s: can't parse NID %s\n",
366 lmd->lmd_server_nid = nid;
374 build_data(char *source, char *options, struct lustre_mount_data *lmd)
377 char *hostname = NULL, *mds = NULL, *profile = NULL, *s;
380 if (lmd_bad_magic(lmd))
383 if (strlen(source) > sizeof(buf) + 1) {
384 fprintf(stderr, "%s: host:/mds/profile argument too long\n",
389 if ((s = strchr(buf, ':'))) {
396 if ((s = strchr(mds, '/'))) {
400 fprintf(stderr, "%s: directory to mount not in "
401 "host:/mds/profile format\n",
406 fprintf(stderr, "%s: "
407 "directory to mount not in host:/mds/profile format\n",
412 rc = parse_options(options, lmd);
420 rc = set_peer(hostname, lmd);
423 if (strlen(mds) > sizeof(lmd->lmd_mds) + 1) {
424 fprintf(stderr, "%s: mds name too long\n", progname);
427 strcpy(lmd->lmd_mds, mds);
429 if (strlen(profile) > sizeof(lmd->lmd_profile) + 1) {
430 fprintf(stderr, "%s: profile name too long\n", progname);
433 strcpy(lmd->lmd_profile, profile);
440 static int set_routes(struct lustre_mount_data *lmd) {
441 struct portals_cfg pcfg;
442 struct portal_ioctl_data data;
443 int i, j, route_exists, rc, err = 0;
445 register_ioc_dev(PORTALS_DEV_ID, PORTALS_DEV_PATH);
447 for (i = 0; i < route_index; i++) {
449 /* Check for existing routes so as not to add duplicates */
451 PCFG_INIT(pcfg, NAL_CMD_GET_ROUTE);
452 pcfg.pcfg_nal = ROUTER;
455 PORTAL_IOC_INIT(data);
456 data.ioc_pbuf1 = (char*)&pcfg;
457 data.ioc_plen1 = sizeof(pcfg);
458 data.ioc_nid = pcfg.pcfg_nid;
460 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
466 if ((pcfg.pcfg_gw_nal == lmd->lmd_nal) &&
467 (pcfg.pcfg_nid == routes[i].gw) &&
468 (pcfg.pcfg_nid2 == routes[i].lo) &&
469 (pcfg.pcfg_nid3 == routes[i].hi)) {
478 PCFG_INIT(pcfg, NAL_CMD_ADD_ROUTE);
479 pcfg.pcfg_nid = routes[i].gw;
480 pcfg.pcfg_nal = ROUTER;
481 pcfg.pcfg_gw_nal = lmd->lmd_nal;
482 pcfg.pcfg_nid2 = MIN(routes[i].lo, routes[i].hi);
483 pcfg.pcfg_nid3 = MAX(routes[i].lo, routes[i].hi);
485 PORTAL_IOC_INIT(data);
486 data.ioc_pbuf1 = (char*)&pcfg;
487 data.ioc_plen1 = sizeof(pcfg);
488 data.ioc_nid = pcfg.pcfg_nid;
490 rc = l_ioctl(PORTALS_DEV_ID, IOC_PORTAL_NAL_CMD, &data);
492 fprintf(stderr, "%s: Unable to add route "
493 "0x%llx : 0x%llx - 0x%llx\n[%d] %s\n",
494 progname, routes[i].gw, routes[i].lo,
495 routes[i].hi, errno, strerror(errno));
501 unregister_ioc_dev(PORTALS_DEV_ID);
505 void usage(FILE *out)
507 fprintf(out, "usage: %s <source> <target> [-f] [-v] [-n] [-o mntopt]\n",
512 int main(int argc, char *const argv[])
514 char *source, *target, *options = "";
515 int i, nargs = 3, opt, rc;
516 struct lustre_mount_data lmd;
517 static struct option long_opt[] = {
518 {"force", 0, 0, 'f'},
520 {"nomtab", 0, 0, 'n'},
521 {"options", 1, 0, 'o'},
522 {"verbose", 0, 0, 'v'},
526 progname = strrchr(argv[0], '/');
527 progname = progname ? progname + 1 : argv[0];
529 while ((opt = getopt_long(argc, argv, "fno:v", long_opt, NULL)) != EOF){
533 printf("force: %d\n", force);
541 printf("nomtab: %d\n", nomtab);
550 printf("verbose: %d\n", verbose);
554 fprintf(stderr, "%s: unknown option '%c'\n",
561 if (optind + 2 > argc) {
562 fprintf(stderr, "%s: too few arguments\n", progname);
566 source = argv[optind];
567 target = argv[optind + 1];
570 for (i = 0; i < argc; i++)
571 printf("arg[%d] = %s\n", i, argv[i]);
572 printf("source = %s, target = %s\n", source, target);
575 if (check_mtab_entry(source, target, "lustre"))
579 rc = build_data(source, options, &lmd);
584 rc = set_routes(&lmd);
590 printf("%s: debug mode, not mounting\n", progname);
594 rc = mount(source, target, "lustre", 0, (void *)&lmd);
599 fprintf(stderr, "Are the lustre modules loaded?\n"
600 "Check /etc/modules.conf and /proc/filesystems\n");
602 update_mtab_entry(source, target, "lustre", options, 0, 0, 0);