mkfs_lustre.c

来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,598 行 · 第 1/4 页

C
1,598
字号
/* -*- 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 <nathan@clusterfs.com> * *   This file is part of Lustre, http://www.lustre.org. * *   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. * *   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. * *   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. * */ /* This source file is compiled into both mkfs.lustre and tunefs.lustre */#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <stdarg.h>#include <mntent.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mount.h>#include <sys/utsname.h>#include <string.h>#include <getopt.h>#include <limits.h>#ifdef __linux__/* kp30.h is not really needed here, but on SLES10/PPC, fs.h includes idr.h which * requires BITS_PER_LONG to be defined */#include <libcfs/kp30.h>#include <linux/fs.h> /* for BLKGETSIZE64 */#include <linux/version.h>#endif#include <lustre_disk.h>#include <lustre_param.h>#include <lnet/lnetctl.h>#include <lustre_ver.h>#ifndef PATH_MAX#define PATH_MAX 4096#endif#define MAX_LOOP_DEVICES 16#define L_BLOCK_SIZE 4096#define INDEX_UNASSIGNED 0xFFFF#define MO_IS_LOOP     0x01#define MO_FORCEFORMAT 0x02/* used to describe the options to format the lustre disk, not persistent */struct mkfs_opts {        struct lustre_disk_data mo_ldd; /* to be written in MOUNT_DATA_FILE */        char  mo_device[128];           /* disk device name */        char  mo_mkfsopts[128];         /* options to the backing-store mkfs */        char  mo_loopdev[128];          /* in case a loop dev is needed */        __u64 mo_device_sz;             /* in KB */        int   mo_stripe_count;        int   mo_flags;        int   mo_mgs_failnodes;};static char *progname;static int verbose = 1;static int print_only = 0;static int failover = 0;void usage(FILE *out){        fprintf(out, "%s v"LUSTRE_VERSION_STRING"\n", progname);        fprintf(out, "usage: %s <target types> [options] <device>\n", progname);        fprintf(out,                "\t<device>:block device or file (e.g /dev/sda or /tmp/ost1)\n"                "\ttarget types:\n"                "\t\t--ost: object storage, mutually exclusive with mdt,mgs\n"                "\t\t--mdt: metadata storage, mutually exclusive with ost\n"                "\t\t--mgs: configuration management service - one per site\n"                "\toptions (in order of popularity):\n"                "\t\t--mgsnode=<nid>[,<...>] : NID(s) of a remote mgs node\n"                "\t\t\trequired for all targets other than the mgs node\n"                "\t\t--fsname=<filesystem_name> : default is 'lustre'\n"                "\t\t--failnode=<nid>[,<...>] : NID(s) of a failover partner\n"                "\t\t--param <key>=<value> : set a permanent parameter\n"                "\t\t\te.g. --param sys.timeout=40\n"                "\t\t\t     --param lov.stripesize=2M\n"                "\t\t--index=#N : target index (i.e. ost index within the lov)\n"                /* FIXME implement 1.6.x                "\t\t--configdev=<altdevice|file>: store configuration info\n"                "\t\t\tfor this device on an alternate device\n"                */                "\t\t--comment=<user comment>: arbitrary user string (%d bytes)\n"                "\t\t--mountfsoptions=<opts> : permanent mount options\n"#ifndef TUNEFS                "\t\t--backfstype=<fstype> : backing fs type (ext3, ldiskfs)\n"                "\t\t--device-size=#N(KB) : device size for loop devices\n"                "\t\t--mkfsoptions=<opts> : format options\n"                "\t\t--reformat: overwrite an existing disk\n"                "\t\t--stripe-count-hint=#N : used for optimizing MDT inode size\n"#else                "\t\t--erase-params : erase all old parameter settings\n"                "\t\t--nomgs: turn off MGS service on this MDT\n"                "\t\t--writeconf: erase all config logs for this fs.\n"#endif                "\t\t--dryrun: just report what we would do; "                "don't write to disk\n"                "\t\t--verbose : e.g. show mkfs progress\n"                "\t\t--quiet\n",                (int)sizeof(((struct lustre_disk_data *)0)->ldd_userdata));        return;}#define vprint if (verbose > 0) printf#define verrprint if (verbose >= 0) printfstatic void fatal(void){        verbose = 0;        fprintf(stderr, "\n%s FATAL: ", progname);}/*================ utility functions =====================*/char *strscat(char *dst, char *src, int buflen) {        dst[buflen - 1] = 0;        if (strlen(dst) + strlen(src) >= buflen) {                fprintf(stderr, "string buffer overflow (max %d): '%s' + '%s'"                        "\n", buflen, dst, src);                exit(EOVERFLOW);        }        return strcat(dst, src);}char *strscpy(char *dst, char *src, int buflen) {        dst[0] = 0;        return strscat(dst, src, buflen);}inline unsigned intdev_major (unsigned long long int __dev){        return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);}inline unsigned intdev_minor (unsigned long long int __dev){        return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);}int get_os_version(){        static int version = 0;        if (!version) {                int fd;                char release[4] = "";                fd = open("/proc/sys/kernel/osrelease", O_RDONLY);                if (fd < 0)                        fprintf(stderr, "%s: Warning: Can't resolve kernel "                                "version, assuming 2.6\n", progname);                else {                        read(fd, release, 4);                        close(fd);                }                if (strncmp(release, "2.4.", 4) == 0)                        version = 24;                else                        version = 26;        }        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;        struct mntent *mnt;        fp = setmntent(MOUNTED, "r");        if (fp == NULL)                return(0);        while ((mnt = getmntent(fp)) != NULL) {                if (strcmp(mnt->mnt_fsname, spec) == 0) {                        endmntent(fp);                        fprintf(stderr, "%s: according to %s %s is "                                "already mounted on %s\n",                                progname, MOUNTED, spec, mnt->mnt_dir);                        return(EEXIST);                }        }        endmntent(fp);        return(0);}/*============ disk dev functions ===================*//* Setup a file in the first unused loop_device */int loop_setup(struct mkfs_opts *mop){        char loop_base[20];        char l_device[64];        int i,ret = 0;        /* Figure out the loop device names */        if (!access("/dev/loop0", F_OK | R_OK))                strcpy(loop_base, "/dev/loop\0");        else if (!access("/dev/loop/0", F_OK | R_OK))                strcpy(loop_base, "/dev/loop/\0");        else {                fprintf(stderr, "%s: can't access loop devices\n", progname);                return EACCES;        }        /* Find unused loop device */        for (i = 0; i < MAX_LOOP_DEVICES; i++) {                char cmd[PATH_MAX];                int cmdsz = sizeof(cmd);                sprintf(l_device, "%s%d", loop_base, i);                if (access(l_device, F_OK | R_OK))                        break;                snprintf(cmd, cmdsz, "losetup %s > /dev/null 2>&1", l_device);                ret = system(cmd);                /* losetup gets 1 (ret=256) for non-set-up device */                if (ret) {                        /* Set up a loopback device to our file */                        snprintf(cmd, cmdsz, "losetup %s %s", l_device,                                 mop->mo_device);                        ret = run_command(cmd, cmdsz);                        if (ret) {                                fprintf(stderr, "%s: error %d on losetup: %s\n",                                        progname, ret, strerror(ret));                                return ret;                        }                        strscpy(mop->mo_loopdev, l_device,                                sizeof(mop->mo_loopdev));                        return ret;                }        }        fprintf(stderr, "%s: out of loop devices!\n", progname);        return EMFILE;}int loop_cleanup(struct mkfs_opts *mop){        char cmd[150];        int ret = 1;        if ((mop->mo_flags & MO_IS_LOOP) && *mop->mo_loopdev) {                sprintf(cmd, "losetup -d %s", mop->mo_loopdev);                ret = run_command(cmd, sizeof(cmd));        }        return ret;}/* Determine if a device is a block device (as opposed to a file) */int is_block(char* devname){        struct stat st;        int ret = 0;        ret = access(devname, F_OK);        if (ret != 0)                return 0;        ret = stat(devname, &st);        if (ret != 0) {                fprintf(stderr, "%s: cannot stat %s\n", progname, devname);                return -1;        }        return S_ISBLK(st.st_mode);}__u64 get_device_size(char* device){        int ret, fd;        __u64 size = 0;        fd = open(device, O_RDONLY);        if (fd < 0) {                fprintf(stderr, "%s: cannot open %s: %s\n",                        progname, device, strerror(errno));                return 0;        }#ifdef BLKGETSIZE64        /* size in bytes. bz5831 */        ret = ioctl(fd, BLKGETSIZE64, (void*)&size);#else        {                __u32 lsize = 0;                /* size in blocks */                ret = ioctl(fd, BLKGETSIZE, (void*)&lsize);                size = (__u64)lsize * 512;        }#endif        close(fd);        if (ret < 0) {                fprintf(stderr, "%s: size ioctl failed: %s\n",                        progname, strerror(errno));                return 0;        }        vprint("device size = "LPU64"MB\n", size >> 20);        /* return value in KB */        return size >> 10;}int loop_format(struct mkfs_opts *mop){        int ret = 0;        if (mop->mo_device_sz == 0) {                fatal();                fprintf(stderr, "loop device requires a --device-size= "                        "param\n");                return EINVAL;        }        ret = creat(mop->mo_device, S_IRUSR|S_IWUSR);        ret = truncate(mop->mo_device, mop->mo_device_sz * 1024);        if (ret != 0) {                ret = errno;                fprintf(stderr, "%s: Unable to create backing store: %d\n",                        progname, ret);        }        return ret;}/* Display the need for the latest e2fsprogs to be installed. make_backfs * indicates if the caller is make_lustre_backfs() or not. */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);                return;        }        msg_displayed++;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?