void print_ldd(char *str, struct lustre_disk_data *ldd) { printf("\n %s:\n", str); printf("Target: %s\n", ldd->ldd_svname); if (ldd->ldd_svindex == INDEX_UNASSIGNED) printf("Index: unassigned\n"); else printf("Index: %d\n", ldd->ldd_svindex); if (ldd->ldd_uuid[0]) printf("UUID: %s\n", (char *)ldd->ldd_uuid); 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%s)\n", IS_MDT(ldd) ? "MDT ":"", IS_OST(ldd) ? "OST ":"", IS_MGS(ldd) ? "MGS ":"", ldd->ldd_flags & LDD_F_NEED_INDEX ? "needs_index ":"", 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_NO_PRIMNODE? "no_primnode ":"", 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); if (ldd->ldd_userdata[0]) printf("Comment: %s\n", ldd->ldd_userdata); printf("\n"); }
void register_service_tags(char *usource, char *source, char *target) { struct lustre_disk_data mo_ldd; struct utsname utsname_buf; struct stat stat_buf; char stclient_loc[] = "/opt/sun/servicetag/bin/stclient"; int rc; rc = stat(stclient_loc, &stat_buf); if (rc) { if (errno != ENOENT && verbose) { fprintf(stderr, "%s: trying to stat stclient failed: %s\n", progname, strerror(errno)); } return; } /* call service tags stclient to show Lustre is in use on this system */ rc = uname(&utsname_buf); if (rc) { if (verbose) fprintf(stderr, "%s: trying to get uname failed: %s, " "inventory tags will not be created\n", progname, strerror(errno)); return; } /* client or server? */ if (strchr(usource, ':')) { stclient("Client", utsname_buf.machine); } else { /* first figure what type of device it is */ rc = get_mountdata(source, &mo_ldd); if (rc) { if (verbose) fprintf(stderr, "%s: trying to read mountdata from %s " "failed: %s, inventory tags will not " "be created\n", progname, target, strerror(errno)); return; } if (IS_MDT(&mo_ldd)) stclient("MDS", utsname_buf.machine); if (IS_MGS(&mo_ldd)) stclient("MGS", utsname_buf.machine); if (IS_OST(&mo_ldd)) stclient("OSS", utsname_buf.machine); } }
int ldiskfs_prepare_lustre(struct mkfs_opts *mop, char *wanted_mountopts, size_t len) { struct lustre_disk_data *ldd = &mop->mo_ldd; int ret; /* Set MO_IS_LOOP to indicate a loopback device is needed */ ret = is_block(mop->mo_device); if (ret < 0) { return errno; } else if (ret == 0) { mop->mo_flags |= MO_IS_LOOP; } if (IS_MDT(ldd) || IS_MGS(ldd)) strscat(wanted_mountopts, ",user_xattr", len); return 0; }
static int parse_ldd(char *source, struct mount_opts *mop, char *options) { struct lustre_disk_data *ldd = &mop->mo_ldd; char *cur, *start; int rc; rc = osd_is_lustre(source, &ldd->ldd_mount_type); if (rc == 0) { fprintf(stderr, "%s: %s has not been formatted with mkfs.lustre" " or the backend filesystem type is not supported by " "this tool\n", progname, source); return ENODEV; } rc = osd_read_ldd(source, ldd); if (rc) { fprintf(stderr, "%s: %s failed to read permanent mount" " data: %s\n", progname, source, rc >= 0 ? strerror(rc) : ""); return rc; } if ((IS_MDT(ldd) || IS_OST(ldd)) && (ldd->ldd_flags & LDD_F_NEED_INDEX)) { fprintf(stderr, "%s: %s has no index assigned " "(probably formatted with old mkfs)\n", progname, source); return EINVAL; } if (ldd->ldd_flags & LDD_F_UPGRADE14) { fprintf(stderr, "%s: we cannot upgrade %s from this (very old) " "Lustre version\n", progname, source); return EINVAL; } if (ldd->ldd_flags & LDD_F_UPDATE) clear_update_ondisk(source, ldd); /* Since we never rewrite ldd, ignore temp flags */ ldd->ldd_flags &= ~(LDD_F_VIRGIN | LDD_F_WRITECONF); /* svname of the form lustre:OST1234 means never registered */ rc = strlen(ldd->ldd_svname); if (strcmp(ldd->ldd_svname, "MGS") != 0) { if (rc < 8) { fprintf(stderr, "%s: invalid name '%s'\n", progname, ldd->ldd_svname); return EINVAL; } else if (ldd->ldd_svname[rc - 8] == ':') { ldd->ldd_svname[rc - 8] = '-'; ldd->ldd_flags |= LDD_F_VIRGIN; } else if (ldd->ldd_svname[rc - 8] == '=') { ldd->ldd_svname[rc - 8] = '-'; ldd->ldd_flags |= LDD_F_WRITECONF; } } /* backend osd type */ append_option(options, "osd="); strcat(options, mt_type(ldd->ldd_mount_type)); append_option(options, ldd->ldd_mount_opts); if (!mop->mo_have_mgsnid) { /* Only use disk data if mount -o mgsnode=nid wasn't * specified */ if (ldd->ldd_flags & LDD_F_SV_TYPE_MGS) { append_option(options, "mgs"); mop->mo_have_mgsnid++; } else { add_mgsnids(mop, options, ldd->ldd_params); } } /* Better have an mgsnid by now */ if (!mop->mo_have_mgsnid) { fprintf(stderr, "%s: missing option mgsnode=<nid>\n", progname); return EINVAL; } if (ldd->ldd_flags & LDD_F_VIRGIN) append_option(options, "virgin"); if (ldd->ldd_flags & LDD_F_UPDATE) append_option(options, "update"); if (ldd->ldd_flags & LDD_F_WRITECONF) append_option(options, "writeconf"); if (ldd->ldd_flags & LDD_F_NO_PRIMNODE) append_option(options, "noprimnode"); /* prefix every lustre parameter with param= so that in-kernel * mount can recognize them properly and send to MGS at registration */ start = ldd->ldd_params; while (start && *start != '\0') { while (*start == ' ') start++; if (*start == '\0') break; cur = start; start = strchr(cur, ' '); if (start) { *start = '\0'; start++; } append_option(options, "param="); strcat(options, cur); } /* svname must be last option */ append_option(options, "svname="); strcat(options, ldd->ldd_svname); return 0; }
/* Build fs according to type */ int ldiskfs_make_lustre(struct mkfs_opts *mop) { char mkfs_cmd[PATH_MAX]; char buf[64]; char *start; char *dev; int ret = 0, ext_opts = 0; bool enable_64bit = false; long inode_size = 0; size_t maxbuflen; mop->mo_blocksize_kb = 4; start = strstr(mop->mo_mkfsopts, "-b"); if (start) { char *end = NULL; long blocksize; blocksize = strtol(start + 2, &end, 0); if (end && (*end == 'k' || *end == 'K')) blocksize *= 1024; /* EXT4_MIN_BLOCK_SIZE || EXT4_MAX_BLOCK_SIZE */ if (blocksize < 1024 || blocksize > 65536) { fprintf(stderr, "%s: blocksize %lu not in 1024-65536 bytes, normally 4096 bytes\n", progname, blocksize); return EINVAL; } if ((blocksize & (blocksize - 1)) != 0) { fprintf(stderr, "%s: blocksize %lu not a power-of-two value\n", progname, blocksize); return EINVAL; } mop->mo_blocksize_kb = blocksize >> 10; } if (!(mop->mo_flags & MO_IS_LOOP)) { __u64 device_kb = get_device_size(mop->mo_device); if (device_kb == 0) return ENODEV; /* Compare to real size */ if (mop->mo_device_kb == 0 || device_kb < mop->mo_device_kb) mop->mo_device_kb = device_kb; } if (mop->mo_device_kb != 0) { __u64 block_count; if (mop->mo_device_kb < 32384) { fprintf(stderr, "%s: size of filesystem must be larger " "than 32MB, but is set to %lldKB\n", progname, (long long)mop->mo_device_kb); return EINVAL; } block_count = mop->mo_device_kb / mop->mo_blocksize_kb; if (block_count > 0xffffffffULL) { /* If the LUN size is just over 2^32 blocks, limit the * filesystem size to 2^32-1 blocks to avoid problems * with ldiskfs/mkfs not handling this well. b=22906 */ if (block_count < 0x100002000ULL) mop->mo_device_kb = 0xffffffffULL * mop->mo_blocksize_kb; else enable_64bit = true; } } 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)) { fprintf(stderr, "%s: unsupported fs type: %d (%s)\n", progname, mop->mo_ldd.ldd_mount_type, MT_STR(&mop->mo_ldd)); return EINVAL; } /* Journal size in MB */ if (strstr(mop->mo_mkfsopts, "-J") == NULL && mop->mo_device_kb > 1024 * 1024) { /* Choose our own default journal size */ long journal_mb = 0, max_mb; /* cap journal size at 4GB for MDT, leave at 1GB for OSTs */ if (IS_MDT(&mop->mo_ldd)) max_mb = 4096; else if (IS_OST(&mop->mo_ldd)) max_mb = 1024; else /* Use mke2fs default size for MGS */ max_mb = 0; /* Use at most 4% of device for journal */ journal_mb = mop->mo_device_kb * 4 / (1024 * 100); if (journal_mb > max_mb) journal_mb = max_mb; if (journal_mb) { snprintf(buf, sizeof(buf), " -J size=%ld", journal_mb); strscat(mop->mo_mkfsopts, buf, sizeof(mop->mo_mkfsopts)); } } /* * The inode size is constituted by following elements * (assuming all files are in composite layout and has * 3 components): * * ldiskfs inode size: 160 * MDT extended attributes size, including: * ext4_xattr_header: 32 * LOV EA size: 32(lov_comp_md_v1) + * 3 * 40(lov_comp_md_entry_v1) + * 3 * 32(lov_mds_md) + * stripes * 24(lov_ost_data) + * 16(xattr_entry) + 4("lov") * LMA EA size: 24(lustre_mdt_attrs) + * 16(xattr_entry) + 4("lma") * SOM EA size: 24(lustre_som_attrs) + * 16(xattr_entry) + 4("som") * link EA size: 24(link_ea_header) + 18(link_ea_entry) + * 16(filename) + 16(xattr_entry) + 4("link") * and some margin for 4-byte alignment, ACLs and other EAs. * * If we say the average filename length is about 32 bytes, * the calculation looks like: * 160 + 32 + (32+3*(40+32)+24*stripes+20) + (24+20) + (24+20) + * (24+20) + (~42+16+20) + other <= 512*2^m, {m=0,1,2,3} */ if (strstr(mop->mo_mkfsopts, "-I") == NULL) { if (IS_MDT(&mop->mo_ldd)) { if (mop->mo_stripe_count > 59) inode_size = 512; /* bz 7241 */ /* see also "-i" below for EA blocks */ else if (mop->mo_stripe_count > 16) inode_size = 2048; else inode_size = 1024; } else if (IS_OST(&mop->mo_ldd)) { /* We store MDS FID and necessary composite * layout information in the OST object EA: * ldiskfs inode size: 160 * OST extended attributes size, including: * ext4_xattr_header: 32 * LMA EA size: 24(lustre_mdt_attrs) + * 16(xattr_entry) + 4("lma") * FID EA size: 52(filter_fid) + * 16(xattr_entry) + 4("fid") * 160 + 32 + (24+20) + (52+20) = 308 */ inode_size = 512; } if (inode_size > 0) { snprintf(buf, sizeof(buf), " -I %ld", inode_size); strscat(mop->mo_mkfsopts, buf, sizeof(mop->mo_mkfsopts)); } } /* Bytes_per_inode: disk size / num inodes */ if (strstr(mop->mo_mkfsopts, "-i") == NULL && strstr(mop->mo_mkfsopts, "-N") == NULL) { long bytes_per_inode = 0; /* Allocate more inodes on MDT devices. There is * no data stored on the MDT, and very little extra * metadata beyond the inode. It could go down as * low as 1024 bytes, but this is conservative. * Account for external EA blocks for wide striping. */ if (IS_MDT(&mop->mo_ldd)) { bytes_per_inode = inode_size + 1536; if (mop->mo_stripe_count > 59) { int extra = mop->mo_stripe_count * 24; extra = ((extra - 1) | 4095) + 1; bytes_per_inode += extra; } } /* Allocate fewer inodes on large OST devices. Most * filesystems can be much more aggressive than even * this, but it is impossible to know in advance. */ if (IS_OST(&mop->mo_ldd)) { /* OST > 16TB assume average file size 1MB */ if (mop->mo_device_kb > (16ULL << 30)) bytes_per_inode = 1024 * 1024; /* OST > 4TB assume average file size 512kB */ else if (mop->mo_device_kb > (4ULL << 30)) bytes_per_inode = 512 * 1024; /* OST > 1TB assume average file size 256kB */ else if (mop->mo_device_kb > (1ULL << 30)) bytes_per_inode = 256 * 1024; /* OST > 10GB assume average file size 64kB, * plus a bit so that inodes will fit into a * 256x flex_bg without overflowing. */ else if (mop->mo_device_kb > (10ULL << 20)) bytes_per_inode = 69905; } if (bytes_per_inode > 0) { snprintf(buf, sizeof(buf), " -i %ld", bytes_per_inode); strscat(mop->mo_mkfsopts, buf, sizeof(mop->mo_mkfsopts)); mop->mo_inode_size = bytes_per_inode; } } if (verbose < 2) strscat(mop->mo_mkfsopts, " -q", sizeof(mop->mo_mkfsopts)); /* start handle -O mkfs options */ start = strstr(mop->mo_mkfsopts, "-O"); if (start) { if (strstr(start + 2, "-O") != NULL) { fprintf(stderr, "%s: don't specify multiple -O options\n", progname); return EINVAL; } start = moveopts_to_end(start); maxbuflen = sizeof(mop->mo_mkfsopts) - (start - mop->mo_mkfsopts) - strlen(start); 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); ret = enable_default_ext4_features(mop, start, maxbuflen, 0); } if (ret) return ret; /* end handle -O mkfs options */ /* start handle -E mkfs options */ start = strstr(mop->mo_mkfsopts, "-E"); if (start) { if (strstr(start + 2, "-E") != NULL) { fprintf(stderr, "%s: don't specify multiple -E options\n", progname); return EINVAL; } start = moveopts_to_end(start); maxbuflen = sizeof(mop->mo_mkfsopts) - (start - mop->mo_mkfsopts) - strlen(start); ext_opts = 1; } else { start = mop->mo_mkfsopts + strlen(mop->mo_mkfsopts); maxbuflen = sizeof(mop->mo_mkfsopts) - strlen(mop->mo_mkfsopts); } /* In order to align the filesystem metadata on 1MB boundaries, * give a resize value that will reserve a power-of-two group * descriptor blocks, but leave one block for the superblock. * Only useful for filesystems with < 2^32 blocks due to resize * limitations. */ if (!enable_64bit && strstr(mop->mo_mkfsopts, "meta_bg") == NULL && IS_OST(&mop->mo_ldd) && mop->mo_device_kb > 100 * 1024) { unsigned int group_blocks = mop->mo_blocksize_kb * 8192; unsigned int desc_per_block = mop->mo_blocksize_kb * 1024 / 32; unsigned int resize_blks; resize_blks = (1ULL<<32) - desc_per_block*group_blocks; snprintf(buf, sizeof(buf), "%u", resize_blks); append_unique(start, ext_opts ? "," : " -E ", "resize", buf, maxbuflen); ext_opts = 1; } /* Avoid zeroing out the full journal - speeds up mkfs */ if (is_e2fsprogs_feature_supp("-E lazy_journal_init")) append_unique(start, ext_opts ? "," : " -E ", "lazy_journal_init", NULL, maxbuflen); /* end handle -E mkfs options */ /* Allow reformat of full devices (as opposed to partitions). * We already checked for mounted dev. */ strscat(mop->mo_mkfsopts, " -F", sizeof(mop->mo_mkfsopts)); snprintf(mkfs_cmd, sizeof(mkfs_cmd), "%s -j -b %d -L %s ", MKE2FS, mop->mo_blocksize_kb * 1024, mop->mo_ldd.ldd_svname); /* For loop device format the dev, not the filename */ dev = mop->mo_device; if (mop->mo_flags & MO_IS_LOOP) dev = mop->mo_loopdev; 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("\tkilobytes %llu\n", mop->mo_device_kb); vprint("\toptions %s\n", mop->mo_mkfsopts); /* mkfs_cmd's trailing space is important! */ strscat(mkfs_cmd, mop->mo_mkfsopts, sizeof(mkfs_cmd)); strscat(mkfs_cmd, " ", sizeof(mkfs_cmd)); strscat(mkfs_cmd, dev, sizeof(mkfs_cmd)); if (mop->mo_device_kb != 0) { snprintf(buf, sizeof(buf), " %lluk", (unsigned long long)mop->mo_device_kb); strscat(mkfs_cmd, buf, sizeof(mkfs_cmd)); } vprint("mkfs_cmd = %s\n", mkfs_cmd); ret = run_command(mkfs_cmd, sizeof(mkfs_cmd)); if (ret) { fatal(); fprintf(stderr, "Unable to build fs %s (%d)\n", dev, ret); } return ret; }
static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, size_t maxbuflen, bool user_spec) { unsigned long long blocks = mop->mo_device_kb / mop->mo_blocksize_kb; bool enable_64bit = false; /* Enable large block addresses if the LUN is over 2^32 blocks. */ if (blocks > 0xffffffffULL && is_e2fsprogs_feature_supp("-O 64bit")) enable_64bit = true; if (IS_OST(&mop->mo_ldd)) { append_unique(anchor, user_spec ? "," : " -O ", "extents", NULL, maxbuflen); append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen); } else if (IS_MDT(&mop->mo_ldd)) { append_unique(anchor, user_spec ? "," : " -O ", "dirdata", NULL, maxbuflen); append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen); if (enable_64bit) append_unique(anchor, ",", "extents", NULL, maxbuflen); else append_unique(anchor, ",", "^extents", NULL, maxbuflen); } else { append_unique(anchor, user_spec ? "," : " -O ", "uninit_bg", NULL, maxbuflen); } /* Multiple mount protection enabled only if failover node specified */ if (mop->mo_flags & MO_FAILOVER) { if (is_e2fsprogs_feature_supp("-O mmp")) append_unique(anchor, ",", "mmp", NULL, maxbuflen); else disp_old_e2fsprogs_msg("mmp", 1); } /* Allow more than 65000 subdirectories */ if (is_e2fsprogs_feature_supp("-O dir_nlink")) append_unique(anchor, ",", "dir_nlink", NULL, maxbuflen); /* 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 0; /* Enable quota by default */ if (is_e2fsprogs_feature_supp("-O quota")) { 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")) append_unique(anchor, ",", "huge_file", NULL, maxbuflen); if (enable_64bit) append_unique(anchor, ",", "64bit", NULL, maxbuflen); if (blocks >= 0x1000000000 && is_e2fsprogs_feature_supp("-O meta_bg")) append_unique(anchor, ",", "meta_bg", NULL, maxbuflen); if (enable_64bit || strstr(mop->mo_mkfsopts, "meta_bg")) append_unique(anchor, ",", "^resize_inode", NULL, maxbuflen); /* Cluster inode/block bitmaps and inode table for more efficient IO. * Align the flex groups on a 1MB boundary for better performance. */ /* This -O feature needs to go last, since it adds the "-G" option. */ if (is_e2fsprogs_feature_supp("-O flex_bg")) { char tmp_buf[64]; append_unique(anchor, ",", "flex_bg", NULL, maxbuflen); if (IS_OST(&mop->mo_ldd) && strstr(mop->mo_mkfsopts, "-G") == NULL) { snprintf(tmp_buf, sizeof(tmp_buf), " -G %u", 1024 / mop->mo_blocksize_kb); strscat(anchor, tmp_buf, maxbuflen); } } /* Don't add any more "-O" options here, see last comment above */ return 0; }
int main(int argc, char *const argv[]) { struct mkfs_opts mop; struct lustre_disk_data *ldd = &mop.mo_ldd; char *mountopts = NULL; char wanted_mountopts[512] = ""; unsigned mount_type; int ret = 0; int ret2 = 0; progname = strrchr(argv[0], '/'); if (progname != NULL) progname++; else progname = argv[0]; if ((argc < 2) || (argv[argc - 1][0] == '-')) { usage(stderr); 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)); ret = osd_init(); if (ret != 0) return ret; #ifdef TUNEFS /* For tunefs, we must read in the old values before parsing any new ones. */ /* Check whether the disk has already been formatted by mkfs.lustre */ ret = osd_is_lustre(mop.mo_device, &mount_type); if (ret == 0) { fatal(); fprintf(stderr, "Device %s has not been formatted with " "mkfs.lustre\n", mop.mo_device); ret = ENODEV; goto out; } ldd->ldd_mount_type = mount_type; ret = osd_read_ldd(mop.mo_device, ldd); if (ret != 0) { fatal(); fprintf(stderr, "Failed to read previous Lustre data from %s " "(%d)\n", mop.mo_device, ret); goto out; } ldd->ldd_flags &= ~(LDD_F_WRITECONF | LDD_F_VIRGIN); /* svname of the form lustre:OST1234 means never registered */ ret = strlen(ldd->ldd_svname); if (ldd->ldd_svname[ret - 8] == ':') { ldd->ldd_svname[ret - 8] = '-'; ldd->ldd_flags |= LDD_F_VIRGIN; } else if (ldd->ldd_svname[ret - 8] == '=') { ldd->ldd_svname[ret - 8] = '-'; ldd->ldd_flags |= LDD_F_WRITECONF; } if (strstr(ldd->ldd_params, PARAM_MGSNODE)) mop.mo_mgs_failnodes++; if (verbose > 0) print_ldd("Read previous values", ldd); #endif /* TUNEFS */ ret = parse_opts(argc, argv, &mop, &mountopts); if (ret != 0 || version) goto out; if (!IS_MDT(ldd) && !IS_OST(ldd) && !IS_MGS(ldd)) { fatal(); fprintf(stderr, "must set target type: MDT,OST,MGS\n"); ret = EINVAL; goto out; } if (((IS_MDT(ldd) || IS_MGS(ldd))) && IS_OST(ldd)) { fatal(); fprintf(stderr, "OST type is exclusive with MDT,MGS\n"); ret = EINVAL; goto out; } /* Stand alone MGS doesn't need an index */ if (!IS_MDT(ldd) && IS_MGS(ldd)) { #ifndef TUNEFS /* But if --index was specified flag an error */ if (!(ldd->ldd_flags & LDD_F_NEED_INDEX)) { badopt("index", "MDT,OST"); goto out; } #endif ldd->ldd_flags &= ~LDD_F_NEED_INDEX; } if ((ldd->ldd_flags & (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) == (LDD_F_NEED_INDEX | LDD_F_UPGRADE14)) { fatal(); fprintf(stderr, "Can't find the target index, " "specify with --index\n"); ret = EINVAL; goto out; } if (ldd->ldd_flags & LDD_F_NEED_INDEX) fprintf(stderr, "warning: %s: for Lustre 2.4 and later, the " "target index must be specified with --index\n", mop.mo_device); /* If no index is supplied for MDT by default set index to zero */ if (IS_MDT(ldd) && (ldd->ldd_svindex == INDEX_UNASSIGNED)) { ldd->ldd_flags &= ~LDD_F_NEED_INDEX; ldd->ldd_svindex = 0; } if (!IS_MGS(ldd) && (mop.mo_mgs_failnodes == 0)) { fatal(); if (IS_MDT(ldd)) fprintf(stderr, "Must specify --mgs or --mgsnode\n"); else fprintf(stderr, "Must specify --mgsnode\n"); ret = EINVAL; goto out; } if ((IS_MDT(ldd) || IS_OST(ldd)) && ldd->ldd_fsname[0] == '\0') { fatal(); fprintf(stderr, "Must specify --fsname for MDT/OST device\n"); ret = EINVAL; goto out; } /* These are the permanent mount options (always included) */ ret = osd_prepare_lustre(&mop, wanted_mountopts, sizeof(wanted_mountopts)); if (ret != 0) { fatal(); fprintf(stderr, "unable to prepare backend (%d)\n", ret); goto out; } if (mountopts) { trim_mountfsoptions(mountopts); if (check_mountfsoptions(mountopts, wanted_mountopts)) { ret = EINVAL; goto out; } snprintf(ldd->ldd_mount_opts, sizeof(ldd->ldd_mount_opts), "%s", mountopts); } else { #ifdef TUNEFS if (ldd->ldd_mount_opts[0] == 0) /* use the defaults unless old opts exist */ #endif { snprintf(ldd->ldd_mount_opts, sizeof(ldd->ldd_mount_opts), "%s", wanted_mountopts); trim_mountfsoptions(ldd->ldd_mount_opts); } } ret = osd_fix_mountopts(&mop, ldd->ldd_mount_opts, sizeof(ldd->ldd_mount_opts)); if (ret != 0) { fatal(); fprintf(stderr, "unable to fix mountfsoptions (%d)\n", ret); goto out; } server_make_name(ldd->ldd_flags, ldd->ldd_svindex, ldd->ldd_fsname, ldd->ldd_svname); if (verbose >= 0) print_ldd("Permanent disk data", ldd); if (print_only) { printf("exiting before disk write.\n"); goto out; } if (check_mtab_entry(mop.mo_device, mop.mo_device, NULL, NULL)) return(EEXIST); /* Create the loopback file */ if (mop.mo_flags & MO_IS_LOOP) { ret = access(mop.mo_device, F_OK); if (ret != 0) ret = errno; #ifndef TUNEFS /* Reformat the loopback file */ if (ret != 0 || (mop.mo_flags & MO_FORCEFORMAT)) { ret = loop_format(&mop); if (ret != 0) goto out; } #endif if (ret == 0) ret = loop_setup(&mop); if (ret != 0) { fatal(); fprintf(stderr, "Loop device setup for %s failed: %s\n", mop.mo_device, strerror(ret)); goto out; } } #ifndef TUNEFS /* Check whether the disk has already been formatted by mkfs.lustre */ if (!(mop.mo_flags & MO_FORCEFORMAT)) { ret = osd_is_lustre(mop.mo_device, &mount_type); if (ret != 0) { fatal(); fprintf(stderr, "Device %s was previously formatted " "for lustre. Use --reformat to reformat it, " "or tunefs.lustre to modify.\n", mop.mo_device); goto out; } } /* Format the backing filesystem */ ret = osd_make_lustre(&mop); if (ret != 0) { fatal(); fprintf(stderr, "mkfs failed %d\n", ret); goto out; } #else /* !TUNEFS */ /* update svname with '=' to refresh config */ if (ldd->ldd_flags & LDD_F_WRITECONF) { struct mount_opts opts; opts.mo_ldd = *ldd; opts.mo_source = mop.mo_device; (void) osd_label_lustre(&opts); } /* Enable quota accounting */ if (mop.mo_flags & MO_QUOTA) { ret = osd_enable_quota(&mop); goto out; } #endif /* !TUNEFS */ /* Write our config files */ ret = osd_write_ldd(&mop); if (ret != 0) { fatal(); fprintf(stderr, "failed to write local files\n"); goto out; } out: osd_fini(); ret2 = loop_cleanup(&mop); if (ret == 0) ret = ret2; /* Fix any crazy return values from system() */ if (ret != 0 && ((ret & 255) == 0)) return 1; if (ret != 0) verrprint("%s: exiting with %d (%s)\n", progname, ret, strerror(ret)); return ret; }
int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, char **mountopts) { static struct option long_opt[] = { { "backfs-mount-opts", required_argument, NULL, 'B' }, { "failnode", required_argument, NULL, 'f' }, { "failover", required_argument, NULL, 'f' }, { "help", no_argument, NULL, 'h' }, { "index", required_argument, NULL, 'i' }, { "fsname", required_argument, NULL, 'L' }, { "mgsnode", required_argument, NULL, 'm' }, { "mgsnid", required_argument, NULL, 'm' }, { "dryrun", no_argument, NULL, 'n' }, { "mountfsoptions", required_argument, NULL, 'o' }, { "param", required_argument, NULL, 'p' }, { "quiet", no_argument, NULL, 'q' }, { "servicenode", required_argument, NULL, 's' }, { "network", required_argument, NULL, 't' }, { "comment", required_argument, NULL, 'u' }, { "force-nohostid", no_argument, NULL, 'U' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, #ifndef TUNEFS { "backfstype", required_argument, NULL, 'b' }, { "stripe-count-hint", required_argument, NULL, 'c' }, { "device-size", required_argument, NULL, 'd' }, { "mgs", no_argument, NULL, 'G' }, { "mkfsoptions", required_argument, NULL, 'k' }, { "mdt", no_argument, NULL, 'M' }, { "nomgs", no_argument, NULL, 'N' }, { "ost", no_argument, NULL, 'O' }, { "reformat", no_argument, NULL, 'r' }, { "replace", no_argument, NULL, 'R' }, #else { "erase-params", no_argument, NULL, 'e' }, { "quota", no_argument, NULL, 'Q' }, { "writeconf", no_argument, NULL, 'w' }, #endif { 0, 0, NULL, 0 } }; char *optstring = "B:f:hi:L:m:no:p:qs:t:u:vV" #ifndef TUNEFS "b:c:d:Gk:MNOrR"; #else "eQw"; #endif struct lustre_disk_data *ldd = &mop->mo_ldd; char new_fsname[16] = { 0 }; int opt; int rc, longidx; int failnode_set = 0, servicenode_set = 0; int replace = 0; bool index_option = false; while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) != EOF) { switch (opt) { case 'B': mop->mo_mountopts = optarg; break; case 'f': case 's': { char *nids; if ((opt == 'f' && servicenode_set) || (opt == 's' && failnode_set)) { fprintf(stderr, "%s: %s cannot use with --%s\n", progname, long_opt[longidx].name, opt == 'f' ? "servicenode" : "failnode"); return 1; } nids = convert_hostnames(optarg); if (nids == NULL) return 1; rc = append_param(ldd->ldd_params, PARAM_FAILNODE, nids, ':'); free(nids); if (rc != 0) return rc; /* Must update the mgs logs */ ldd->ldd_flags |= LDD_F_UPDATE; if (opt == 'f') { failnode_set = 1; } else { ldd->ldd_flags |= LDD_F_NO_PRIMNODE; servicenode_set = 1; } mop->mo_flags |= MO_FAILOVER; break; } case 'h': usage(stdout); return 1; case 'i': { char *endptr = NULL; int base; index_option = true; /* LU-2374: check whether it is OST/MDT later */ base = (strlen(optarg) > 1 && !strncmp(optarg, "0x", 2)) ? 16 : 10; /* Allowed input are base 16 and base 10 numbers only */ mop->mo_ldd.ldd_svindex = strtoul(optarg, &endptr, base); if (*endptr != '\0') { fprintf(stderr, "%s: wrong index %s. " "Target index must be decimal or " "hexadecimal.\n", progname, optarg); return 1; } if (ldd->ldd_svindex >= INDEX_UNASSIGNED) { fprintf(stderr, "%s: wrong index %u. " "Target index must be less than %u.\n", progname, ldd->ldd_svindex, INDEX_UNASSIGNED); return 1; } ldd->ldd_flags &= ~LDD_F_NEED_INDEX; break; } case 'L': { rc = lustre_is_fsname_valid(optarg, 1, LUSTRE_MAXFSNAME); if (rc < 0) { fprintf(stderr, "%s: filesystem name must be " "1-%d chars\n", progname, LUSTRE_MAXFSNAME); return 1; } else if (rc > 0) { fprintf(stderr, "%s: char '%c' not allowed in " "filesystem name\n", progname, rc); return 1; } strscpy(new_fsname, optarg, sizeof(new_fsname)); break; } case 'm': { char *nids = convert_hostnames(optarg); if (nids == NULL) return 1; rc = append_param(ldd->ldd_params, PARAM_MGSNODE, nids, ':'); free(nids); if (rc != 0) return rc; mop->mo_mgs_failnodes++; break; } case 'n': print_only++; break; case 'o': *mountopts = optarg; break; case 'p': rc = add_param(ldd->ldd_params, NULL, optarg); if (rc != 0) return rc; /* Must update the mgs logs */ ldd->ldd_flags |= LDD_F_UPDATE; break; case 'q': verbose--; break; case 't': if (!IS_MDT(ldd) && !IS_OST(ldd)) { badopt(long_opt[longidx].name, "MDT,OST"); return 1; } if (optarg == NULL) return 1; rc = add_param(ldd->ldd_params, PARAM_NETWORK, optarg); if (rc != 0) return rc; /* Must update the mgs logs */ ldd->ldd_flags |= LDD_F_UPDATE; break; case 'u': strscpy(ldd->ldd_userdata, optarg, sizeof(ldd->ldd_userdata)); break; case 'U': mop->mo_flags |= MO_NOHOSTID_CHECK; break; case 'v': verbose++; break; case 'V': ++version; fprintf(stdout, "%s %s\n", progname, LUSTRE_VERSION_STRING); return 0; #ifndef TUNEFS case 'b': { int i = 0; do { if (strcmp(optarg, mt_str(i)) == 0) { ldd->ldd_mount_type = i; break; } } while (++i < LDD_MT_LAST); if (i == LDD_MT_LAST) { fprintf(stderr, "%s: invalid backend filesystem" " type %s\n", progname, optarg); return 1; } break; } case 'c': if (IS_MDT(ldd)) { int stripe_count = atol(optarg); if (stripe_count <= 0) { fprintf(stderr, "%s: bad stripe count " "%d\n", progname, stripe_count); return 1; } mop->mo_stripe_count = stripe_count; } else { badopt(long_opt[longidx].name, "MDT"); return 1; } break; case 'd': mop->mo_device_kb = atol(optarg); break; case 'G': ldd->ldd_flags |= LDD_F_SV_TYPE_MGS; break; case 'k': strscpy(mop->mo_mkfsopts, optarg, sizeof(mop->mo_mkfsopts)); break; case 'M': ldd->ldd_flags |= LDD_F_SV_TYPE_MDT; break; case 'N': ldd->ldd_flags &= ~LDD_F_SV_TYPE_MGS; break; case 'O': ldd->ldd_flags |= LDD_F_SV_TYPE_OST; break; case 'r': mop->mo_flags |= MO_FORCEFORMAT; break; case 'R': replace = 1; break; #else /* !TUNEFS */ case 'e': ldd->ldd_params[0] = '\0'; /* Must update the mgs logs */ ldd->ldd_flags |= LDD_F_UPDATE; break; case 'Q': mop->mo_flags |= MO_QUOTA; break; case 'w': ldd->ldd_flags |= LDD_F_WRITECONF; break; #endif /* !TUNEFS */ default: if (opt != '?') { fatal(); fprintf(stderr, "Unknown option '%c'\n", opt); } return EINVAL; } } if (strlen(new_fsname) > 0) { if (!(mop->mo_flags & MO_FORCEFORMAT) && (!(ldd->ldd_flags & (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF)))) { fprintf(stderr, "%s: cannot change the name " "of a registered target\n", progname); return 1; } strscpy(ldd->ldd_fsname, new_fsname, sizeof(ldd->ldd_fsname)); } if (index_option && !(mop->mo_ldd.ldd_flags & (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF))) { fprintf(stderr, "%s: cannot change the index of" " a registered target\n", progname); return 1; } /* Need to clear this flag after parsing 'L' and 'i' options. */ if (replace) ldd->ldd_flags &= ~LDD_F_VIRGIN; if (optind == argc) { /* The user didn't specify device name */ fatal(); fprintf(stderr, "Not enough arguments - device name or " "pool/dataset name not specified.\n"); return EINVAL; } else { /* The device or pool/filesystem name */ strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device)); /* Followed by optional vdevs */ if (optind < argc - 1) mop->mo_pool_vdevs = (char **) &argv[optind + 1]; } return 0; }
int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, char **mountopts) { static struct option long_opt[] = { { "backfstype", required_argument, NULL, 'b' }, { "stripe-count-hint", required_argument, NULL, 'c' }, { "comment", required_argument, NULL, 'u' }, { "configdev", required_argument, NULL, 'C' }, { "device-size", required_argument, NULL, 'd' }, { "dryrun", no_argument, NULL, 'n' }, { "erase-params", no_argument, NULL, 'e' }, { "failnode", required_argument, NULL, 'f' }, { "failover", required_argument, NULL, 'f' }, { "mgs", no_argument, NULL, 'G' }, { "help", no_argument, NULL, 'h' }, { "index", required_argument, NULL, 'i' }, { "mkfsoptions", required_argument, NULL, 'k' }, { "mgsnode", required_argument, NULL, 'm' }, { "mgsnid", required_argument, NULL, 'm' }, { "mdt", no_argument, NULL, 'M' }, { "fsname", required_argument, NULL, 'L' }, { "noformat", no_argument, NULL, 'n' }, { "nomgs", no_argument, NULL, 'N' }, { "mountfsoptions", required_argument, NULL, 'o' }, { "ost", no_argument, NULL, 'O' }, { "param", required_argument, NULL, 'p' }, { "print", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "quota", no_argument, NULL, 'Q' }, { "reformat", no_argument, NULL, 'r' }, { "replace", no_argument, NULL, 'R' }, { "servicenode", required_argument, NULL, 's' }, { "network", required_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "writeconf", no_argument, NULL, 'w' }, { 0, 0, NULL, 0 } }; char *optstring = "b:c:C:d:ef:Ghi:k:L:m:MnNo:Op:PqrRs:t:Uu:vw"; int opt; int rc, longidx; int failnode_set = 0, servicenode_set = 0; int replace = 0; while ((opt = getopt_long(argc, argv, optstring, long_opt, &longidx)) != EOF) { switch (opt) { case 'b': { int i = 0; while (i < LDD_MT_LAST) { if (strcmp(optarg, mt_str(i)) == 0) { mop->mo_ldd.ldd_mount_type = i; break; } i++; } if (i == LDD_MT_LAST) { fprintf(stderr, "%s: invalid backend filesystem" " type %s\n", progname, optarg); return 1; } break; } case 'c': if (IS_MDT(&mop->mo_ldd)) { int stripe_count = atol(optarg); if (stripe_count <= 0) { fprintf(stderr, "%s: bad stripe count " "%d\n", progname, stripe_count); return 1; } mop->mo_stripe_count = stripe_count; } else { badopt(long_opt[longidx].name, "MDT"); return 1; } break; case 'C': /* Configdev */ //FIXME printf("Configdev not implemented\n"); return 1; case 'd': mop->mo_device_kb = atol(optarg); break; case 'e': mop->mo_ldd.ldd_params[0] = '\0'; /* Must update the mgs logs */ mop->mo_ldd.ldd_flags |= LDD_F_UPDATE; break; case 'f': case 's': { char *nids; if ((opt == 'f' && servicenode_set) || (opt == 's' && failnode_set)) { fprintf(stderr, "%s: %s cannot use with --%s\n", progname, long_opt[longidx].name, opt == 'f' ? "servicenode" : "failnode"); return 1; } nids = convert_hostnames(optarg); if (!nids) return 1; rc = add_param(mop->mo_ldd.ldd_params, PARAM_FAILNODE, nids); free(nids); if (rc) return rc; /* Must update the mgs logs */ mop->mo_ldd.ldd_flags |= LDD_F_UPDATE; if (opt == 'f') { failnode_set = 1; } else { mop->mo_ldd.ldd_flags |= LDD_F_NO_PRIMNODE; servicenode_set = 1; } mop->mo_flags |= MO_FAILOVER; break; } case 'G': mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MGS; break; case 'h': usage(stdout); return 1; case 'i': if (!(mop->mo_ldd.ldd_flags & (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF))) { fprintf(stderr, "%s: cannot change the index of" " a registered target\n", progname); return 1; } /* LU-2374: check whether it is OST/MDT later */ mop->mo_ldd.ldd_svindex = atol(optarg); mop->mo_ldd.ldd_flags &= ~LDD_F_NEED_INDEX; break; case 'k': strscpy(mop->mo_mkfsopts, optarg, sizeof(mop->mo_mkfsopts)); break; case 'L': { char *tmp; if (!(mop->mo_flags & MO_FORCEFORMAT) && (!(mop->mo_ldd.ldd_flags & (LDD_F_UPGRADE14 | LDD_F_VIRGIN | LDD_F_WRITECONF)))) { fprintf(stderr, "%s: cannot change the name of" " a registered target\n", progname); return 1; } if ((strlen(optarg) < 1) || (strlen(optarg) > 8)) { fprintf(stderr, "%s: filesystem name must be " "1-8 chars\n", progname); return 1; } if ((tmp = strpbrk(optarg, "/:"))) { fprintf(stderr, "%s: char '%c' not allowed in " "filesystem name\n", progname, *tmp); return 1; } strscpy(mop->mo_ldd.ldd_fsname, optarg, sizeof(mop->mo_ldd.ldd_fsname)); break; } case 'm': { char *nids = convert_hostnames(optarg); if (!nids) return 1; rc = add_param(mop->mo_ldd.ldd_params, PARAM_MGSNODE, nids); free(nids); if (rc) return rc; mop->mo_mgs_failnodes++; break; } case 'M': mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_MDT; break; case 'n': print_only++; break; case 'N': mop->mo_ldd.ldd_flags &= ~LDD_F_SV_TYPE_MGS; break; case 'o': *mountopts = optarg; break; case 'O': mop->mo_ldd.ldd_flags |= LDD_F_SV_TYPE_OST; break; case 'p': rc = add_param(mop->mo_ldd.ldd_params, NULL, optarg); if (rc) return rc; /* Must update the mgs logs */ mop->mo_ldd.ldd_flags |= LDD_F_UPDATE; break; case 'q': verbose--; break; case 'r': mop->mo_flags |= MO_FORCEFORMAT; break; case 'R': replace = 1; 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)); break; case 'v': verbose++; break; case 'w': mop->mo_ldd.ldd_flags |= LDD_F_WRITECONF; break; case 'Q': mop->mo_flags |= MO_QUOTA; break; default: if (opt != '?') { fatal(); fprintf(stderr, "Unknown option '%c'\n", opt); } return EINVAL; } }//while /* Need to clear this flag after parsing 'L' and 'i' options. */ if (replace) mop->mo_ldd.ldd_flags &= ~LDD_F_VIRGIN; if (optind == argc) { /* The user didn't specify device name */ fatal(); fprintf(stderr, "Not enough arguments - device name or " "pool/dataset name not specified.\n"); return EINVAL; } else { /* The device or pool/filesystem name */ strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device)); /* Followed by optional vdevs */ if (optind < argc - 1) mop->mo_pool_vdevs = (char **) &argv[optind + 1]; } return 0; }