Whamcloud - gitweb
new version llog_reader
[fs/lustre-release.git] / lustre / utils / mount_lustre.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  *   Author: Nathan Rutman <nathan@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25
26 #define _GNU_SOURCE
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/mount.h>
34 #include <mntent.h>
35 #include <getopt.h>
36 #include <sys/utsname.h>
37
38 #include <linux/lustre_disk.h>
39 #include <portals/ptlctl.h>
40 #include "obdctl.h"
41
42 int          verbose;
43 int          nomtab;
44 int          fake;
45 int          force;
46 static char *progname = NULL;
47
48 void usage(FILE *out)
49 {
50         fprintf(out, "usage: %s <mdsnode>:/<mdsname>/<cfgname> <mountpt> "
51                 "[-fhnv] [-o mntopt]\n", progname);
52         fprintf(out, "\t<mdsnode>: nid of MDS (config) node\n"
53                 "\t<mdsname>: name of MDS service (e.g. mds1)\n"
54                 "\t<cfgname>: name of client config (e.g. client)\n"
55                 "\t<mountpt>: filesystem mountpoint (e.g. /mnt/lustre)\n"
56                 "\t-f|--fake: fake mount (updates /etc/mtab)\n"
57                 "\t--force: force mount even if already in /etc/mtab\n"
58                 "\t-h|--help: print this usage message\n"
59                 "\t-n|--nomtab: do not update /etc/mtab after mount\n"
60                 "\t-v|--verbose: print verbose config settings\n");
61         exit(out != stdout);
62 }
63
64 int get_os_version()
65 {
66         static int version = 0;
67
68         if (!version) {
69                 int fd;
70                 char release[4] = "";
71
72                 fd = open("/proc/sys/kernel/osrelease", O_RDONLY);
73                 if (fd < 0) 
74                         fprintf(stderr, "Warning: Can't resolve kernel version,"
75                         " assuming 2.6\n");
76                 else {
77                         read(fd, release, 4);
78                         close(fd);
79                 }
80                 if (strncmp(release, "2.4.", 4) == 0) 
81                         version = 24;
82                 else 
83                         version = 26;
84         }
85         return version;
86 }
87
88 static int load_module(char *module_name)
89 {
90         char buf[256];
91         int rc;
92         
93         if (verbose)
94                 printf("loading %s\n", module_name);
95         sprintf(buf, "/sbin/modprobe %s", module_name);
96         rc = system(buf);
97         if (rc) {
98                 fprintf(stderr, "%s: failed to modprobe %s: %s\n", 
99                         progname, module_name, strerror(errno));
100                 fprintf(stderr, "Check /etc/modules.conf\n");
101         }
102         return rc;
103 }
104
105 static int load_modules(struct lustre_mount_data *lmd)
106 {
107         int rc = 0;
108
109         if (lmd_is_client(lmd)) {
110                 rc = load_module("lustre");
111         } else {
112                 rc = load_module("mds");
113                 if (rc) return rc;
114                 rc = load_module("oss");
115         }
116         return rc;
117 }
118
119 static int check_mtab_entry(char *spec, char *mtpt, char *type)
120 {
121         FILE *fp;
122         struct mntent *mnt;
123
124         if (force)
125                 return (0);
126
127         fp = setmntent(MOUNTED, "r");
128         if (fp == NULL)
129                 return(0);
130
131         while ((mnt = getmntent(fp)) != NULL) {
132                 if (strcmp(mnt->mnt_fsname, spec) == 0 &&
133                         strcmp(mnt->mnt_dir, mtpt) == 0 &&
134                         strcmp(mnt->mnt_type, type) == 0) {
135                         fprintf(stderr, "%s: according to %s %s is "
136                                 "already mounted on %s\n",
137                                 progname, MOUNTED, spec, mtpt);
138                         return(1); /* or should we return an error? */
139                 }
140         }
141         endmntent(fp);
142
143         return(0);
144 }
145
146 static int
147 update_mtab_entry(char *spec, char *mtpt, char *type, char *opts,
148                   int flags, int freq, int pass)
149 {
150         FILE *fp;
151         struct mntent mnt;
152         int rc = 0;
153
154         mnt.mnt_fsname = spec;
155         mnt.mnt_dir = mtpt;
156         mnt.mnt_type = type;
157         mnt.mnt_opts = opts ? opts : "";
158         mnt.mnt_freq = freq;
159         mnt.mnt_passno = pass;
160
161         fp = setmntent(MOUNTED, "a+");
162         if (fp == NULL) {
163                 fprintf(stderr, "%s: setmntent(%s): %s:",
164                         progname, MOUNTED, strerror (errno));
165                 rc = 16;
166         } else {
167                 if ((addmntent(fp, &mnt)) == 1) {
168                         fprintf(stderr, "%s: addmntent: %s:",
169                                 progname, strerror (errno));
170                         rc = 16;
171                 }
172                 endmntent(fp);
173         }
174
175         return rc;
176 }
177
178 int
179 init_options(struct lustre_mount_data *lmd)
180 {
181         memset(lmd, 0, sizeof(*lmd));
182         //gethostname(lmd->lmd_hostname, sizeof lmd->lmd_hostname);
183         //lmd->lmd_server_nid = PTL_NID_ANY;
184         //ptl_parse_nid(&lmd->lmd_nid, lmd->lmd_hostname);
185         //lmd->lmd_port = 988;    /* XXX define LUSTRE_DEFAULT_PORT */
186         //lmd->lmd_nal = SOCKNAL;
187         //ptl_parse_ipaddr(&lmd->lmd_ipaddr, lmd->lmd_hostname); 
188         lmd->lmd_magic = LMD_MAGIC;
189         lmd->lmd_flags = LMD_FLG_MNTCNF;
190         lmd->lmd_mgsnid.primary = PTL_NID_ANY;
191         lmd->lmd_mgsnid.backup  = PTL_NID_ANY;
192         return 0;
193 }
194
195 int
196 print_options(struct lustre_mount_data *lmd)
197 {
198         printf("mgmt primary nid: %s\n",
199                libcfs_nid2str(lmd->lmd_mgsnid.primary));
200         printf("mgmt backup nid:  %s\n",
201                libcfs_nid2str(lmd->lmd_mgsnid.backup));
202         printf("device:           %s\n", lmd->lmd_dev);
203         printf("mount point:      %s\n", lmd->lmd_mtpt);
204         printf("options:          %s\n", lmd->lmd_opts);
205         printf("flags:            %x\n", lmd->lmd_flags);
206         if (lmd_is_client(lmd)) 
207                 printf("CLIENT\n");
208         else 
209                 printf("SERVER\n");
210
211         return 0;
212 }
213
214 /*****************************************************************************
215  *
216  * This part was cribbed from util-linux/mount/mount.c.  There was no clear
217  * license information, but many other files in the package are identified as
218  * GNU GPL, so it's a pretty safe bet that was their intent.
219  *
220  ****************************************************************************/
221 struct opt_map {
222         const char *opt;        /* option name */
223         int skip;               /* skip in mtab option string */
224         int inv;                /* true if flag value should be inverted */
225         int mask;               /* flag mask value */
226 };
227
228 static const struct opt_map opt_map[] = {
229   { "defaults", 0, 0, 0         },      /* default options */
230   { "rw",       1, 1, MS_RDONLY },      /* read-write */
231   { "ro",       0, 0, MS_RDONLY },      /* read-only */
232   { "exec",     0, 1, MS_NOEXEC },      /* permit execution of binaries */
233   { "noexec",   0, 0, MS_NOEXEC },      /* don't execute binaries */
234   { "suid",     0, 1, MS_NOSUID },      /* honor suid executables */
235   { "nosuid",   0, 0, MS_NOSUID },      /* don't honor suid executables */
236   { "dev",      0, 1, MS_NODEV  },      /* interpret device files  */
237   { "nodev",    0, 0, MS_NODEV  },      /* don't interpret devices */
238   { "async",    0, 1, MS_SYNCHRONOUS},  /* asynchronous I/O */
239   { "auto",     0, 0, 0         },      /* Can be mounted using -a */
240   { "noauto",   0, 0, 0         },      /* Can  only be mounted explicitly */
241   { "nousers",  0, 1, 0         },      /* Forbid ordinary user to mount */
242   { "nouser",   0, 1, 0         },      /* Forbid ordinary user to mount */
243   { "noowner",  0, 1, 0         },      /* Device owner has no special privs */
244   { "_netdev",  0, 0, 0         },      /* Device accessible only via network */
245   { NULL,       0, 0, 0         }
246 };
247 /****************************************************************************/
248
249 static int parse_one_option(const char *check, int *flagp)
250 {
251         const struct opt_map *opt;
252
253         for (opt = &opt_map[0]; opt->opt != NULL; opt++) {
254                 if (strcmp(check, opt->opt) == 0) {
255                         if (opt->inv)
256                                 *flagp &= ~(opt->mask);
257                         else
258                                 *flagp |= opt->mask;
259                         return 1;
260                 }
261         }
262         return 0;
263 }
264
265 int parse_options(char *options, struct lustre_mount_data *lmd, int *flagp)
266 {
267         int val;
268         char *opt, *opteq;
269
270         *flagp = 0;
271         /* parsing ideas here taken from util-linux/mount/nfsmount.c */
272         for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
273                 if ((opteq = strchr(opt, '='))) {
274                         val = atoi(opteq + 1);
275                         *opteq = '\0';
276                         if (0) {
277                                 /* All the network options have gone :)) */
278                         } else {
279                                 fprintf(stderr, "%s: unknown option '%s'\n",
280                                         progname, opt);
281                                 usage(stderr);
282                         }
283                 } else {
284                         if (parse_one_option(opt, flagp))
285                                 continue;
286
287                         fprintf(stderr, "%s: unknown option '%s'\n",
288                                 progname, opt);
289                         usage(stderr);
290                 }
291         }
292         return 0;
293 }
294
295 int
296 build_data(char *source, char *target, char *options, 
297            struct lustre_mount_data *lmd, int *flagp)
298 {
299         char  buf[1024];
300         char *nid = NULL;
301         char *devname = NULL;
302         char *s;
303         int   rc;
304
305         if (lmd_bad_magic(lmd))
306                 return 4;
307
308         if (strlen(source) >= sizeof(buf)) {
309                 fprintf(stderr, "%s: device name too long\n",
310                         progname);
311                 return 1;
312         }
313         strcpy(buf, source);
314
315         if ((s = strchr(buf, ':'))) {
316                 /* Client */
317                 if (verbose)
318                         printf("CLIENT\n");
319                 lmd->lmd_flags |= LMD_FLG_CLIENT;
320
321                 /* <mgsnid>[,<alt mgsnid>]:/fsname[/fsetname[/subdir/]]
322                    nid=mgsnid, devname=fsname */
323                 nid = buf;
324                 *s = '\0';
325                 while (*++s == '/') /*spin*/;
326                 devname = s; /* for clients, devname=fsname */
327
328                 rc = parse_options(options, lmd, flagp);
329                 if (rc)
330                         return rc;
331
332                 if (lmd->lmd_mgsnid.primary != PTL_NID_ANY)
333                         /* In case it was defined as -o mgmtnode= */
334                         //FIXME set_nid_pair(&lmd->lmd_mgsnid, nid);
335                 if (lmd->lmd_mgsnid.primary == PTL_NID_ANY) {
336                         fprintf(stderr, "%s: can't parse nid '%s'\n",
337                                 progname, nid);
338                         return 1;
339                 }
340         } else {
341                 /* Server */
342                 if (verbose)
343                         printf("SERVER\n");
344
345                 devname = source;
346
347                 /* We have to keep the loop= option in the mtab file
348                    in order for umount to free the loop device. The strtok
349                    in parse_options terminates the options list at the first
350                    comma, so we're saving a local copy here. */
351                 strcpy(buf, options);
352                 rc = parse_options(options, lmd, flagp); 
353                 if (rc)
354                         return rc;
355                 strcpy(options, buf);
356
357                 // move into lustre: rc = read_mount_options(source, target, lmd);
358         }
359
360         if (strlen(devname) + 1 > sizeof(lmd->lmd_dev)) {
361                 fprintf(stderr, "%s: device name too long\n", progname);
362                 return(1);
363         }
364         strcpy(lmd->lmd_dev, devname);
365
366         if (strlen(target) + 1 > sizeof(lmd->lmd_mtpt)) {
367                 fprintf(stderr, "%s: mount point too long\n", progname);
368                 return(1);
369         }
370         strcpy(lmd->lmd_mtpt, target);
371         
372         if (verbose)
373                 print_options(lmd);
374         return 0;
375 }
376
377 int main(int argc, char *const argv[])
378 {
379         char *source, *target, *options = "";
380         int i, nargs = 3, opt, rc, flags;
381         struct lustre_mount_data lmd;
382         static struct option long_opt[] = {
383                 {"fake", 0, 0, 'f'},
384                 {"force", 0, 0, 1},
385                 {"help", 0, 0, 'h'},
386                 {"nomtab", 0, 0, 'n'},
387                 {"options", 1, 0, 'o'},
388                 {"verbose", 0, 0, 'v'},
389                 {0, 0, 0, 0}
390         };
391
392         progname = strrchr(argv[0], '/');
393         progname = progname ? progname + 1 : argv[0];
394
395         while ((opt = getopt_long(argc, argv, "fhno:v",
396                                   long_opt, NULL)) != EOF){
397                 switch (opt) {
398                 case 1:
399                         ++force;
400                         printf("force: %d\n", force);
401                         nargs++;
402                         break;
403                 case 'f':
404                         ++fake;
405                         printf("fake: %d\n", fake);
406                         nargs++;
407                         break;
408                 case 'h':
409                         usage(stdout);
410                         break;
411                 case 'n':
412                         ++nomtab;
413                         printf("nomtab: %d\n", nomtab);
414                         nargs++;
415                         break;
416                 case 'o':
417                         options = optarg;
418                         nargs++;
419                         break;
420                 case 'v':
421                         ++verbose;
422                         printf("verbose: %d\n", verbose);
423                         nargs++;
424                         break;
425                 default:
426                         fprintf(stderr, "%s: unknown option '%c'\n",
427                                 progname, opt);
428                         usage(stderr);
429                         break;
430                 }
431         }
432
433         if (optind + 2 > argc) {
434                 fprintf(stderr, "%s: too few arguments\n", progname);
435                 usage(stderr);
436         }
437
438         source = argv[optind];
439         target = argv[optind + 1];
440
441         if (verbose) {
442                 for (i = 0; i < argc; i++)
443                         printf("arg[%d] = %s\n", i, argv[i]);
444                 printf("source = %s, target = %s\n", source, target);
445         }
446
447         if (!force && check_mtab_entry(source, target, "lustre"))
448                 exit(32);
449
450         init_options(&lmd);
451         rc = build_data(source, target, options, &lmd, &flags);
452         if (rc) {
453                 exit(1);
454         }
455
456         rc = access(target, F_OK);
457         if (rc) {
458                 rc = errno;
459                 fprintf(stderr, "%s: %s inaccessible: %s\n", progname, target,
460                         strerror(errno));
461                 return 1;
462         }
463
464         /* FIXME remove */
465         if ((rc = load_modules(&lmd))) {
466                 return rc;
467         }
468
469         if (!fake)
470                 /* flags and target get to lustre_get_sb, but not 
471                    lustre_fill_super.  Lustre ignores the flags, but mount 
472                    does not. */
473                 rc = mount(source, target, "lustre", flags, (void *)&lmd);
474         if (rc) {
475                 fprintf(stderr, "%s: mount(%s, %s) failed: %s\n", source,
476                         target, progname, strerror(errno));
477                 if (errno == ENODEV)
478                         fprintf(stderr, "Are the lustre modules loaded?\n"
479                              "Check /etc/modules.conf and /proc/filesystems\n");
480                 rc = 32;
481         } else if (!nomtab) {
482                 rc = update_mtab_entry(source, target, "lustre", options,0,0,0);
483         }
484
485         return rc;
486 }