Whamcloud - gitweb
Landing b_elan4.
[fs/lustre-release.git] / lustre / utils / llmount.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2002 Cluster File Systems, Inc.
5  *   Author: Robert Read <rread@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
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.
12  *
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.
17  *
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.
21  *
22  */
23
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <sys/mount.h>
31 #include <mntent.h>
32
33 #include "obdctl.h"
34 #include <portals/ptlctl.h>
35
36 int debug = 0;
37 int verbose = 0;
38 int nomtab = 0;
39
40 static void
41 update_mtab_entry(char *spec, char *node, char *type, char *opts,
42                   int flags, int freq, int pass)
43 {
44         FILE *fp;
45         struct mntent mnt;
46
47         mnt.mnt_fsname = spec;
48         mnt.mnt_dir = node;
49         mnt.mnt_type = type;
50         mnt.mnt_opts = opts ? opts : "";
51         mnt.mnt_freq = freq;
52         mnt.mnt_passno = pass;
53
54         if (!nomtab) {
55                 fp = setmntent(MOUNTED, "a+");
56                 if (fp == NULL) {
57                         fprintf(stderr, "setmntent(%s): %s:", MOUNTED,
58                                 strerror (errno));
59                 } else {
60                         if ((addmntent (fp, &mnt)) == 1) {
61                                 fprintf(stderr, "addmntent: %s:",
62                                         strerror (errno));
63                         }
64                         endmntent(fp);
65                 }
66         }
67 }
68
69 int
70 init_options(struct lustre_mount_data *lmd)
71 {
72         memset(lmd, 0, sizeof(lmd));
73         lmd->lmd_server_nid = PTL_NID_ANY;
74         lmd->lmd_local_nid = PTL_NID_ANY;
75         lmd->lmd_port = 988;    /* XXX define LUSTRE_DEFAULT_PORT */
76         lmd->lmd_nal = SOCKNAL;
77         return 0;
78 }
79
80 int
81 print_options(struct lustre_mount_data *lmd)
82 {
83         printf("mds:             %s\n", lmd->lmd_mds);
84         printf("profile:         %s\n", lmd->lmd_profile);
85         printf("server_nid:      "LPX64"\n", lmd->lmd_server_nid);
86         printf("local_nid:       "LPX64"\n", lmd->lmd_local_nid);
87         printf("nal:             %d\n", lmd->lmd_nal);
88         printf("server_ipaddr:   0x%x\n", lmd->lmd_server_ipaddr);
89         printf("port:            %d\n", lmd->lmd_port);
90
91         return 0;
92 }
93
94 int
95 parse_options(char * options, struct lustre_mount_data *lmd)
96 {
97         ptl_nid_t nid = 0;
98         int val;
99         char *opt;
100         char * opteq;
101         
102         /* parsing ideas here taken from util-linux/mount/nfsmount.c */
103         for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
104                 if ((opteq = strchr(opt, '='))) {
105                         val = atoi(opteq + 1);
106                         *opteq = '\0';
107                         if (!strcmp(opt, "nettype")) {
108                                 lmd->lmd_nal = ptl_name2nal(opteq+1);
109                         } else if(!strcmp(opt, "local_nid")) {
110                                 if (ptl_parse_nid(&nid, opteq+1) != 0) {
111                                         fprintf (stderr, "mount: "
112                                                  "can't parse NID %s\n",
113                                                  opteq+1);
114                                         return (-1);
115                                 }
116                                 lmd->lmd_local_nid = nid;
117                         } else if(!strcmp(opt, "server_nid")) {
118                                 if (ptl_parse_nid(&nid, opteq+1) != 0) {
119                                         fprintf (stderr, "mount: "
120                                                  "can't parse NID %s\n",
121                                                  opteq+1);
122                                         return (-1);
123                                 }
124                                 lmd->lmd_server_nid = nid;
125                         } else if (!strcmp(opt, "port")) {
126                                 lmd->lmd_port = val;
127                         }
128                 } else {
129                         val = 1;
130                         if (!strncmp(opt, "no", 2)) {
131                                 val = 0;
132                                 opt += 2;
133                         }
134                         if (!strcmp(opt, "debug")) {
135                                 debug = val;
136                         }
137                 }
138         }
139         return 0;
140 }
141
142 int
143 get_local_elan_id(char *fname, char *buf)
144 {
145         FILE *fp = fopen(fname, "r");
146         int   rc;
147
148         if (fp == NULL)
149                 return -1;
150
151         rc = fscanf(fp, "NodeId %255s", buf);
152
153         fclose(fp);
154
155         return (rc == 1) ? 0 : -1;
156 }
157
158 int
159 set_local(struct lustre_mount_data *lmd)
160 {
161         /* XXX ClusterID?
162          * XXX PtlGetId() will be safer if portals is loaded and
163          * initialised correctly at this time... */
164         char buf[256];
165         ptl_nid_t nid;
166         int rc;
167
168         if (lmd->lmd_local_nid != PTL_NID_ANY)
169                 return 0;
170
171         memset(buf, 0, sizeof(buf));
172
173         if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
174                 rc = gethostname(buf, sizeof(buf) - 1);
175                 if (rc) {
176                         fprintf (stderr, "mount: can't get local buf:"
177                                  "%d\n", rc);
178                         return rc;
179                 }
180         } else if (lmd->lmd_nal == QSWNAL) {
181 #if MULTIRAIL_EKC
182                 char *pfiles[] = {"/proc/qsnet/elan3/device0/position",
183                                   "/proc/qsnet/elan4/device0/position",
184                                   NULL};
185 #else
186                 char *pfiles[] = {"/proc/elan/device0/position",
187                                   NULL};
188 #endif
189                 int   i = 0;
190
191                 do {
192                         rc = get_local_elan_id(pfiles[i], buf);
193                 } while (rc != 0 &&
194                          pfiles[++i] != NULL);
195                 
196                 if (rc != 0) {
197                         fprintf(stderr, "mount: can't read elan ID"
198                                 " from /proc\n");
199                         return -1;
200                 }
201         }
202
203         if (ptl_parse_nid (&nid, buf) != 0) {
204                 fprintf (stderr, "mount: can't parse NID %s\n", 
205                          buf);
206                 return (-1);
207         }
208
209         lmd->lmd_local_nid = nid;
210         return 0;
211 }
212
213 int
214 set_peer(char *hostname, struct lustre_mount_data *lmd)
215 {
216         ptl_nid_t nid = 0;
217         int rc;
218
219         if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
220                 if (lmd->lmd_server_nid == PTL_NID_ANY) {
221                         if (ptl_parse_nid (&nid, hostname) != 0) {
222                                 fprintf (stderr, "mount: can't parse NID %s\n",
223                                          hostname);
224                                 return (-1);
225                         }
226                         lmd->lmd_server_nid = nid;
227                 }
228
229                 if (ptl_parse_ipaddr(&lmd->lmd_server_ipaddr, hostname) != 0) {
230                         fprintf (stderr, "mount: can't parse host %s\n",
231                                  hostname);
232                         return (-1);
233                 }
234         } else if (lmd->lmd_nal == QSWNAL) {
235                 char buf[64];
236                 rc = sscanf(hostname, "%*[^0-9]%63[0-9]", buf);
237                 if (rc != 1) {
238                         fprintf (stderr, "mount: can't get elan id from host %s\n",
239                                  hostname);
240                         return -1;
241                 }
242                 if (ptl_parse_nid (&nid, buf) != 0) {
243                         fprintf (stderr, "mount: can't parse NID %s\n",
244                                  hostname);
245                         return (-1);
246                 }
247                 lmd->lmd_server_nid = nid;
248         }
249
250
251         return 0;
252 }
253
254 int
255 build_data(char *source, char *options, struct lustre_mount_data *lmd)
256 {
257         char target[1024];
258         char *hostname = NULL;
259         char *mds = NULL;
260         char *profile = NULL;
261         char *s;
262         int rc;
263
264         if (strlen(source) > sizeof(target) + 1) {
265                 fprintf(stderr, "mount: "
266                         "exessively long host:/mds/profile argument\n");
267                 return -EINVAL;
268         }
269         strcpy(target, source);
270         if ((s = strchr(target, ':'))) {
271                 hostname = target;
272                 *s = '\0';
273
274                 while (*++s == '/')
275                         ;
276                 mds = s;
277                 if ((s = strchr(mds, '/'))) {
278                         *s = '\0';
279                         profile = s + 1;
280                 } else {
281                         fprintf(stderr, "mount: "
282                                 "directory to mount not in "
283                                 "host:/mds/profile format\n");
284                         return(-1);
285                 }
286         } else {
287                 fprintf(stderr, "mount: "
288                         "directory to mount not in host:/mds/profile format\n");
289                 return(-1);
290         }
291         if (verbose)
292                 printf("host: %s\nmds: %s\nprofile: %s\n", hostname, mds,
293                        profile);
294
295         rc = parse_options(options, lmd);
296         if (rc)
297                 return rc;
298
299         rc = set_local(lmd);
300         if (rc)
301                 return rc;
302
303         rc = set_peer(hostname, lmd);
304         if (rc)
305                 return rc;
306         if (strlen(mds) > sizeof(lmd->lmd_mds) + 1) {
307                 fprintf(stderr, "mount: mds name too long\n");
308                 return(-1);
309         }
310         strcpy(lmd->lmd_mds, mds);
311
312         if (strlen(profile) > sizeof(lmd->lmd_profile) + 1) {
313                 fprintf(stderr, "mount: profile name too long\n");
314                 return(-1);
315         }
316         strcpy(lmd->lmd_profile, profile);
317
318         
319         if (verbose)
320                 print_options(lmd);
321         return 0;
322 }
323
324 int
325 main(int argc, char * const argv[])
326 {
327         char * source = argv[1];
328         char * target = argv[2];
329         char * options = "";
330         int opt;
331         int i;
332         struct lustre_mount_data lmd;
333
334         int rc;
335
336         while ((opt = getopt(argc, argv, "vno:")) != EOF) {
337                 switch (opt) {
338                 case 'v':
339                         verbose = 1;
340                         printf("verbose: %d\n", verbose);
341                         break;
342                 case 'n':
343                         nomtab = 1;
344                         printf("nomtab: %d\n", nomtab);
345                         break;
346                 case 'o':
347                         options = optarg;
348                         break;
349                 default:
350                         break;
351                 }
352         }
353
354         if (verbose)
355                 for (i = 0; i < argc; i++) {
356                         printf("arg[%d] = %s\n", i, argv[i]);
357                 }
358
359         init_options(&lmd);
360         rc = build_data(source, options, &lmd);
361         if (rc) {
362                 exit(1);
363         }
364
365         if (debug) {
366                 printf("mount: debug mode, not mounting\n");
367                 exit(0);
368         }
369
370         rc = mount(source, target, "lustre", 0, (void *)&lmd);
371         if (rc) {
372                 perror(argv[0]);
373         } else {
374                 update_mtab_entry(source, target, "lustre", options, 0, 0, 0);
375         }
376         return rc;
377 }