- char default_options[] = "";
- char *usource, *source, *ptr;
- char target[PATH_MAX] = {'\0'};
- char real_path[PATH_MAX] = {'\0'};
- char path[256], name[256];
- FILE *f;
- size_t sz;
- char *options, *optcopy, *orig_options = default_options;
- int i, nargs = 3, opt, rc, flags, optlen;
- static struct option long_opt[] = {
- {"fake", 0, 0, 'f'},
- {"force", 0, 0, 1},
- {"help", 0, 0, 'h'},
- {"nomtab", 0, 0, 'n'},
- {"options", 1, 0, 'o'},
- {"verbose", 0, 0, 'v'},
- {0, 0, 0, 0}
- };
-
- progname = strrchr(argv[0], '/');
- progname = progname ? progname + 1 : argv[0];
-
- while ((opt = getopt_long(argc, argv, "fhno:v",
- long_opt, NULL)) != EOF){
- switch (opt) {
- case 1:
- ++force;
- printf("force: %d\n", force);
- nargs++;
- break;
- case 'f':
- ++fake;
- printf("fake: %d\n", fake);
- nargs++;
- break;
- case 'h':
- usage(stdout);
- break;
- case 'n':
- ++nomtab;
- printf("nomtab: %d\n", nomtab);
- nargs++;
- break;
- case 'o':
- orig_options = optarg;
- nargs++;
- break;
- case 'v':
- ++verbose;
- nargs++;
- break;
- default:
- fprintf(stderr, "%s: unknown option '%c'\n",
- progname, opt);
- usage(stderr);
- break;
- }
- }
-
- if (optind + 2 > argc) {
- fprintf(stderr, "%s: too few arguments\n", progname);
- usage(stderr);
- }
-
- usource = argv[optind];
- if (!usource) {
- usage(stderr);
- }
-
- /**
- * Try to get the real path to the device, in case it is a
- * symbolic link for instance
- */
- if (realpath(usource, real_path) != NULL) {
- usource = real_path;
-
- ptr = strrchr(real_path, '/');
- if (ptr && strncmp(ptr, "/dm-", 4) == 0 && isdigit(*(ptr + 4))) {
- snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptr+1);
- if ((f = fopen(path, "r"))) {
- /* read "<name>\n" from sysfs */
- if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
- name[sz - 1] = '\0';
- snprintf(real_path, sizeof(real_path), "/dev/mapper/%s", name);
- }
- fclose(f);
- }
- }
- }
-
- source = convert_hostnames(usource);
- if (!source) {
- usage(stderr);
- }
-
- if (realpath(argv[optind + 1], target) == NULL) {
- rc = errno;
- fprintf(stderr, "warning: %s: cannot resolve: %s\n",
- argv[optind + 1], strerror(errno));
- return rc;
- }
-
- if (verbose) {
- for (i = 0; i < argc; i++)
- printf("arg[%d] = %s\n", i, argv[i]);
- printf("source = %s (%s), target = %s\n", usource, source,
- target);
- printf("options = %s\n", orig_options);
- }
-
- options = malloc(strlen(orig_options) + 1);
- if (options == NULL) {
- fprintf(stderr, "can't allocate memory for options\n");
- return -1;
- }
- strcpy(options, orig_options);
- rc = parse_options(options, &flags);
- if (rc) {
- fprintf(stderr, "%s: can't parse options: %s\n",
- progname, options);
- return(EINVAL);
- }
-
- if (!force) {
- rc = check_mtab_entry(usource, source, target, "lustre");
- if (rc && !(flags & MS_REMOUNT)) {
- fprintf(stderr, "%s: according to %s %s is "
- "already mounted on %s\n",
- progname, MOUNTED, usource, target);
- return(EEXIST);
- }
- if (!rc && (flags & MS_REMOUNT)) {
- fprintf(stderr, "%s: according to %s %s is "
- "not already mounted on %s\n",
- progname, MOUNTED, usource, target);
- return(ENOENT);
- }
- }
- if (flags & MS_REMOUNT)
- nomtab++;
-
- rc = access(target, F_OK);
- if (rc) {
- rc = errno;
- fprintf(stderr, "%s: %s inaccessible: %s\n", progname, target,
- strerror(errno));
- return rc;
- }
-
- /* In Linux 2.4, the target device doesn't get passed to any of our
- functions. So we'll stick it on the end of the options. */
- optlen = strlen(options) + strlen(",device=") + strlen(source) + 1;
- optcopy = malloc(optlen);
- if (optcopy == NULL) {
- fprintf(stderr, "can't allocate memory to optcopy\n");
- return -1;
- }
- strcpy(optcopy, options);
- if (*optcopy)
- strcat(optcopy, ",");
- strcat(optcopy, "device=");
- strcat(optcopy, source);
-
- if (verbose)
- printf("mounting device %s at %s, flags=%#x options=%s\n",
- source, target, flags, optcopy);
-
- if (!strstr(usource, ":/") && set_blockdev_tunables(source, 1)) {
- if (verbose)
- fprintf(stderr, "%s: unable to set tunables for %s"
- " (may cause reduced IO performance)\n",
- argv[0], source);
- }
-
- register_service_tags(usource, source, target);
-
- if (!fake) {
- /* flags and target get to lustre_get_sb, but not
- lustre_fill_super. Lustre ignores the flags, but mount
- does not. */
- for (i = 0, rc = -EAGAIN; i <= retry && rc != 0; i++) {
- rc = mount(source, target, "lustre", flags,
- (void *)optcopy);
- if (rc) {
- if (verbose) {
- fprintf(stderr, "%s: mount %s at %s "
- "failed: %s retries left: "
- "%d\n", basename(progname),
- usource, target,
- strerror(errno), retry-i);
- }
-
- if (retry) {
- sleep(1 << max((i/2), 5));
- }
- else {
- rc = errno;
- }
- }
- }
- }
-
- if (rc) {
- char *cli;
-
- rc = errno;
-
- cli = strrchr(usource, ':');
- if (cli && (strlen(cli) > 2))
- cli += 2;
- else
- cli = NULL;
-
- fprintf(stderr, "%s: mount %s at %s failed: %s\n", progname,
- usource, target, strerror(errno));
- if (errno == ENODEV)
- fprintf(stderr, "Are the lustre modules loaded?\n"
- "Check /etc/modprobe.conf and "
- "/proc/filesystems\n");
- if (errno == ENOTBLK)
- fprintf(stderr, "Do you need -o loop?\n");
- if (errno == ENOMEDIUM)
- fprintf(stderr,
- "This filesystem needs at least 1 OST\n");
- if (errno == ENOENT) {
- fprintf(stderr, "Is the MGS specification correct?\n");
- fprintf(stderr, "Is the filesystem name correct?\n");
- fprintf(stderr, "If upgrading, is the copied client log"
- " valid? (see upgrade docs)\n");
- }
- if (errno == EALREADY)
- fprintf(stderr, "The target service is already running."
- " (%s)\n", usource);
- if (errno == ENXIO)
- fprintf(stderr, "The target service failed to start "
- "(bad config log?) (%s). "
- "See /var/log/messages.\n", usource);
- if (errno == EIO)
- fprintf(stderr, "Is the MGS running?\n");
- if (errno == EADDRINUSE)
- fprintf(stderr, "The target service's index is already "
- "in use. (%s)\n", usource);
- if (errno == EINVAL) {
- fprintf(stderr, "This may have multiple causes.\n");
- if (cli)
- fprintf(stderr, "Is '%s' the correct filesystem"
- " name?\n", cli);
- fprintf(stderr, "Are the mount options correct?\n");
- fprintf(stderr, "Check the syslog for more info.\n");
- }
-
- /* May as well try to clean up loop devs */
- if (strncmp(usource, "/dev/loop", 9) == 0) {
- char cmd[256];
- int ret;
- sprintf(cmd, "/sbin/losetup -d %s", usource);
- if ((ret = system(cmd)) < 0)
- rc = errno;
- else if (ret > 0)
- rc = WEXITSTATUS(ret);
- }
-
- } else if (!nomtab) {
- rc = update_mtab_entry(usource, target, "lustre", orig_options,
- 0,0,0);
- }
-
- free(optcopy);
- free(source);
- return rc;
+ struct mount_opts mop;
+ char *options;
+ int i, flags;
+ int rc;
+ bool client;
+ size_t maxopt_len;
+ size_t g_pagesize;
+
+ progname = strrchr(argv[0], '/');
+ progname = progname ? progname + 1 : argv[0];
+
+ set_defaults(&mop);
+
+ g_pagesize = sysconf(_SC_PAGESIZE);
+ if (g_pagesize == -1) {
+ rc = errno;
+ printf("error: %d failed to get page size.\n", rc);
+ return rc;
+ }
+ maxopt_len = MIN(g_pagesize, 64 * 1024);
+
+ rc = parse_opts(argc, argv, &mop);
+ if (rc || version)
+ return rc;
+
+ if (verbose) {
+ for (i = 0; i < argc; i++)
+ printf("arg[%d] = %s\n", i, argv[i]);
+ printf("source = %s (%s), target = %s\n", mop.mo_usource,
+ mop.mo_source, mop.mo_target);
+ printf("options = %s\n", mop.mo_orig_options);
+ }
+
+ options = malloc(maxopt_len);
+ if (!options) {
+ fprintf(stderr, "can't allocate memory for options\n");
+ rc = ENOMEM;
+ goto out_mo_source;
+ }
+
+ if (strlen(mop.mo_orig_options) >= maxopt_len) {
+ fprintf(stderr, "error: mount options too long\n");
+ rc = E2BIG;
+ goto out_options;
+ }
+
+ strcpy(options, mop.mo_orig_options);
+ rc = parse_options(&mop, options, &flags, maxopt_len);
+ if (rc) {
+ fprintf(stderr, "%s: can't parse options: %s\n",
+ progname, options);
+ goto out_options;
+ }
+
+ if (!mop.mo_force) {
+ rc = check_mtab_entry(mop.mo_usource, mop.mo_source,
+ mop.mo_target, "lustre");
+ if (rc && !(flags & MS_REMOUNT)) {
+ fprintf(stderr,
+ "%s: according to %s %s is already mounted on %s\n",
+ progname, MOUNTED, mop.mo_usource,
+ mop.mo_target);
+ rc = EEXIST;
+ goto out_options;
+ }
+ if (!rc && (flags & MS_REMOUNT)) {
+ fprintf(stderr,
+ "%s: according to %s %s is not already mounted on %s\n",
+ progname, MOUNTED, mop.mo_usource,
+ mop.mo_target);
+ rc = ENOENT;
+ goto out_options;
+ }
+ }
+ if (flags & MS_REMOUNT)
+ mop.mo_nomtab++;
+
+ rc = access(mop.mo_target, F_OK);
+ if (rc) {
+ rc = errno;
+ fprintf(stderr, "%s: %s inaccessible: %s\n", progname,
+ mop.mo_target, strerror(errno));
+ goto out_options;
+ }
+
+ client = (strstr(mop.mo_usource, ":/") != NULL);
+ if (!client) {
+#ifdef HAVE_SERVER_SUPPORT
+ rc = osd_init();
+ if (rc)
+ goto out_options;
+
+ rc = parse_ldd(mop.mo_source, &mop, options, maxopt_len);
+ if (rc)
+ goto out_osd;
+#else
+ rc = EINVAL;
+ fprintf(stderr, "%s: cannot mount %s: no server support\n",
+ progname, mop.mo_usource);
+ goto out_options;
+#endif
+ }
+
+ /*
+ * In Linux 2.4, the target device doesn't get passed to any of our
+ * functions. So we'll stick it on the end of the options.
+ */
+ rc = append_option(options, maxopt_len, "device=", mop.mo_source);
+ if (rc != 0)
+ goto out_osd;
+
+ if (verbose)
+ printf("mounting device %s at %s, flags=%#x options=%s\n",
+ mop.mo_source, mop.mo_target, flags, options);
+
+#ifdef HAVE_SERVER_SUPPORT
+ if (!client && osd_tune_lustre(mop.mo_source, &mop)) {
+ if (verbose)
+ fprintf(stderr,
+ "%s: unable to set tunables for %s (may cause reduced IO performance)\n",
+ argv[0], mop.mo_source);
+ }
+#endif
+#ifdef HAVE_GSS
+ if (mop.mo_skpath[0] != '\0') {
+ /* Treat shared key failures as fatal */
+ rc = load_shared_keys(&mop);
+ if (rc) {
+ fprintf(stderr, "%s: Error loading shared keys: %s\n",
+ progname, strerror(rc));
+ goto out_osd;
+ }
+ }
+#endif /* HAVE_GSS */
+
+ if (!mop.mo_fake) {
+ char *fstype;
+
+ /* Prefer filesystem type given on mount command line
+ * so it appears correctly in the /proc/mounts output.
+ */
+ if (strstr(argv[0], "mount.lustre_tgt"))
+ fstype = "lustre_tgt";
+ else
+ fstype = "lustre";
+ /*
+ * flags and target get to lustre_get_sb(), but not
+ * lustre_fill_super(). Lustre ignores the flags, but mount
+ * does not.
+ */
+ for (i = 0, rc = -EAGAIN; i <= mop.mo_retry && rc != 0; i++) {
+ rc = mount(mop.mo_source, mop.mo_target, fstype,
+ flags, (void *)options);
+ if (rc != 0) {
+ if (verbose) {
+ fprintf(stderr,
+ "%s: mount -t %s %s at %s failed: %s retries left: %d\n",
+ basename(progname), fstype,
+ mop.mo_usource, mop.mo_target,
+ strerror(errno),
+ mop.mo_retry - i);
+ }
+
+ /* Pre-2.13 Lustre without 'lustre_tgt' type?
+ * Try with 'lustre' instead. Eventually this
+ * can be removed (e.g. 2.18 or whenever).
+ */
+ if (errno == ENODEV &&
+ strcmp(fstype, "lustre_tgt") == 0) {
+ fstype = "lustre";
+ i--;
+ continue;
+ }
+
+ if (mop.mo_retry) {
+ int limit = i / 2 > 5 ? i / 2 : 5;
+
+ sleep(1 << limit);
+ } else {
+ rc = errno;
+ }
+#ifdef HAVE_SERVER_SUPPORT
+ } else {
+ if (!client)
+ label_lustre(&mop);
+#endif
+ }
+ }
+ }
+
+ if (rc) {
+ char *cli;
+
+ rc = errno;
+
+ cli = strrchr(mop.mo_usource, ':');
+ if (cli && (strlen(cli) > 2))
+ cli += 2;
+ else
+ cli = NULL;
+
+ fprintf(stderr, "%s: mount %s at %s failed: %s\n", progname,
+ mop.mo_usource, mop.mo_target, strerror(errno));
+ if (errno == EBUSY)
+ fprintf(stderr,
+ "Is the backend filesystem mounted?\n Check /etc/mtab and /proc/mounts\n");
+ if (errno == ENODEV)
+ fprintf(stderr,
+ "Are the lustre modules loaded?\n Check /etc/modprobe.conf and /proc/filesystems\n");
+ if (errno == ENOTBLK)
+ fprintf(stderr, "Do you need -o loop?\n");
+ if (errno == ENOMEDIUM)
+ fprintf(stderr,
+ "This filesystem needs at least 1 OST\n");
+ if (errno == ENOENT) {
+ fprintf(stderr, "Is the MGS specification correct?\n");
+ fprintf(stderr, "Is the filesystem name correct?\n");
+ fprintf(stderr,
+ "If upgrading, is the copied client log valid? (see upgrade docs)\n");
+ }
+ if (errno == EALREADY)
+ fprintf(stderr,
+ "The target service is already running. (%s)\n",
+ mop.mo_usource);
+ if (errno == ENXIO)
+ fprintf(stderr,
+ "The target service failed to start (bad config log?) (%s). See /var/log/messages.\n",
+ mop.mo_usource);
+ if (errno == EIO)
+ fprintf(stderr, "Is the MGS running?\n");
+ if (errno == EADDRINUSE)
+ fprintf(stderr,
+ "The target service's index is already in use. (%s)\n",
+ mop.mo_usource);
+ if (errno == EINVAL) {
+ fprintf(stderr, "This may have multiple causes.\n");
+ if (cli)
+ fprintf(stderr,
+ "Is '%s' the correct filesystem name?\n",
+ cli);
+ fprintf(stderr, "Are the mount options correct?\n");
+ fprintf(stderr, "Check the syslog for more info.\n");
+ }
+
+ /* May as well try to clean up loop devs */
+ if (strncmp(mop.mo_usource, "/dev/loop", 9) == 0) {
+ char cmd[256];
+ int ret;
+
+ sprintf(cmd, "/sbin/losetup -d %s", mop.mo_usource);
+ if ((ret = system(cmd)) < 0)
+ rc = errno;
+ else if (ret > 0)
+ rc = WEXITSTATUS(ret);
+ }
+
+ } else {
+ /*
+ * Deal with utab just for client. Note that we ignore
+ * the return value here since it is not worth to fail
+ * mount by prevent some rare cases
+ */
+ if (strstr(mop.mo_usource, ":/") != NULL)
+ update_utab_entry(&mop);
+ if (!mop.mo_nomtab) {
+ rc = update_mtab_entry(mop.mo_usource, mop.mo_target,
+ "lustre", mop.mo_orig_options,
+ 0, 0, 0);
+ }
+ }
+
+out_osd:
+#ifdef HAVE_SERVER_SUPPORT
+ if (!client)
+ osd_fini();
+#endif
+out_options:
+ free(options);
+
+out_mo_source:
+ /* mo_usource should be freed, but we can rely on the kernel */
+ free(mop.mo_source);
+ return rc;