#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_device[128]; /* disk device name or ZFS pool name */
+ char **mo_pool_vdevs; /* list of pool vdevs */
char mo_mkfsopts[128]; /* options to the backing-store mkfs */
char mo_loopdev[128]; /* in case a loop dev is needed */
+ char mo_osname[256]; /* ZFS objset name */
__u64 mo_device_sz; /* in KB */
int mo_stripe_count;
int mo_flags;
static int print_only = 0;
static int failover = 0;
static int upgrade_to_18 = 0;
+static int force_zpool = 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, "usage: %s <target types> [--backfstype=zfs] [options] "
+ "<pool name> [[<vdev type>] <device> [<device> ...] "
+ "[[vdev type>] ...]]\n", progname);
+ fprintf(out, "usage: %s <target types> --backfstype=ext3|ldiskfs "
+ "[options] <device>\n", progname);
fprintf(out,
"\t<device>:block device or file (e.g /dev/sda or /tmp/ost1)\n"
+ "\t<pool name>: name of the new ZFS pool. It can also be an "
+ "existing pool, in which case you should not provide a list "
+ "of devices.\n"
+ "\t<vdev type>: type of vdev (mirror, raidz, raidz2, spare, "
+ "cache, log)\n"
+ "\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--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--backfstype=<fstype> : backing fs type (zfs, 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--force-create : force the creation of a ZFS pool\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
}
/* Check whether the file exists in the device */
+#ifndef TUNEFS
static int file_in_dev(char *file_name, char *dev_name)
{
FILE *fp;
vprint("checking for existing Lustre data: ");
+ if (mop->mo_ldd.ldd_mount_type == LDD_MT_ZFS) {
+ vprint("WARNING: this functionality is currently disabled.\n");
+ return 0;
+ }
+
if ((rc = file_in_dev(MOUNT_DATA_FILE, mop->mo_device))) {
vprint("found %s\n",
(rc == 1) ? MOUNT_DATA_FILE : "extents");
vprint("not found\n");
return 0; /* The device is not a lustre target. */
}
+#endif
/* Check if a certain feature is supported by e2fsprogs.
* Firstly we try to use "debugfs supported_features" command to check if
}
snprintf(mkfs_cmd, sizeof(mkfs_cmd), "mkreiserfs -ff ");
} else if (mop->mo_ldd.ldd_mount_type == LDD_MT_ZFS) {
- snprintf(mkfs_cmd, sizeof(mkfs_cmd), "echo ");
+ if (mop->mo_pool_vdevs != NULL) {
+ /* We are creating a new ZFS pool */
+ snprintf(mkfs_cmd, sizeof(mkfs_cmd),
+ "zpool create %s%s", force_zpool ? "-f " : "",
+ mop->mo_device);
+
+ /* Add the vdevs to the cmd line */
+ while (*mop->mo_pool_vdevs != NULL) {
+ strscat(mkfs_cmd, " ", sizeof(mkfs_cmd));
+ strscat(mkfs_cmd, *mop->mo_pool_vdevs,
+ sizeof(mkfs_cmd));
+ mop->mo_pool_vdevs++; /* point to next vdev */
+ }
+
+ vprint("\ncreating ZFS pool '%s'...\n", mop->mo_device);
+ vprint("zpool_cmd = '%s'\n", mkfs_cmd);
+
+ ret = run_command(mkfs_cmd, sizeof(mkfs_cmd));
+ if (ret) {
+ fatal();
+ fprintf(stderr, "Unable to create pool '%s' "
+ "(%d)\n", mop->mo_device, ret);
+ return ret;
+ }
+ }
+
+retry:
+ snprintf(mop->mo_osname, sizeof(mop->mo_osname), "%s/%s",
+ mop->mo_device, mop->mo_ldd.ldd_svname);
+
+ /* Create the ZFS filesystem */
+ snprintf(mkfs_cmd, sizeof(mkfs_cmd), "zfs create%s%s %s",
+ mop->mo_mkfsopts[0] ? " -o " : "", mop->mo_mkfsopts,
+ mop->mo_osname);
+
+ vprint("\ncreating ZFS filesystem \"%s\"...\n", mop->mo_osname);
+ vprint("zfs_cmd = \"%s\"\n", mkfs_cmd);
+
+ ret = run_command_err(mkfs_cmd, sizeof(mkfs_cmd),
+ mop->mo_ldd.ldd_flags & LDD_F_NEED_INDEX ?
+ "dataset already exists" : NULL);
+
+ if (ret == -2 && mop->mo_ldd.ldd_flags & LDD_F_NEED_INDEX) {
+ vprint("Dataset \"%s\" already exists, retrying with "
+ "higher index.\n", mop->mo_osname);
+ /* Dataset already exists.
+ Increase svindex and retry */
+ mop->mo_ldd.ldd_svindex++;
+ server_make_name(mop->mo_ldd.ldd_flags,
+ mop->mo_ldd.ldd_svindex,
+ mop->mo_ldd.ldd_fsname,
+ mop->mo_ldd.ldd_svname);
+ goto retry;
+ }
+
+ if (ret) {
+ fatal();
+ fprintf(stderr, "Unable to create filesystem %s (%d)\n",
+ mop->mo_osname, ret);
+ return ret;
+ }
+
+ goto skip_format;
} else {
fprintf(stderr,"%s: unsupported fs type: %d (%s)\n",
progname, mop->mo_ldd.ldd_mount_type,
fatal();
fprintf(stderr, "Unable to build fs %s (%d)\n", dev, ret);
}
+
+skip_format:
return ret;
}
{
printf("\n %s:\n", str);
printf("Target: %s\n", ldd->ldd_svname);
- if (ldd->ldd_svindex == INDEX_UNASSIGNED)
+ if (ldd->ldd_flags & LDD_F_NEED_INDEX)
printf("Index: unassigned\n");
else
printf("Index: %d\n", ldd->ldd_svindex);
FILE *filep;
int ret = 0;
- if (mop->mo_ldd.ldd_mount_type == LDD_MT_ZFS) {
- /* XXX: no LDD on ZFS yet */
- return 0;
- }
-
/* Mount this device temporarily in order to write these files */
if (!mkdtemp(mntpt)) {
fprintf(stderr, "%s: Can't create temp mount point %s: %s\n",
if (get_os_version() == 24)
mop->mo_ldd.ldd_mount_type = LDD_MT_EXT3;
else
- mop->mo_ldd.ldd_mount_type = LDD_MT_LDISKFS;
+ mop->mo_ldd.ldd_mount_type = LDD_MT_ZFS;
- mop->mo_ldd.ldd_svindex = INDEX_UNASSIGNED;
+ mop->mo_ldd.ldd_svindex = 0;
mop->mo_stripe_count = 1;
+ mop->mo_pool_vdevs = NULL;
}
static inline void badopt(const char *opt, char *type)
{"erase-params", 0, 0, 'e'},
{"failnode", 1, 0, 'f'},
{"failover", 1, 0, 'f'},
+ {"force-create", 0, 0, 'F'},
{"mgs", 0, 0, 'G'},
{"help", 0, 0, 'h'},
{"index", 1, 0, 'i'},
failover = 1;
break;
}
+ case 'F':
+ force_zpool = 1;
+ break;
case 'G':
mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MGS;
break;
}
}//while
- /* Last arg is device */
- if (optind != argc - 1) {
+ /* optind points to device or pool name */
+ strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device));
+
+ if (mop->mo_ldd.ldd_mount_type == LDD_MT_ZFS) {
+ /* Common mistake: user gave device name instead of pool name */
+ if (mop->mo_device[0] == '/') {
+ fatal();
+ fprintf(stderr, "Pool name cannot start with '/': %s\n"
+ "Please run '%s --help' for syntax help.\n",
+ mop->mo_device, progname);
+ return EINVAL;
+ }
+ /* next index (if existent) points to vdevs */
+ if (optind < argc - 1)
+ mop->mo_pool_vdevs = (char **) &argv[optind + 1];
+ } else if (optind != argc - 1) {
+ /* For non-ZFS backfs, last arg must be the device */
fatal();
fprintf(stderr, "Bad argument: %s\n", argv[optind]);
return EINVAL;
memset(&mop, 0, sizeof(mop));
set_defaults(&mop);
- /* device is last arg */
- strscpy(mop.mo_device, argv[argc - 1], sizeof(mop.mo_device));
-
- /* Are we using a loop device? */
- ret = is_block(mop.mo_device);
- if (ret < 0)
- goto out;
- if (ret == 0)
- mop.mo_flags |= MO_IS_LOOP;
-
#ifdef TUNEFS
+ fatal();
+ fprintf(stderr, "%s is non-functional in this release.\n", progname);
+ ret = EINVAL;
+ goto out;
+#if 0
/* For tunefs, we must read in the old values before parsing any
new ones. */
if (verbose > 0)
print_ldd("Read previous values", &(mop.mo_ldd));
#endif
+#endif
ret = parse_opts(argc, argv, &mop, &mountopts);
if (ret)
case LDD_MT_EXT3:
case LDD_MT_LDISKFS:
case LDD_MT_LDISKFS2: {
+ /* Are we using a loop device? */
+ ret = is_block(mop.mo_device);
+ if (ret < 0)
+ goto out;
+ if (ret == 0)
+ mop.mo_flags |= MO_IS_LOOP;
+
sprintf(always_mountopts, "errors=remount-ro");
if (IS_MDT(ldd) || IS_MGS(ldd))
strscat(always_mountopts, ",iopen_nopriv,user_xattr",
mop.mo_device);
break;
}
- case LDD_MT_ZFS: {
+ case LDD_MT_ZFS:
break;
- }
default: {
fatal();
fprintf(stderr, "unknown fs type %d '%s'\n",
goto out;
}
- if (check_mtab_entry(mop.mo_device))
+ if (ldd->ldd_mount_type != LDD_MT_ZFS &&
+ check_mtab_entry(mop.mo_device))
return(EEXIST);
/* Create the loopback file */
- if (mop.mo_flags & MO_IS_LOOP) {
+ if (ldd->ldd_mount_type != LDD_MT_ZFS && mop.mo_flags & MO_IS_LOOP) {
ret = access(mop.mo_device, F_OK);
if (ret)
ret = errno;
}
#endif
- /* Write our config files */
- ret = write_local_files(&mop);
- if (ret != 0) {
- fatal();
- fprintf(stderr, "failed to write local files\n");
- goto out;
+ if (ldd->ldd_mount_type != LDD_MT_ZFS) {
+ /* Write our config files */
+ ret = write_local_files(&mop);
+ if (ret != 0) {
+ fatal();
+ fprintf(stderr, "failed to write local files\n");
+ goto out;
+ }
}
out: