Whamcloud - gitweb
b=2421
[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 set_local(struct lustre_mount_data *lmd)
144 {
145         char buf[256];
146         ptl_nid_t nid;
147         int rc;
148
149         if (lmd->lmd_local_nid != PTL_NID_ANY)
150                 return 0;
151
152         memset(buf, 0, sizeof(buf));
153
154         if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
155                 rc = gethostname(buf, sizeof(buf) - 1);
156                 if (rc) {
157                         fprintf (stderr, "mount: can't get local buf:"
158                                  "%d\n", rc);
159                         return rc;
160                 }
161         } else if (lmd->lmd_nal == QSWNAL) {
162                 FILE *fp;
163                 fp = fopen("/proc/elan/device0/position", "r");
164                 if (fp == NULL) {
165                         perror("mount: /proc/elan/device0/position");
166                         return -1;
167                 }
168                 rc = fscanf(fp, "%*s %255s", buf);
169                 fclose(fp);
170                 if (rc != 1) {
171                         fprintf(stderr, "mount: problem read elan NID");
172                         return -1;
173                 }
174                 
175         }
176
177         if (ptl_parse_nid (&nid, buf) != 0) {
178                 fprintf (stderr, "mount: can't parse NID %s\n", 
179                          buf);
180                 return (-1);
181         }
182
183         lmd->lmd_local_nid = nid;
184         return 0;
185 }
186
187 int
188 set_peer(char *hostname, struct lustre_mount_data *lmd)
189 {
190         ptl_nid_t nid = 0;
191         int rc;
192
193         if (lmd->lmd_nal == SOCKNAL || lmd->lmd_nal == TCPNAL) {
194                 if (lmd->lmd_server_nid == PTL_NID_ANY) {
195                         if (ptl_parse_nid (&nid, hostname) != 0) {
196                                 fprintf (stderr, "mount: can't parse NID %s\n",
197                                          hostname);
198                                 return (-1);
199                         }
200                         lmd->lmd_server_nid = nid;
201                 }
202
203                 if (ptl_parse_ipaddr(&lmd->lmd_server_ipaddr, hostname) != 0) {
204                         fprintf (stderr, "mount: can't parse host %s\n",
205                                  hostname);
206                         return (-1);
207                 }
208         } else if (lmd->lmd_nal == QSWNAL) {
209                 char buf[64];
210                 rc = sscanf(hostname, "%*[^0-9]%63[0-9]", buf);
211                 if (rc != 1) {
212                         fprintf (stderr, "mount: can't get elan id from host %s\n",
213                                  hostname);
214                         return -1;
215                 }
216                 if (ptl_parse_nid (&nid, buf) != 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
225         return 0;
226 }
227
228 int
229 build_data(char *source, char *options, struct lustre_mount_data *lmd)
230 {
231         char target[1024];
232         char *hostname = NULL;
233         char *mds = NULL;
234         char *profile = NULL;
235         char *s;
236         int rc;
237
238         if (strlen(source) > sizeof(target) + 1) {
239                 fprintf(stderr, "mount: "
240                         "exessively long host:/mds/profile argument\n");
241                 return -EINVAL;
242         }
243         strcpy(target, source);
244         if ((s = strchr(target, ':'))) {
245                 hostname = target;
246                 *s = '\0';
247
248                 while (*++s == '/')
249                         ;
250                 mds = s;
251                 if ((s = strchr(mds, '/'))) {
252                         *s = '\0';
253                         profile = s + 1;
254                 } else {
255                         fprintf(stderr, "mount: "
256                                 "directory to mount not in "
257                                 "host:/mds/profile format\n");
258                         return(-1);
259                 }
260         } else {
261                 fprintf(stderr, "mount: "
262                         "directory to mount not in host:/mds/profile format\n");
263                 return(-1);
264         }
265         if (verbose)
266                 printf("host: %s\nmds: %s\nprofile: %s\n", hostname, mds,
267                        profile);
268
269         rc = parse_options(options, lmd);
270         if (rc)
271                 return rc;
272
273         rc = set_local(lmd);
274         if (rc)
275                 return rc;
276
277         rc = set_peer(hostname, lmd);
278         if (rc)
279                 return rc;
280         if (strlen(mds) > sizeof(lmd->lmd_mds) + 1) {
281                 fprintf(stderr, "mount: mds name too long\n");
282                 return(-1);
283         }
284         strcpy(lmd->lmd_mds, mds);
285
286         if (strlen(profile) > sizeof(lmd->lmd_profile) + 1) {
287                 fprintf(stderr, "mount: profile name too long\n");
288                 return(-1);
289         }
290         strcpy(lmd->lmd_profile, profile);
291
292         
293         if (verbose)
294                 print_options(lmd);
295         return 0;
296 }
297
298 int
299 main(int argc, char * const argv[])
300 {
301         char * source = argv[1];
302         char * target = argv[2];
303         char * options = "";
304         int opt;
305         int i;
306         struct lustre_mount_data lmd;
307
308         int rc;
309
310         while ((opt = getopt(argc, argv, "vno:")) != EOF) {
311                 switch (opt) {
312                 case 'v':
313                         verbose = 1;
314                         printf("verbose: %d\n", verbose);
315                         break;
316                 case 'n':
317                         nomtab = 1;
318                         printf("nomtab: %d\n", nomtab);
319                         break;
320                 case 'o':
321                         options = optarg;
322                         break;
323                 default:
324                         break;
325                 }
326         }
327
328         if (verbose)
329                 for (i = 0; i < argc; i++) {
330                         printf("arg[%d] = %s\n", i, argv[i]);
331                 }
332
333         init_options(&lmd);
334         rc = build_data(source, options, &lmd);
335         if (rc) {
336                 exit(1);
337         }
338
339         if (debug) {
340                 printf("mount: debug mode, not mounting\n");
341                 exit(0);
342         }
343
344         rc = mount(source, target, "lustre", 0, (void *)&lmd);
345         if (rc) {
346                 perror(argv[0]);
347         } else {
348                 update_mtab_entry(source, target, "lustre", options, 0, 0, 0);
349         }
350         return rc;
351 }