Whamcloud - gitweb
LU-7728 osp: soft lockup in osp_precreate_reserve()
[fs/lustre-release.git] / lustre / utils / mount_utils.c
index 7383f21..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>
@@ -51,6 +54,8 @@
 #include <linux/loop.h>
 #include <dlfcn.h>
 
+#include "mount_utils.h"
+
 extern char *progname;
 extern int verbose;
 
@@ -237,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)
 {
@@ -296,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;
@@ -309,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;
@@ -365,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);
@@ -373,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;
@@ -489,7 +539,7 @@ struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type)
 
        /* This deals with duplicate ldd_mount_types resolving to same OSD layer
         * plugin (e.g. ext3/ldiskfs/ldiskfs2 all being ldiskfs) */
-       strlcpy(fsname, mt_type(mount_type), sizeof(fsname));
+       strncpy(fsname, mt_type(mount_type), sizeof(fsname));
        name = fsname + sizeof("osd-") - 1;
 
        /* change osd- to osd_ */
@@ -545,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;
 }
 
@@ -571,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;
        }
@@ -586,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;
 
@@ -600,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;
 
@@ -634,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;
 
@@ -642,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;
@@ -666,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;
 
@@ -680,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;
 
@@ -695,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;
 
@@ -704,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;
@@ -760,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;
 }
@@ -777,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;
        }