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