Whamcloud - gitweb
LU-3763 utils: set multipath devices recursively
[fs/lustre-release.git] / lustre / utils / mount_utils_ldiskfs.c
index fe365e8..4c75200 100644 (file)
@@ -27,7 +27,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, Whamcloud, Inc.
+ * Copyright (c) 2012, 2013, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #include <lnet/lnetctl.h>
 #include <lustre_ver.h>
 
+#ifdef HAVE_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #define MAX_HW_SECTORS_KB_PATH "queue/max_hw_sectors_kb"
 #define MAX_SECTORS_KB_PATH    "queue/max_sectors_kb"
+#define SCHEDULER_PATH         "queue/scheduler"
 #define STRIPE_CACHE_SIZE      "md/stripe_cache_size"
 
+#define DEFAULT_SCHEDULER      "deadline"
+
 extern char *progname;
 
 #define L_BLOCK_SIZE 4096
@@ -91,6 +98,29 @@ extern char *progname;
 #define DUMMY_FILE_NAME_LEN             25
 #define EXT3_DIRENT_SIZE                DUMMY_FILE_NAME_LEN
 
+/*
+ * Concatenate context of the temporary mount point iff selinux is enabled
+ */
+#ifdef HAVE_SELINUX
+void append_context_for_mount(char *mntpt, struct mkfs_opts *mop)
+{
+       security_context_t fcontext;
+
+       if (getfilecon(mntpt, &fcontext) < 0) {
+               /* Continuing with default behaviour */
+               fprintf(stderr, "%s: Get file context failed : %s\n",
+                       progname, strerror(errno));
+               return;
+       }
+
+       if (fcontext != NULL) {
+               strcat(mop->mo_ldd.ldd_mount_opts, ",context=");
+               strcat(mop->mo_ldd.ldd_mount_opts, fcontext);
+               freecon(fcontext);
+       }
+}
+#endif
+
 /* Write the server config files */
 int ldiskfs_write_ldd(struct mkfs_opts *mop)
 {
@@ -108,6 +138,14 @@ int ldiskfs_write_ldd(struct mkfs_opts *mop)
                return errno;
        }
 
+       /*
+        * Append file context to mount options if SE Linux is enabled
+        */
+       #ifdef HAVE_SELINUX
+       if (is_selinux_enabled() > 0)
+               append_context_for_mount(mntpt, mop);
+       #endif
+
        dev = mop->mo_device;
        if (mop->mo_flags & MO_IS_LOOP)
                dev = mop->mo_loopdev;
@@ -287,7 +325,7 @@ static int file_in_dev(char *file_name, char *dev_name)
                pclose(fp);
                return 1;
        }
-       i = fread(debugfs_cmd, 1, sizeof(debugfs_cmd), fp);
+       i = fread(debugfs_cmd, 1, sizeof(debugfs_cmd) - 1, fp);
        if (i) {
                debugfs_cmd[i] = 0;
                fprintf(stderr, "%s", debugfs_cmd);
@@ -346,7 +384,8 @@ static int is_e2fsprogs_feature_supp(const char *feature)
                        fprintf(stderr, "%s: %s\n", progname, strerror(errno));
                        return 0;
                }
-               ret = fread(supp_features, 1, sizeof(supp_features), fp);
+               ret = fread(supp_features, 1, sizeof(supp_features) - 1, fp);
+               supp_features[ret] = '\0';
                fclose(fp);
        }
        if (ret > 0 && strstr(supp_features,
@@ -786,7 +825,7 @@ int ldiskfs_prepare_lustre(struct mkfs_opts *mop,
        return 0;
 }
 
-int read_file(char *path, char *buf, int size)
+int read_file(const char *path, char *buf, int size)
 {
        FILE *fd;
 
@@ -804,7 +843,7 @@ int read_file(char *path, char *buf, int size)
        return 0;
 }
 
-int write_file(char *path, char *buf)
+int write_file(const char *path, const char *buf)
 {
        FILE *fd;
 
@@ -817,10 +856,55 @@ int write_file(char *path, char *buf)
        return 0;
 }
 
+int set_blockdev_scheduler(const char *path, const char *scheduler)
+{
+       char buf[PATH_MAX], *c;
+       int rc;
+
+       /* Before setting the scheduler, we need to check to see if it's
+        * already set to "noop". If it is, we don't want to override
+        * that setting. If it's set to anything other than "noop", set
+        * the scheduler to what has been passed in. */
+
+       rc = read_file(path, buf, sizeof(buf));
+       if (rc) {
+               if (verbose)
+                       fprintf(stderr, "%s: cannot open '%s': %s\n",
+                               progname, path, strerror(errno));
+               return rc;
+       }
+
+       /* The expected format of buf: noop anticipatory deadline [cfq] */
+       c = strchr(buf, '[');
+
+       /* If c is NULL, the format is not what we expect. Play it safe
+        * and error out. */
+       if (c == NULL) {
+               if (verbose)
+                       fprintf(stderr, "%s: cannot parse scheduler "
+                                       "options for '%s'\n", progname, path);
+               return -EINVAL;
+       }
+
+       if (strncmp(c+1, "noop", 4) == 0)
+               return 0;
+
+       rc = write_file(path, scheduler);
+       if (rc) {
+               if (verbose)
+                       fprintf(stderr, "%s: cannot set scheduler on "
+                                       "'%s': %s\n", progname, path,
+                                       strerror(errno));
+               return rc;
+       }
+
+       return rc;
+}
+
 /* This is to tune the kernel for good SCSI performance.
  * For that we set the value of /sys/block/{dev}/queue/max_sectors_kb
  * to the value of /sys/block/{dev}/queue/max_hw_sectors_kb */
-int set_blockdev_tunables(char *source, struct mount_opts *mop, int fan_out)
+int set_blockdev_tunables(char *source, struct mount_opts *mop)
 {
        glob_t glob_info = { 0 };
        struct stat stat_buf;
@@ -831,6 +915,7 @@ int set_blockdev_tunables(char *source, struct mount_opts *mop, int fan_out)
        char real_path[PATH_MAX] = {'\0'};
        int i, rc = 0;
        int major, minor;
+       char *slave = NULL;
 
        if (!source)
                return -EINVAL;
@@ -899,7 +984,8 @@ int set_blockdev_tunables(char *source, struct mount_opts *mop, int fan_out)
 
                chk_major = strtok_r(buf, ":", &savept);
                chk_minor = savept;
-               if (major == atoi(chk_major) &&minor == atoi(chk_minor))
+               if (chk_major != NULL && major == atoi(chk_major) &&
+                   chk_minor != NULL && minor == atoi(chk_minor))
                        break;
        }
 
@@ -969,45 +1055,48 @@ set_params:
                }
        }
 
-       if (fan_out) {
-               char *slave = NULL;
-               glob_info.gl_pathc = 0;
-               glob_info.gl_offs = 0;
-               /* if device is multipath device, tune its slave devices */
-               snprintf(real_path, sizeof(real_path), "%s/slaves/*", path);
-               rc = glob(real_path, GLOB_NOSORT, NULL, &glob_info);
-
-               for (i = 0; rc == 0 && i < glob_info.gl_pathc; i++){
-                       slave = basename(glob_info.gl_pathv[i]);
-                       snprintf(real_path, sizeof(real_path), "/dev/%s", slave);
-                       rc = set_blockdev_tunables(real_path, mop, 0);
-               }
+       /* Purposely ignore errors reported from set_blockdev_scheduler.
+        * The worst that will happen is a block device with an "incorrect"
+        * scheduler. */
+       snprintf(real_path, sizeof(real_path), "%s/%s", path, SCHEDULER_PATH);
+       set_blockdev_scheduler(real_path, DEFAULT_SCHEDULER);
+
+       /* if device is multipath device, tune its slave devices */
+       glob_info.gl_pathc = 0;
+       glob_info.gl_offs = 0;
+       snprintf(real_path, sizeof(real_path), "%s/slaves/*", path);
+       rc = glob(real_path, GLOB_NOSORT, NULL, &glob_info);
+
+       for (i = 0; rc == 0 && i < glob_info.gl_pathc; i++) {
+               slave = basename(glob_info.gl_pathv[i]);
+               snprintf(real_path, sizeof(real_path), "/dev/%s", slave);
+               rc = set_blockdev_tunables(real_path, mop);
+       }
 
-               if (rc == GLOB_NOMATCH) {
-                       /* no slave device is not an error */
-                       rc = 0;
-               } else if (rc && verbose) {
-                       if (slave == NULL) {
-                               fprintf(stderr, "warning: %s, failed to read"
-                                       " entries under %s/slaves\n",
-                                       strerror(errno), path);
-                       } else {
-                               fprintf(stderr, "unable to set tunables for"
-                                       " slave device %s (slave would be"
-                                       " unable to handle IO request from"
-                                       " master %s)\n",
-                                       real_path, source);
-                       }
+       if (rc == GLOB_NOMATCH) {
+               /* no slave device is not an error */
+               rc = 0;
+       } else if (rc && verbose) {
+               if (slave == NULL) {
+                       fprintf(stderr, "warning: %s, failed to read"
+                               " entries under %s/slaves\n",
+                               strerror(errno), path);
+               } else {
+                       fprintf(stderr, "unable to set tunables for"
+                               " slave device %s (slave would be"
+                               " unable to handle IO request from"
+                               " master %s)\n",
+                               real_path, source);
                }
-               globfree(&glob_info);
        }
+       globfree(&glob_info);
 
        return rc;
 }
 
 int ldiskfs_tune_lustre(char *dev, struct mount_opts *mop)
 {
-       return set_blockdev_tunables(dev, mop, 1);
+       return set_blockdev_tunables(dev, mop);
 }
 
 int ldiskfs_label_lustre(struct mount_opts *mop)
@@ -1015,8 +1104,9 @@ int ldiskfs_label_lustre(struct mount_opts *mop)
        char label_cmd[PATH_MAX];
        int rc;
 
-       snprintf(label_cmd, sizeof(label_cmd), E2LABEL" %s %s",
-                mop->mo_source, mop->mo_ldd.ldd_svname);
+       snprintf(label_cmd, sizeof(label_cmd),
+                TUNE2FS" -f -L '%s' '%s' >/dev/null 2>&1",
+                mop->mo_ldd.ldd_svname, mop->mo_source);
        rc = run_command(label_cmd, sizeof(label_cmd));
 
        return rc;
@@ -1104,6 +1194,7 @@ static int is_feature_enabled(const char *feature, const char *devpath)
        char cmd[PATH_MAX];
        FILE *fp;
        char enabled_features[4096] = "";
+       int ret = 1;
 
        snprintf(cmd, sizeof(cmd), "%s -R features %s 2>&1",
                 DEBUGFS, devpath);
@@ -1116,7 +1207,8 @@ static int is_feature_enabled(const char *feature, const char *devpath)
                return 0;
        }
 
-       fread(enabled_features, 1, sizeof(enabled_features), fp);
+       ret = fread(enabled_features, 1, sizeof(enabled_features) - 1, fp);
+       enabled_features[ret] = '\0';
        fclose(fp);
 
        if (strstr(enabled_features, feature))