Whamcloud - gitweb
LU-5070 utils: mkfs.lustre code cleanup
[fs/lustre-release.git] / lustre / utils / mount_utils.c
index 8054b07..8287d34 100644 (file)
@@ -26,7 +26,8 @@
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
- * Copyright (c) 2012, 2013, Intel Corporation.
+ *
+ * Copyright (c) 2012, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #  include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#include "mount_utils.h"
+#include <inttypes.h>
+#include <limits.h>
+#include <mntent.h>
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 #include <config.h>
 #include <lustre_disk.h>
 #include <lustre_ver.h>
+#include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <linux/loop.h>
 #include <dlfcn.h>
 
+#include "mount_utils.h"
+
 extern char *progname;
 extern int verbose;
 
@@ -144,6 +151,43 @@ int get_param(char *buf, char *key, char **val)
        return ENOENT;
 }
 
+int append_param(char *buf, char *key, char *val, char sep)
+{
+       int key_len, i, offset, old_val_len;
+       char *ptr = NULL, str[1024];
+
+       if (key)
+               ptr = strstr(buf, key);
+
+       /* key doesn't exist yet, so just add it */
+       if (ptr == NULL)
+               return add_param(buf, key, val);
+
+       key_len = strlen(key);
+
+       /* Copy previous values to str */
+       for (i = 0; i < sizeof(str); ++i) {
+               if ((ptr[i+key_len] == ' ') || (ptr[i+key_len] == '\0'))
+                       break;
+               str[i] = ptr[i+key_len];
+       }
+       if (i == sizeof(str))
+               return E2BIG;
+       old_val_len = i;
+
+       offset = old_val_len+key_len;
+
+       /* Move rest of buf to overwrite previous key and value */
+       for (i = 0; ptr[i+offset] != '\0'; ++i)
+               ptr[i] = ptr[i+offset];
+
+       ptr[i] = '\0';
+
+       snprintf(str+old_val_len, sizeof(str)-old_val_len, "%c%s", sep, val);
+
+       return add_param(buf, key, str);
+}
+
 char *strscat(char *dst, char *src, int buflen)
 {
        dst[buflen - 1] = 0;
@@ -198,6 +242,52 @@ static int mtab_is_proc(const char *mtab)
        return 1;
 }
 
+#ifdef HAVE_LIBMOUNT
+
+# include <libmount/libmount.h>
+
+/*
+ * The libmount is part of util-linux since 2.18.
+ * We use it to update utab to avoid umount would
+ * blocked in some rare case.
+ */
+int update_utab_entry(struct mount_opts *mop)
+{
+       struct libmnt_fs *fs = mnt_new_fs();
+       struct libmnt_update *upd;
+       int rc;
+
+       mnt_fs_set_source(fs, mop->mo_source);
+       mnt_fs_set_target(fs, mop->mo_target);
+       mnt_fs_set_fstype(fs, "lustre");
+       mnt_fs_set_attributes(fs, "lustre");
+
+       upd = mnt_new_update();
+       if (!upd)
+               return -ENOMEM;
+
+       rc = mnt_update_set_fs(upd, mop->mo_nomtab ? MS_REMOUNT : 0, NULL, fs);
+       if (rc == 1) /* update is unnecessary */
+               rc = 0;
+       if (rc) {
+               fprintf(stderr,
+                       "error: failed to save utab entry: rc = %d\n", rc);
+       } else {
+               rc = mnt_update_table(upd, NULL);
+       }
+
+       mnt_free_update(upd);
+       mnt_free_fs(fs);
+
+       return rc;
+}
+#else
+int update_utab_entry(struct mount_opts *mop)
+{
+       return 0;
+}
+#endif /* HAVE_LIBMOUNT */
+
 int update_mtab_entry(char *spec, char *mtpt, char *type, char *opts,
                int flags, int freq, int pass)
 {
@@ -257,8 +347,7 @@ static int in_mntlist(char *opt, char *mntlist)
  * present in mountopts.  The justwarn boolean toggles between error and
  * warning message.  Return an error count.
  */
-int check_mountfsoptions(char *mountopts, char *wanted_mountopts,
-                        int justwarn)
+int check_mountfsoptions(char *mountopts, char *wanted_mountopts)
 {
        char *ml, *mlp, *item, *ctx = NULL;
        int errors = 0;
@@ -270,9 +359,8 @@ int check_mountfsoptions(char *mountopts, char *wanted_mountopts,
        mlp = ml;
        while ((item = strtok_r(mlp, ",", &ctx))) {
                if (!in_mntlist(item, mountopts)) {
-                       fprintf(stderr, "%s: %s mount option `%s' is missing\n",
-                               progname, justwarn ? "Warning: default"
-                               : "Error: mandatory", item);
+                       fprintf(stderr, "%s: Error: mandatory mount option"
+                               " '%s' is missing\n", progname, item);
                        errors++;
                }
                mlp = NULL;
@@ -326,7 +414,7 @@ int loop_setup(struct mkfs_opts *mop)
                char cmd[PATH_MAX];
                int cmdsz = sizeof(cmd);
 
-#ifdef LOOP_CTL_GET_FREE
+#ifdef HAVE_LOOP_CTL_GET_FREE
                ret = open("/dev/loop-control", O_RDWR);
                if (ret < 0) {
                        fprintf(stderr, "%s: can't access loop control\n", progname);
@@ -334,6 +422,7 @@ int loop_setup(struct mkfs_opts *mop)
                }
                /* find or allocate a free loop device to use */
                i = ioctl(ret, LOOP_CTL_GET_FREE);
+               close(ret);
                if (i < 0) {
                        fprintf(stderr, "%s: access loop control error\n", progname);
                        return EACCES;
@@ -506,6 +595,10 @@ struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type)
                free(ops);
                return NULL;
        }
+
+       /* optional methods */
+       DLSYM(name, ops, fix_mountopts);
+
        return ops;
 }
 
@@ -532,7 +625,7 @@ int backfs_mount_type_okay(enum ldd_mount_type mount_type)
        }
        if (backfs_ops[mount_type] == NULL) {
                fatal();
-               fprintf(stderr, "unhandled fs type %d '%s'\n",
+               fprintf(stderr, "unhandled/unloaded fs type %d '%s'\n",
                        mount_type, mt_str(mount_type));
                return 0;
        }
@@ -547,7 +640,6 @@ int osd_write_ldd(struct mkfs_opts *mop)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->write_ldd(mop);
-
        else
                ret = EINVAL;
 
@@ -561,7 +653,6 @@ int osd_read_ldd(char *dev, struct lustre_disk_data *ldd)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->read_ldd(dev, ldd);
-
        else
                ret = EINVAL;
 
@@ -595,7 +686,6 @@ int osd_make_lustre(struct mkfs_opts *mop)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->make_lustre(mop);
-
        else
                ret = EINVAL;
 
@@ -603,23 +693,34 @@ int osd_make_lustre(struct mkfs_opts *mop)
 }
 
 int osd_prepare_lustre(struct mkfs_opts *mop,
-               char *default_mountopts, int default_len,
-               char *always_mountopts, int always_len)
+                      char *wanted_mountopts, size_t len)
 {
        struct lustre_disk_data *ldd = &mop->mo_ldd;
        int ret;
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->prepare_lustre(mop,
-                       default_mountopts, default_len,
-                       always_mountopts, always_len);
-
+                                                       wanted_mountopts, len);
        else
                ret = EINVAL;
 
        return ret;
 }
 
+int osd_fix_mountopts(struct mkfs_opts *mop, char *mountopts, size_t len)
+{
+       struct lustre_disk_data *ldd = &mop->mo_ldd;
+
+       if (!backfs_mount_type_okay(ldd->ldd_mount_type))
+               return EINVAL;
+
+       if (backfs_ops[ldd->ldd_mount_type]->fix_mountopts == NULL)
+               return 0;
+
+       return backfs_ops[ldd->ldd_mount_type]->fix_mountopts(mop, mountopts,
+                                                             len);
+}
+
 int osd_tune_lustre(char *dev, struct mount_opts *mop)
 {
        struct lustre_disk_data *ldd = &mop->mo_ldd;
@@ -627,7 +728,6 @@ int osd_tune_lustre(char *dev, struct mount_opts *mop)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->tune_lustre(dev, mop);
-
        else
                ret = EINVAL;
 
@@ -641,7 +741,6 @@ int osd_label_lustre(struct mount_opts *mop)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->label_lustre(mop);
-
        else
                ret = EINVAL;
 
@@ -656,7 +755,6 @@ int osd_enable_quota(struct mkfs_opts *mop)
 
        if (backfs_mount_type_okay(ldd->ldd_mount_type))
                ret = backfs_ops[ldd->ldd_mount_type]->enable_quota(mop);
-
        else
                ret = EINVAL;
 
@@ -665,14 +763,19 @@ int osd_enable_quota(struct mkfs_opts *mop)
 
 int osd_init(void)
 {
-       int i, ret = 0;
+       int i, rc, ret = EINVAL;
 
        for (i = 0; i < LDD_MT_LAST; ++i) {
+               rc = 0;
                backfs_ops[i] = load_backfs_module(i);
                if (backfs_ops[i] != NULL)
-                       ret = backfs_ops[i]->init();
-               if (ret)
-                       break;
+                       rc = backfs_ops[i]->init();
+               if (rc != 0) {
+                       backfs_ops[i]->fini();
+                       unload_backfs_module(backfs_ops[i]);
+                       backfs_ops[i] = NULL;
+               } else
+                       ret = 0;
        }
 
        return ret;
@@ -721,7 +824,7 @@ __u64 get_device_size(char* device)
                return 0;
        }
 
-       vprint("device size = "LPU64"MB\n", size >> 20);
+       vprint("device size = %juMB\n", (uintmax_t)(size >> 20));
        /* return value in KB */
        return size >> 10;
 }
@@ -738,8 +841,9 @@ int file_create(char *path, __u64 size)
         */
        size_max = (off_t)1 << (_FILE_OFFSET_BITS - 1 - 10);
        if (size >= size_max) {
-               fprintf(stderr, "%s: "LPU64" KB: Backing store size must be "
-                       "smaller than "LPU64" KB\n", progname, size, size_max);
+               fprintf(stderr, "%s: %ju KB: Backing store size must be "
+                       "smaller than %ju KB\n", progname, (uintmax_t) size,
+                       (uintmax_t)size_max);
                return EFBIG;
        }