X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fmkfs_lustre.c;h=1960bb26e6c8761fbd7491cc1876ae1b435aea1a;hp=8f852357896e6198c66b92588312a2595bd828f9;hb=301ed9bdf692d762c9b1c09d18e3403c9b9ef8f6;hpb=3c670d0a3e156a4b051b07a4d6ef7b001f8dcf69;ds=sidebyside diff --git a/lustre/utils/mkfs_lustre.c b/lustre/utils/mkfs_lustre.c index 8f85235..1960bb2 100644 --- a/lustre/utils/mkfs_lustre.c +++ b/lustre/utils/mkfs_lustre.c @@ -1,28 +1,52 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Copyright (C) 2006 Cluster File Systems, Inc. - * Author: Nathan Rutman + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. */ - /* This source file is compiled into both mkfs.lustre and tunefs.lustre */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/utils/mkfs_lustre.c + * + * Author: Nathan Rutman +*/ + +/* This source file is compiled into both mkfs.lustre and tunefs.lustre */ +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include #include @@ -38,18 +62,22 @@ #include #include #include +#include #ifdef __linux__ -/* kp30.h is not really needed here, but on SLES10/PPC, fs.h includes idr.h which +/* libcfs.h is not really needed here, but on SLES10/PPC, fs.h includes idr.h which * requires BITS_PER_LONG to be defined */ -#include +#include +#ifndef BLKGETSIZE64 #include /* for BLKGETSIZE64 */ +#endif #include #endif #include #include #include #include +#include "mount_utils.h" #ifndef PATH_MAX #define PATH_MAX 4096 @@ -73,10 +101,11 @@ struct mkfs_opts { int mo_mgs_failnodes; }; -static char *progname; -static int verbose = 1; +char *progname; +int verbose = 1; static int print_only = 0; static int failover = 0; +static int upgrade_to_18 = 0; void usage(FILE *out) { @@ -103,12 +132,14 @@ void usage(FILE *out) */ "\t\t--comment=: arbitrary user string (%d bytes)\n" "\t\t--mountfsoptions= : permanent mount options\n" + "\t\t--network=[,<...>] : network(s) to restrict this ost/mdt to\n" #ifndef TUNEFS "\t\t--backfstype= : backing fs type (ext3, ldiskfs)\n" "\t\t--device-size=#N(KB) : device size for loop devices\n" "\t\t--mkfsoptions= : format options\n" "\t\t--reformat: overwrite an existing disk\n" "\t\t--stripe-count-hint=#N : used for optimizing MDT inode size\n" + "\t\t--iam-dir: make use of IAM directory format on backfs, incompatible with ext3.\n" #else "\t\t--erase-params : erase all old parameter settings\n" "\t\t--nomgs: turn off MGS service on this MDT\n" @@ -125,12 +156,6 @@ void usage(FILE *out) #define vprint if (verbose > 0) printf #define verrprint if (verbose >= 0) printf -static void fatal(void) -{ - verbose = 0; - fprintf(stderr, "\n%s FATAL: ", progname); -} - /*================ utility functions =====================*/ char *strscat(char *dst, char *src, int buflen) { @@ -174,7 +199,12 @@ int get_os_version() fprintf(stderr, "%s: Warning: Can't resolve kernel " "version, assuming 2.6\n", progname); else { - read(fd, release, 4); + if (read(fd, release, 4) < 0) { + fprintf(stderr, "reading from /proc/sys/kernel" + "/osrelease: %s\n", strerror(errno)); + close(fd); + exit(-1); + } close(fd); } if (strncmp(release, "2.4.", 4) == 0) @@ -185,47 +215,6 @@ int get_os_version() return version; } -int run_command(char *cmd, int cmdsz) -{ - char log[] = "/tmp/mkfs_logXXXXXX"; - int fd = -1, rc; - - if ((cmdsz - strlen(cmd)) < 6) { - fatal(); - fprintf(stderr, "Command buffer overflow: %.*s...\n", - cmdsz, cmd); - return ENOMEM; - } - - if (verbose > 1) { - printf("cmd: %s\n", cmd); - } else { - if ((fd = mkstemp(log)) >= 0) { - close(fd); - strcat(cmd, " >"); - strcat(cmd, log); - } - } - strcat(cmd, " 2>&1"); - - /* Can't use popen because we need the rv of the command */ - rc = system(cmd); - if (rc && (fd >= 0)) { - char buf[128]; - FILE *fp; - fp = fopen(log, "r"); - if (fp) { - while (fgets(buf, sizeof(buf), fp) != NULL) { - printf(" %s", buf); - } - fclose(fp); - } - } - if (fd >= 0) - remove(log); - return rc; -} - static int check_mtab_entry(char *spec) { FILE *fp; @@ -285,6 +274,10 @@ int loop_setup(struct mkfs_opts *mop) snprintf(cmd, cmdsz, "losetup %s %s", l_device, mop->mo_device); ret = run_command(cmd, cmdsz); + if (ret == 256) + /* someone else picked up this loop device + * behind our back */ + continue; if (ret) { fprintf(stderr, "%s: error %d on losetup: %s\n", progname, ret, strerror(ret)); @@ -400,23 +393,25 @@ static void disp_old_e2fsprogs_msg(const char *feature, int make_backfs) static int msg_displayed; if (msg_displayed) { - fprintf(stderr, "WARNING: e2fsprogs does not support %s " - "feature.\n\n", feature); + fprintf(stderr, "WARNING: %s does not support %s " + "feature.\n\n", E2FSPROGS, feature); return; } msg_displayed++; - fprintf(stderr, "WARNING: The e2fsprogs package currently installed on " - "your system does not support \"%s\" feature.\nPlease install " - "the latest version of e2fsprogs from http://www.clusterfs.com/" - "downloads/public/Lustre/Tools/e2fsprogs/\nto enable this " - "feature.\n", feature); - + fprintf(stderr, "WARNING: The %s package currently installed on " + "your system does not support \"%s\" feature.\n", + E2FSPROGS, feature); +#if !(HAVE_LDISKFSPROGS) + fprintf(stderr, "Please install the latest version of e2fsprogs from\n" + "http://downloads.lustre.org/public/tools/e2fsprogs/\n" + "to enable this feature.\n"); +#endif if (make_backfs) - fprintf(stderr, "Feature will not be enabled until e2fsprogs " - "is updated and 'tune2fs -O %s %%{device}' " - "is run.\n\n", feature); + fprintf(stderr, "Feature will not be enabled until %s" + "is updated and '%s -O %s %%{device}' " + "is run.\n\n", E2FSPROGS, TUNE2FS, feature); } /* Check whether the file exists in the device */ @@ -429,8 +424,8 @@ static int file_in_dev(char *file_name, char *dev_name) /* Construct debugfs command line. */ snprintf(debugfs_cmd, sizeof(debugfs_cmd), - "debugfs -c -R 'stat %s' %s 2>&1 | egrep '(Inode|unsupported)'", - file_name, dev_name); + "%s -c -R 'stat %s' '%s' 2>&1 | egrep '(Inode|unsupported)'", + DEBUGFS, file_name, dev_name); fp = popen(debugfs_cmd, "r"); if (!fp) { @@ -449,6 +444,7 @@ static int file_in_dev(char *file_name, char *dev_name) if (strstr(debugfs_cmd, "unsupported feature")) { disp_old_e2fsprogs_msg("an unknown", 0); } + pclose(fp); return -1; } pclose(fp); @@ -491,8 +487,8 @@ static int is_e2fsprogs_feature_supp(const char *feature) int fd = -1; int ret = 0; - snprintf(cmd, sizeof(cmd), - "debugfs -c -R \"supported_features %s\" 2>&1", feature); + snprintf(cmd, sizeof(cmd), "%s -c -R \"supported_features %s\" 2>&1", + DEBUGFS, feature); /* Using popen() instead of run_command() since debugfs does not return * proper error code if command is not supported */ @@ -510,8 +506,8 @@ static int is_e2fsprogs_feature_supp(const char *feature) if ((fd = mkstemp(imgname)) < 0) return -1; - snprintf(cmd, sizeof(cmd), "mke2fs -F -O %s %s 100 >/dev/null 2>&1", - feature, imgname); + snprintf(cmd, sizeof(cmd), "%s -F -O %s %s 100 >/dev/null 2>&1", + MKE2FS, feature, imgname); /* run_command() displays the output of mke2fs when it fails for * some feature, so use system() directly */ ret = system(cmd); @@ -521,28 +517,29 @@ static int is_e2fsprogs_feature_supp(const char *feature) return ret; } -static void disp_old_kernel_msg(char *feature) -{ - fprintf(stderr, "WARNING: ldiskfs filesystem does not support \"%s\" " - "feature.\n\n", feature); -} - static void enable_default_backfs_features(struct mkfs_opts *mop) { struct utsname uts; - int maj_high, maj_low, min; int ret; - strscat(mop->mo_mkfsopts, " -O dir_index", sizeof(mop->mo_mkfsopts)); + if (IS_OST(&mop->mo_ldd)) + strscat(mop->mo_mkfsopts, " -O dir_index,extents", + sizeof(mop->mo_mkfsopts)); + else if (IS_MDT(&mop->mo_ldd)) + strscat(mop->mo_mkfsopts, " -O dir_index,dirdata", + sizeof(mop->mo_mkfsopts)); + else + strscat(mop->mo_mkfsopts, " -O dir_index", + sizeof(mop->mo_mkfsopts)); /* Upstream e2fsprogs called our uninit_groups feature uninit_bg, * check for both of them when testing e2fsprogs features. */ - if (is_e2fsprogs_feature_supp("uninit_groups") == 0) - strscat(mop->mo_mkfsopts, ",uninit_groups", - sizeof(mop->mo_mkfsopts)); - else if (is_e2fsprogs_feature_supp("uninit_bg") == 0) + if (is_e2fsprogs_feature_supp("uninit_bg") == 0) strscat(mop->mo_mkfsopts, ",uninit_bg", sizeof(mop->mo_mkfsopts)); + else if (is_e2fsprogs_feature_supp("uninit_groups") == 0) + strscat(mop->mo_mkfsopts, ",uninit_groups", + sizeof(mop->mo_mkfsopts)); else disp_old_e2fsprogs_msg("uninit_bg", 1); @@ -550,32 +547,37 @@ static void enable_default_backfs_features(struct mkfs_opts *mop) if (ret) return; - sscanf(uts.release, "%d.%d.%d", &maj_high, &maj_low, &min); - printf("%d %d %d\n", maj_high, maj_low, min); - /* Multiple mount protection is enabled only if failover node is * specified and if kernel version is higher than 2.6.9 */ if (failover) { - if (KERNEL_VERSION(maj_high, maj_low, min) >= - KERNEL_VERSION(2,6,9)) { - if (is_e2fsprogs_feature_supp("mmp") == 0) - strscat(mop->mo_mkfsopts, ",mmp", - sizeof(mop->mo_mkfsopts)); - else - disp_old_e2fsprogs_msg("mmp", 1); - } else { - disp_old_kernel_msg("mmp"); - } + if (is_e2fsprogs_feature_supp("mmp") == 0) + strscat(mop->mo_mkfsopts, ",mmp", + sizeof(mop->mo_mkfsopts)); + else + disp_old_e2fsprogs_msg("mmp", 1); } } /* Build fs according to type */ int make_lustre_backfs(struct mkfs_opts *mop) { + __u64 device_sz = mop->mo_device_sz, block_count = 0; char mkfs_cmd[PATH_MAX]; char buf[64]; char *dev; int ret = 0; - int block_count = 0; + + if (!(mop->mo_flags & MO_IS_LOOP)) { + mop->mo_device_sz = get_device_size(mop->mo_device); + + if (mop->mo_device_sz == 0) + return ENODEV; + + /* Compare to real size */ + if (device_sz == 0 || device_sz > mop->mo_device_sz) + device_sz = mop->mo_device_sz; + else + mop->mo_device_sz = device_sz; + } if (mop->mo_device_sz != 0) { if (mop->mo_device_sz < 8096){ @@ -590,15 +592,6 @@ int make_lustre_backfs(struct mkfs_opts *mop) if ((mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3) || (mop->mo_ldd.ldd_mount_type == LDD_MT_LDISKFS) || (mop->mo_ldd.ldd_mount_type == LDD_MT_LDISKFS2)) { - __u64 device_sz = mop->mo_device_sz; - - /* we really need the size */ - if (device_sz == 0) { - device_sz = get_device_size(mop->mo_device); - if (device_sz == 0) - return ENODEV; - } - /* Journal size in MB */ if (strstr(mop->mo_mkfsopts, "-J") == NULL) { /* Choose our own default journal size */ @@ -609,7 +602,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) if (journal_sz > 1024L) journal_sz = 1024L; /* man mkfs.ext3 */ - max_sz = (256000 * L_BLOCK_SIZE) >> 20; /* 1GB */ + max_sz = (102400 * L_BLOCK_SIZE) >> 20; /* 400MB */ if (journal_sz > max_sz) journal_sz = max_sz; if (journal_sz) { @@ -681,7 +674,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) strscat(mop->mo_mkfsopts, " -F", sizeof(mop->mo_mkfsopts)); snprintf(mkfs_cmd, sizeof(mkfs_cmd), - "mkfs.ext2 -j -b %d -L %s ", L_BLOCK_SIZE, + "%s -j -b %d -L %s ", MKE2FS, L_BLOCK_SIZE, mop->mo_ldd.ldd_svname); } else if (mop->mo_ldd.ldd_mount_type == LDD_MT_REISERFS) { long journal_sz = 0; /* FIXME default journal size */ @@ -706,7 +699,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) vprint("formatting backing filesystem %s on %s\n", MT_STR(&mop->mo_ldd), dev); vprint("\ttarget name %s\n", mop->mo_ldd.ldd_svname); - vprint("\t4k blocks %d\n", block_count); + vprint("\t4k blocks "LPU64"\n", block_count); vprint("\toptions %s\n", mop->mo_mkfsopts); /* mkfs_cmd's trailing space is important! */ @@ -714,7 +707,7 @@ int make_lustre_backfs(struct mkfs_opts *mop) strscat(mkfs_cmd, " ", sizeof(mkfs_cmd)); strscat(mkfs_cmd, dev, sizeof(mkfs_cmd)); if (block_count != 0) { - sprintf(buf, " %d", block_count); + sprintf(buf, " "LPU64, block_count); strscat(mkfs_cmd, buf, sizeof(mkfs_cmd)); } @@ -742,7 +735,7 @@ void print_ldd(char *str, struct lustre_disk_data *ldd) printf("Lustre FS: %s\n", ldd->ldd_fsname); printf("Mount type: %s\n", MT_STR(ldd)); printf("Flags: %#x\n", ldd->ldd_flags); - printf(" (%s%s%s%s%s%s%s%s)\n", + printf(" (%s%s%s%s%s%s%s%s%s)\n", IS_MDT(ldd) ? "MDT ":"", IS_OST(ldd) ? "OST ":"", IS_MGS(ldd) ? "MGS ":"", @@ -750,6 +743,7 @@ void print_ldd(char *str, struct lustre_disk_data *ldd) ldd->ldd_flags & LDD_F_VIRGIN ? "first_time ":"", ldd->ldd_flags & LDD_F_UPDATE ? "update ":"", ldd->ldd_flags & LDD_F_WRITECONF ? "writeconf ":"", + ldd->ldd_flags & LDD_F_IAM_DIR ? "IAM_dir_format ":"", ldd->ldd_flags & LDD_F_UPGRADE14 ? "upgrade1.4 ":""); printf("Persistent mount opts: %s\n", ldd->ldd_mount_opts); printf("Parameters:%s\n", ldd->ldd_params); @@ -758,6 +752,67 @@ void print_ldd(char *str, struct lustre_disk_data *ldd) printf("\n"); } +static int touch_file(char *filename) +{ + int fd; + + if (filename == NULL) { + return 1; + } + + fd = open(filename, O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + return 1; + } else { + close(fd); + return 0; + } +} + +/* keep it less than LL_FID_NAMELEN */ +#define DUMMY_FILE_NAME_LEN 25 +#define EXT3_DIRENT_SIZE DUMMY_FILE_NAME_LEN + +/* Need to add these many entries to this directory to make HTREE dir. */ +#define MIN_ENTRIES_REQ_FOR_HTREE ((L_BLOCK_SIZE / EXT3_DIRENT_SIZE)) + +static int add_dummy_files(char *dir) +{ + char fpname[PATH_MAX]; + int i; + int rc; + + for (i = 0; i < MIN_ENTRIES_REQ_FOR_HTREE; i++) { + snprintf(fpname, PATH_MAX, "%s/%0*d", dir, + DUMMY_FILE_NAME_LEN, i); + + rc = touch_file(fpname); + if (rc && rc != -EEXIST) { + fprintf(stderr, + "%s: Can't create dummy file %s: %s\n", + progname, fpname , strerror(errno)); + return rc; + } + } + return 0; +} + +static int __l_mkdir(char * filepnm, int mode , struct mkfs_opts *mop) +{ + int ret; + + ret = mkdir(filepnm, mode); + if (ret && ret != -EEXIST) + return ret; + + /* IAM mode supports ext3 directories of HTREE type only. So add dummy + * entries to new directory to create htree type of container for + * this directory. */ + if (mop->mo_ldd.ldd_flags & LDD_F_IAM_DIR) + return add_dummy_files(filepnm); + return 0; +} + /* Write the server config files */ int write_local_files(struct mkfs_opts *mop) { @@ -766,6 +821,7 @@ int write_local_files(struct mkfs_opts *mop) char *dev; FILE *filep; int ret = 0; + size_t num; /* Mount this device temporarily in order to write these files */ if (!mkdtemp(mntpt)) { @@ -778,7 +834,8 @@ int write_local_files(struct mkfs_opts *mop) if (mop->mo_flags & MO_IS_LOOP) dev = mop->mo_loopdev; - ret = mount(dev, mntpt, MT_STR(&mop->mo_ldd), 0, NULL); + ret = mount(dev, mntpt, MT_STR(&mop->mo_ldd), 0, + mop->mo_ldd.ldd_mount_opts); if (ret) { fprintf(stderr, "%s: Unable to mount %s: %s\n", progname, dev, strerror(errno)); @@ -792,7 +849,7 @@ int write_local_files(struct mkfs_opts *mop) /* Set up initial directories */ sprintf(filepnm, "%s/%s", mntpt, MOUNT_CONFIGS_DIR); - ret = mkdir(filepnm, 0777); + ret = __l_mkdir(filepnm, 0777, mop); if ((ret != 0) && (errno != EEXIST)) { fprintf(stderr, "%s: Can't make configs dir %s (%s)\n", progname, filepnm, strerror(errno)); @@ -801,16 +858,6 @@ int write_local_files(struct mkfs_opts *mop) ret = 0; } - sprintf(filepnm, "%s/%s", mntpt, "ROOT"); - ret = mkdir(filepnm, 0777); - if ((ret != 0) && (errno != EEXIST)) { - fprintf(stderr, "%s: Can't make ROOT dir %s (%s)\n", - progname, filepnm, strerror(errno)); - goto out_umnt; - } else if (errno == EEXIST) { - ret = 0; - } - /* Save the persistent mount data into a file. Lustre must pre-read this file to get the real mount options. */ vprint("Writing %s\n", MOUNT_DATA_FILE); @@ -821,9 +868,13 @@ int write_local_files(struct mkfs_opts *mop) progname, filepnm, strerror(errno)); goto out_umnt; } - fwrite(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep); + num = fwrite(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep); + if (num < 1 && ferror(filep)) { + fprintf(stderr, "%s: Unable to write to file (%s): %s\n", + progname, filepnm, strerror(errno)); + goto out_umnt; + } fclose(filep); - /* COMPAT_146 */ #ifdef TUNEFS /* Check for upgrade */ @@ -885,7 +936,6 @@ int write_local_files(struct mkfs_opts *mop) #endif /* end COMPAT_146 */ - out_umnt: umount(mntpt); out_rmdir: @@ -912,9 +962,13 @@ int read_local_files(struct mkfs_opts *mop) dev = mop->mo_device; + /* TODO: it's worth observing the get_mountdata() function that is + in mount_utils.c for getting the mountdata out of the + filesystem */ + /* Construct debugfs command line. */ - snprintf(cmd, cmdsz, "debugfs -c -R 'dump /%s %s/mountdata' %s", - MOUNT_DATA_FILE, tmpdir, dev); + snprintf(cmd, cmdsz, "%s -c -R 'dump /%s %s/mountdata' '%s'", + DEBUGFS, MOUNT_DATA_FILE, tmpdir, dev); ret = run_command(cmd, cmdsz); if (ret) @@ -924,8 +978,14 @@ int read_local_files(struct mkfs_opts *mop) sprintf(filepnm, "%s/mountdata", tmpdir); filep = fopen(filepnm, "r"); if (filep) { + size_t num_read; vprint("Reading %s\n", MOUNT_DATA_FILE); - fread(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep); + num_read = fread(&mop->mo_ldd, sizeof(mop->mo_ldd), 1, filep); + if (num_read < 1 && ferror(filep)) { + fprintf(stderr, "%s: Unable to read from file (%s): %s\n", + progname, filepnm, strerror(errno)); + goto out_close; + } } else { /* COMPAT_146 */ /* Try to read pre-1.6 config from last_rcvd */ @@ -937,8 +997,8 @@ int read_local_files(struct mkfs_opts *mop) sprintf(filepnm, "%s/%s", tmpdir, LAST_RCVD); /* Construct debugfs command line. */ - snprintf(cmd, cmdsz, "debugfs -c -R 'dump /%s %s' %s", - LAST_RCVD, filepnm, dev); + snprintf(cmd, cmdsz, "%s -c -R 'dump /%s %s' %s", + DEBUGFS, LAST_RCVD, filepnm, dev); ret = run_command(cmd, cmdsz); if (ret) { @@ -957,7 +1017,8 @@ int read_local_files(struct mkfs_opts *mop) snprintf(cmd, cmdsz, "ls -l %s/", tmpdir); run_command(cmd, cmdsz); verrprint("Contents of disk:\n"); - snprintf(cmd, cmdsz, "debugfs -c -R 'ls -l /' %s", dev); + snprintf(cmd, cmdsz, "%s -c -R 'ls -l /' %s", + DEBUGFS, dev); run_command(cmd, cmdsz); goto out_rmdir; @@ -989,8 +1050,8 @@ int read_local_files(struct mkfs_opts *mop) } else { /* If neither is set, we're pre-1.4.6, make a guess. */ /* Construct debugfs command line. */ - snprintf(cmd, cmdsz, "debugfs -c -R 'rdump /%s %s' %s", - MDT_LOGS_DIR, tmpdir, dev); + snprintf(cmd, cmdsz, "%s -c -R 'rdump /%s %s' %s", + DEBUGFS, MDT_LOGS_DIR, tmpdir, dev); run_command(cmd, cmdsz); sprintf(filepnm, "%s/%s", tmpdir, MDT_LOGS_DIR); @@ -1079,7 +1140,7 @@ static int add_param(char *buf, char *key, char *val) #define MAXNIDSTR 1024 static char *convert_hostnames(char *s1) { - char *converted, *s2 = 0, *c; + char *converted, *s2 = 0, *c, *end, sep; int left = MAXNIDSTR; lnet_nid_t nid; @@ -1088,33 +1149,35 @@ static char *convert_hostnames(char *s1) return NULL; } + end = s1 + strlen(s1); c = converted; - while ((left > 0) && ((s2 = strsep(&s1, ",: \0")))) { - nid = libcfs_str2nid(s2); + while ((left > 0) && (s1 < end)) { + s2 = strpbrk(s1, ",:"); + if (!s2) + s2 = end; + sep = *s2; + *s2 = '\0'; + nid = libcfs_str2nid(s1); + if (nid == LNET_NID_ANY) { - if (*s2 == '/') - /* end of nids */ - break; - fprintf(stderr, "%s: Can't parse NID '%s'\n", - progname, s2); + fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, s1); free(converted); return NULL; } - if (strncmp(libcfs_nid2str(nid), "127.0.0.1", strlen("127.0.0.1")) == 0) { fprintf(stderr, "%s: The NID '%s' resolves to the " "loopback address '%s'. Lustre requires a " "non-loopback address.\n", - progname, s2, libcfs_nid2str(nid)); + progname, s1, libcfs_nid2str(nid)); free(converted); return NULL; } - c += snprintf(c, left, "%s,", libcfs_nid2str(nid)); + c += snprintf(c, left, "%s%c", libcfs_nid2str(nid), sep); left = converted + MAXNIDSTR - c; + s1 = s2 + 1; } - *(c - 1) = '\0'; return converted; } @@ -1122,6 +1185,7 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, char **mountopts) { static struct option long_opt[] = { + {"iam-dir", 0, 0, 'a'}, {"backfstype", 1, 0, 'b'}, {"stripe-count-hint", 1, 0, 'c'}, {"comment", 1, 0, 'u'}, @@ -1149,6 +1213,8 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, {"reformat", 0, 0, 'r'}, {"verbose", 0, 0, 'v'}, {"writeconf", 0, 0, 'w'}, + {"upgrade_to_18", 0, 0, 'U'}, + {"network", 1, 0, 't'}, {0, 0, 0, 0} }; char *optstring = "b:c:C:d:ef:Ghi:k:L:m:MnNo:Op:Pqru:vw"; @@ -1158,6 +1224,11 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) != EOF) { switch (opt) { + case 'a': { + if (IS_MDT(&mop->mo_ldd)) + mop->mo_ldd.ldd_flags |= LDD_F_IAM_DIR; + break; + } case 'b': { int i = 0; while (i < LDD_MT_LAST) { @@ -1299,6 +1370,22 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, case 'r': mop->mo_flags |= MO_FORCEFORMAT; break; + case 't': + if (!IS_MDT(&mop->mo_ldd) && !IS_OST(&mop->mo_ldd)) { + badopt(long_opt[longidx].name, "MDT,OST"); + return 1; + } + + if (!optarg) + return 1; + + rc = add_param(mop->mo_ldd.ldd_params, + PARAM_NETWORK, optarg); + if (rc != 0) + return rc; + /* Must update the mgs logs */ + mop->mo_ldd.ldd_flags |= LDD_F_UPDATE; + break; case 'u': strscpy(mop->mo_ldd.ldd_userdata, optarg, sizeof(mop->mo_ldd.ldd_userdata)); @@ -1309,6 +1396,9 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, case 'w': mop->mo_ldd.ldd_flags |= LDD_F_WRITECONF; break; + case 'U': + upgrade_to_18 = 1; + break; default: if (opt != '?') { fatal(); @@ -1325,229 +1415,82 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, return EINVAL; } - return 0; -} - -#include - -#define LDISKFS_IOC_GETVERSION _IOR('f', 3, long) + /* single argument: */ + if (argc == 2) + ++print_only; -#ifndef TUNEFS /* mkfs.lustre */ -static int mkfs_iam_insert(int key_need_convert, char *keybuf, - int rec_need_convert, char *recbuf, char *filename) -{ - int fd; - int ret; - struct iam_uapi_info ua; - - fd = iam_open(filename, &ua); - if (fd < 0) { - fprintf(stderr, "failed to iam_open %s\n", filename); - return 1; - } - - ret = iam_insert(fd, &ua, - key_need_convert, keybuf, - rec_need_convert, recbuf); - iam_close(fd); - if (ret) { - fprintf(stderr, "failed to iam_insert %s\n", filename); - return 1; - } else { - return 0; - } + return 0; } -static int touch_file(char *filename) +/* Search for opt in mntlist, returning true if found. + */ +static int in_mntlist(char *opt, char *mntlist) { - int fd; + char *ml, *mlp, *item, *ctx = NULL; - if (filename == NULL) { - return 1; + if (!(ml = strdup(mntlist))) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); } - - fd = open(filename, O_CREAT | O_TRUNC, 0600); - if (fd < 0) { - return 1; - } else { - close(fd); - return 0; + mlp = ml; + while ((item = strtok_r(mlp, ",", &ctx))) { + if (!strcmp(opt, item)) + break; + mlp = NULL; } + free(ml); + return (item != NULL); } -static int get_generation(char *filename, unsigned long *result) +/* Issue a message on stderr for every item in wanted_mountopts that is not + * present in mountopts. The justwarn boolean toggles between error and + * warning message. Return an error count. + */ +static int check_mountfsoptions(char *mountopts, char *wanted_mountopts, + int justwarn) { - int fd; - int ret; - - if (filename == NULL) { - return 1; - } - - fd = open(filename, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "%s: failed to open %s\n", - __FUNCTION__, filename); - return 1; + char *ml, *mlp, *item, *ctx = NULL; + int errors = 0; + + if (!(ml = strdup(wanted_mountopts))) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + 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); + errors++; + } + mlp = NULL; } - - ret = ioctl(fd, LDISKFS_IOC_GETVERSION, result); - close(fd); - - return ((ret < 0) ? ret : 0); + free(ml); + return errors; } -static int mkfs_mdt(struct mkfs_opts *mop) +/* Trim embedded white space, leading and trailing commas from string s. + */ +static void trim_mountfsoptions(char *s) { - char mntpt[] = "/tmp/mntXXXXXX"; - char fstype[] = "ldiskfs"; - char filepnm[128]; - char recbuf[64]; - char *source; - int ret; - unsigned long generation; - struct stat st; - - source = mop->mo_device; - if (mop->mo_flags & MO_IS_LOOP) { - source = mop->mo_loopdev; - } - - if ((source == NULL) || (*source == 0)) { - return 1; - } - - if (!mkdtemp(mntpt)) { - fprintf(stderr, "%s: failed to mkdtemp %s\n", - __FUNCTION__, mntpt); - return errno; - } - - ret = mount(source, mntpt, fstype, 0, NULL); - if (ret) { - goto out_rmdir; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "seq_ctl"); - ret = touch_file(filepnm); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "seq_srv"); - ret = touch_file(filepnm); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "last_received"); - ret = touch_file(filepnm); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "lov_objid"); - ret = touch_file(filepnm); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); - ret = iam_creat(filepnm, FMT_LVAR, L_BLOCK_SIZE, 4, 17, 4); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "fld"); - ret = iam_creat(filepnm, FMT_LFIX, L_BLOCK_SIZE, 8, 8, 4); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "orphans"); - ret = iam_creat(filepnm, FMT_LFIX, L_BLOCK_SIZE, 20, 8, 4); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "oi.16"); - ret = iam_creat(filepnm, FMT_LFIX, L_BLOCK_SIZE, 16, 8, 4); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "oi.5"); - ret = iam_creat(filepnm, FMT_LFIX, L_BLOCK_SIZE, 5, 8, 4); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, CAPA_KEYS); - ret = touch_file(filepnm); - if (ret) { - goto out_umount; - } - - umount(mntpt); - ret = mount(source, mntpt, fstype, 0, NULL); - if (ret) { - goto out_rmdir; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); - ret = iam_polymorph(filepnm, 040755); - if (ret) { - perror("IAM_IOC_POLYMORPH"); - goto out_umount; - } - - umount(mntpt); - ret = mount(source, mntpt, fstype, 0, NULL); - if (ret) { - goto out_rmdir; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "fld"); - ret = mkfs_iam_insert(1, "0000000000000002", 1, "0000000000000000", filepnm); - if (ret) { - goto out_umount; - } - - ret = mkfs_iam_insert(1, "0000000000000001", 1, "0000000000000000", filepnm); - if (ret) { - goto out_umount; - } - - snprintf(filepnm, sizeof(filepnm) - 1, "%s/%s", mntpt, "root"); - ret = stat(filepnm, &st); - if (ret) { - goto out_umount; - } + char *p; - ret = get_generation(filepnm, &generation); - if (ret) { - goto out_umount; - } - - snprintf(recbuf, sizeof(recbuf) - 1, "110000000000000001%8.8x%8.8x", - (unsigned int)st.st_ino, (unsigned int)generation); - ret = mkfs_iam_insert(0, ".", 1, recbuf, filepnm); - if (ret) { - goto out_umount; + for (p = s; *p; ) { + if (isspace(*p)) { + memmove(p, p + 1, strlen(p + 1) + 1); + continue; + } + p++; } - ret = mkfs_iam_insert(0, "..", 1, recbuf, filepnm); - if (ret) { - goto out_umount; - } + while (s[0] == ',') + memmove(&s[0], &s[1], strlen(&s[1]) + 1); -out_umount: - umount(mntpt); -out_rmdir: - rmdir(mntpt); - return ret; + p = s + strlen(s) - 1; + while (p >= s && *p == ',') + *p-- = '\0'; } -#endif int main(int argc, char *const argv[]) { @@ -1663,7 +1606,8 @@ int main(int argc, char *const argv[]) case LDD_MT_EXT3: case LDD_MT_LDISKFS: case LDD_MT_LDISKFS2: { - sprintf(always_mountopts, "errors=remount-ro"); + strscat(default_mountopts, ",errors=remount-ro", + sizeof(default_mountopts)); if (IS_MDT(ldd) || IS_MGS(ldd)) strscat(always_mountopts, ",iopen_nopriv,user_xattr", sizeof(always_mountopts)); @@ -1671,7 +1615,7 @@ int main(int argc, char *const argv[]) strscat(always_mountopts, ",asyncdel", sizeof(always_mountopts)); /* NB: Files created while extents are enabled cannot be read - if mounted with a kernel that doesn't include the CFS + if mounted with a kernel that doesn't include the Lustre ldiskfs patches! */ if (IS_OST(ldd) && (ldd->ldd_mount_type == LDD_MT_LDISKFS || @@ -1683,7 +1627,7 @@ int main(int argc, char *const argv[]) } case LDD_MT_SMFS: { mop.mo_flags |= MO_IS_LOOP; - sprintf(always_mountopts, "type=ext3,dev=%s", + sprintf(always_mountopts, ",type=ext3,dev=%s", mop.mo_device); break; } @@ -1698,10 +1642,13 @@ int main(int argc, char *const argv[]) } if (mountopts) { - /* If user specifies mount opts, don't use defaults, - but always use always_mountopts */ - sprintf(ldd->ldd_mount_opts, "%s,%s", - always_mountopts, mountopts); + trim_mountfsoptions(mountopts); + (void)check_mountfsoptions(mountopts, default_mountopts, 1); + if (check_mountfsoptions(mountopts, always_mountopts, 0)) { + ret = EINVAL; + goto out; + } + sprintf(ldd->ldd_mount_opts, "%s", mountopts); } else { #ifdef TUNEFS if (ldd->ldd_mount_opts[0] == 0) @@ -1710,6 +1657,7 @@ int main(int argc, char *const argv[]) { sprintf(ldd->ldd_mount_opts, "%s%s", always_mountopts, default_mountopts); + trim_mountfsoptions(ldd->ldd_mount_opts); } } @@ -1778,16 +1726,6 @@ int main(int argc, char *const argv[]) goto out; } -#ifndef TUNEFS /* mkfs.lustre */ - if (IS_MDT(ldd)) { - ret = mkfs_mdt(&mop); - if (ret != 0) { - fprintf(stderr, "failed to mkfs_mdt\n"); - goto out; - } - } -#endif - out: loop_cleanup(&mop);