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