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 + -
显示快捷键?