X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Futils%2Fmount_utils_ldiskfs.c;h=bf8e2c86008c2596509493ea46b0b52b2879659e;hb=d51e4a48fd75bd9840bdf5d84701efb8d18fd669;hp=a8419e9c11491f965d93451356fc322f1941b3a4;hpb=9e7b2d9cb8563c30152c6a4cbebbc568e042e9c8;p=fs%2Flustre-release.git diff --git a/lustre/utils/mount_utils_ldiskfs.c b/lustre/utils/mount_utils_ldiskfs.c index a8419e9..bf8e2c8 100644 --- a/lustre/utils/mount_utils_ldiskfs.c +++ b/lustre/utils/mount_utils_ldiskfs.c @@ -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/ @@ -47,6 +47,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include "mount_utils.h" #include #include #include @@ -78,12 +79,14 @@ #include #include #include -#include "mount_utils.h" #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 @@ -150,6 +153,7 @@ int ldiskfs_write_ldd(struct mkfs_opts *mop) if (num < 1 && ferror(filep)) { fprintf(stderr, "%s: Unable to write to file (%s): %s\n", progname, filepnm, strerror(errno)); + fclose(filep); goto out_umnt; } fclose(filep); @@ -161,6 +165,25 @@ out_rmdir: return ret; } +static int readcmd(char *cmd, char *buf, int len) +{ + FILE *fp; + int red; + + fp = popen(cmd, "r"); + if (!fp) + return errno; + + red = fread(buf, 1, len, fp); + pclose(fp); + + /* strip trailing newline */ + if (buf[red - 1] == '\n') + buf[red - 1] = '\0'; + + return (red == 0) ? -ENOENT : 0; +} + int ldiskfs_read_ldd(char *dev, struct lustre_disk_data *mo_ldd) { char tmpdir[] = "/tmp/dirXXXXXX"; @@ -199,16 +222,19 @@ int ldiskfs_read_ldd(char *dev, struct lustre_disk_data *mo_ldd) if (num_read < 1 && ferror(filep)) { fprintf(stderr, "%s: Unable to read from file %s: %s\n", progname, filepnm, strerror(errno)); - goto out_close; } + fclose(filep); } -out_close: - fclose(filep); snprintf(cmd, cmdsz, "rm -rf %s", tmpdir); run_command(cmd, cmdsz); if (ret) verrprint("Failed to read old data (%d)\n", ret); + + /* As long as we at least have the label, we're good to go */ + snprintf(cmd, sizeof(cmd), E2LABEL" %s", dev); + ret = readcmd(cmd, mo_ldd->ldd_svname, sizeof(mo_ldd->ldd_svname) - 1); + return ret; } @@ -264,7 +290,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); @@ -323,7 +349,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, @@ -381,8 +408,8 @@ static void append_unique(char *buf, char *prefix, char *key, char *val, } } -static void enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, - size_t maxbuflen, int user_spec) +static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, + size_t maxbuflen, int user_spec) { if (IS_OST(&mop->mo_ldd)) { append_unique(anchor, user_spec ? "," : " -O ", @@ -413,7 +440,17 @@ static void enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, /* The following options are only valid for ext4-based ldiskfs. * If --backfstype=ext3 is specified, do not enable them. */ if (mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3) - return; + return 0; + + /* Enable quota by default */ + if (is_e2fsprogs_feature_supp("-O quota") == 0) { + append_unique(anchor, ",", "quota", NULL, maxbuflen); + } else { + fatal(); + fprintf(stderr, "\"-O quota\" must be supported by " + "e2fsprogs, please upgrade your e2fsprogs.\n"); + return EINVAL; + } /* Allow files larger than 2TB. Also needs LU-16, but not harmful. */ if (is_e2fsprogs_feature_supp("-O huge_file") == 0) @@ -439,6 +476,7 @@ static void enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, } } /* Don't add any more "-O" options here, see last comment above */ + return 0; } /** @@ -634,13 +672,15 @@ int ldiskfs_make_lustre(struct mkfs_opts *mop) start = moveopts_to_end(start); maxbuflen = sizeof(mop->mo_mkfsopts) - (start - mop->mo_mkfsopts) - strlen(start); - enable_default_ext4_features(mop, start, maxbuflen, 1); + ret = enable_default_ext4_features(mop, start, maxbuflen, 1); } else { start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts), maxbuflen = sizeof(mop->mo_mkfsopts) - strlen(mop->mo_mkfsopts); - enable_default_ext4_features(mop, start, maxbuflen, 0); + ret = enable_default_ext4_features(mop, start, maxbuflen, 0); } + if (ret) + return ret; /* end handle -O mkfs options */ /* start handle -E mkfs options */ @@ -750,7 +790,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; @@ -768,7 +808,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; @@ -781,6 +821,51 @@ 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 */ @@ -933,6 +1018,12 @@ set_params: } } + /* 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 (fan_out) { char *slave = NULL; glob_info.gl_pathc = 0; @@ -974,6 +1065,19 @@ int ldiskfs_tune_lustre(char *dev, struct mount_opts *mop) return set_blockdev_tunables(dev, mop, 1); } +int ldiskfs_label_lustre(struct mount_opts *mop) +{ + char label_cmd[PATH_MAX]; + int rc; + + 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; +} + /* return canonicalized absolute pathname, even if the target file does not * exist, unlike realpath */ static char *absolute_path(char *devname) @@ -987,8 +1091,10 @@ static char *absolute_path(char *devname) return NULL; if (devname[0] != '/') { - if (getcwd(buf, sizeof(buf) - 1) == NULL) + if (getcwd(buf, sizeof(buf) - 1) == NULL) { + free(path); return NULL; + } strcat(buf, "/"); strcat(buf, devname); } else { @@ -1049,6 +1155,65 @@ out: return ret; } +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); + + /* Using popen() instead of run_command() since debugfs does + * not return proper error code if command is not supported */ + fp = popen(cmd, "r"); + if (!fp) { + fprintf(stderr, "%s: %s\n", progname, strerror(errno)); + return 0; + } + + ret = fread(enabled_features, 1, sizeof(enabled_features) - 1, fp); + enabled_features[ret] = '\0'; + fclose(fp); + + if (strstr(enabled_features, feature)) + return 1; + return 0; +} + +/* Enable quota accounting */ +int ldiskfs_enable_quota(struct mkfs_opts *mop) +{ + char *dev; + char cmd[512]; + int cmdsz = sizeof(cmd), ret; + + if (is_e2fsprogs_feature_supp("-O quota") != 0) { + fprintf(stderr, "%s: \"-O quota\" is is not supported by " + "current e2fsprogs\n", progname); + return EINVAL; + } + + dev = mop->mo_device; + if (mop->mo_flags & MO_IS_LOOP) + dev = mop->mo_loopdev; + + /* Quota feature is already enabled? */ + if (is_feature_enabled("quota", dev)) { + vprint("Quota feature is already enabled.\n"); + return 0; + } + + /* Turn on quota feature by "tune2fs -O quota" */ + snprintf(cmd, cmdsz, "%s -O quota %s", TUNE2FS, dev); + ret = run_command(cmd, cmdsz); + if (ret) + fprintf(stderr, "command:%s (%d)", cmd, ret); + + return ret; +} + int ldiskfs_init(void) { /* Required because full path to DEBUGFS is not specified */