Blame gfs2/mkfs/main_mkfs.c

Packit Service 360c39
#include "clusterautoconfig.h"
Packit Service 360c39
Packit Service 360c39
#include <stdio.h>
Packit Service 360c39
#include <stdlib.h>
Packit Service 360c39
#include <string.h>
Packit Service 360c39
#include <stdint.h>
Packit Service 360c39
#include <inttypes.h>
Packit Service 360c39
#include <sys/types.h>
Packit Service 360c39
#include <sys/stat.h>
Packit Service 360c39
#include <fcntl.h>
Packit Service 360c39
#include <unistd.h>
Packit Service 360c39
#include <time.h>
Packit Service 360c39
#include <errno.h>
Packit Service 360c39
#include <stdarg.h>
Packit Service 360c39
#include <mntent.h>
Packit Service 360c39
#include <ctype.h>
Packit Service 360c39
#include <poll.h>
Packit Service 360c39
#include <signal.h>
Packit Service 360c39
#include <sys/time.h>
Packit Service 360c39
#include <libintl.h>
Packit Service 360c39
#include <sys/ioctl.h>
Packit Service 360c39
#include <limits.h>
Packit Service 360c39
#include <blkid.h>
Packit Service 360c39
#include <locale.h>
Packit Service 360c39
Packit Service 360c39
#define _(String) gettext(String)
Packit Service 360c39
Packit Service 360c39
#include <linux/types.h>
Packit Service 360c39
#include "libgfs2.h"
Packit Service 360c39
#include "gfs2_mkfs.h"
Packit Service 360c39
#include "progress.h"
Packit Service 360c39
Packit Service 360c39
#ifdef GFS2_HAS_UUID
Packit Service 360c39
#include <uuid.h>
Packit Service 360c39
#endif
Packit Service 360c39
Packit Service 360c39
static void print_usage(const char *prog_name)
Packit Service 360c39
{
Packit Service 360c39
	int i;
Packit Service 360c39
	const char *option, *param, *desc;
Packit Service 360c39
	const char *options[] = {
Packit Service 360c39
	    /* Translators: This is a usage string printed with --help.
Packit Service 360c39
	       <size> and <number> here are the commandline parameters,
Packit Service 360c39
	       e.g. mkfs.gfs2 -b <size> -j <number> /dev/sda */
Packit Service 360c39
	    "-b", _("<size>"),   _("File system block size, in bytes"),
Packit Service 360c39
	    "-c", _("<size>"),   _("Size of quota change file, in megabytes"),
Packit Service 360c39
	    "-D", NULL,          _("Enable debugging code"),
Packit Service 360c39
	    "-h", NULL,          _("Display this help, then exit"),
Packit Service 360c39
	    "-J", _("<size>"),   _("Size of journals, in megabytes"),
Packit Service 360c39
	    "-j", _("<number>"), _("Number of journals"),
Packit Service 360c39
	    "-K", NULL,          _("Don't try to discard unused blocks"),
Packit Service 360c39
	    "-O", NULL,          _("Don't ask for confirmation"),
Packit Service 360c39
	    "-o", _("<key>[=<value>][,...]"), _("Specify extended options. See '-o help'."),
Packit Service 360c39
	    "-p", _("<name>"),   _("Name of the locking protocol"),
Packit Service 360c39
	    "-q", NULL,          _("Don't print anything"),
Packit Service 360c39
	    "-r", _("<size>"),   _("Size of resource groups, in megabytes"),
Packit Service 360c39
	    "-t", _("<name>"),   _("Name of the lock table"),
Packit Service 360c39
	    "-V", NULL,          _("Display program version information, then exit"),
Packit Service 360c39
	    NULL, NULL, NULL /* Must be kept at the end */
Packit Service 360c39
	};
Packit Service 360c39
Packit Service 360c39
	printf("%s\n", _("Usage:"));
Packit Service 360c39
	printf("%s [%s] <%s> [%s]\n\n", prog_name, _("options"), _("device"), _("size"));
Packit Service 360c39
	printf(_("Create a gfs2 file system on a device. If a size, in blocks, is not "
Packit Service 360c39
	         "specified, the whole device will be used."));
Packit Service 360c39
	printf("\n\n%s\n", _("Options:"));
Packit Service 360c39
Packit Service 360c39
	for (i = 0; options[i] != NULL; i += 3) {
Packit Service 360c39
		option = options[i];
Packit Service 360c39
		param = options[i + 1];
Packit Service 360c39
		desc = options[i + 2];
Packit Service 360c39
		printf("%3s %-22s %s\n", option, param ? param : "", desc);
Packit Service 360c39
	}
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void print_ext_opts(void)
Packit Service 360c39
{
Packit Service 360c39
	int i;
Packit Service 360c39
	const char *options[] = {
Packit Service 360c39
		"help", _("Display this help, then exit"),
Packit Service 360c39
		"swidth=N",  _("Specify the stripe width of the device, overriding probed values"),
Packit Service 360c39
		"sunit=N", _("Specify the stripe unit of the device, overriding probed values"),
Packit Service 360c39
		"align=[0|1]", _("Disable or enable alignment of resource groups"),
Packit Service 360c39
		NULL, NULL
Packit Service 360c39
	};
Packit Service 360c39
	printf(_("Extended options:\n"));
Packit Service 360c39
	for (i = 0; options[i] != NULL; i += 2) {
Packit Service 360c39
		printf("%15s  %-22s\n", options[i], options[i + 1]);
Packit Service 360c39
	}
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
/**
Packit Service 360c39
 * Values probed by libblkid:
Packit Service 360c39
 *  alignment_offset: offset, in bytes, of the start of the dev from its natural alignment
Packit Service 360c39
 *  logical_sector_size: smallest addressable unit
Packit Service 360c39
 *  minimum_io_size: device's preferred unit of I/O. RAID stripe unit.
Packit Service 360c39
 *  optimal_io_size: biggest I/O we can submit without incurring a penalty. RAID stripe width.
Packit Service 360c39
 *  physical_sector_size: the smallest unit we can write atomically
Packit Service 360c39
 */
Packit Service 360c39
struct mkfs_dev {
Packit Service 360c39
	int fd;
Packit Service 360c39
	const char *path;
Packit Service 360c39
	struct stat stat;
Packit Service 360c39
	uint64_t size;
Packit Service 360c39
	unsigned long alignment_offset;
Packit Service 360c39
	unsigned long logical_sector_size;
Packit Service 360c39
	unsigned long minimum_io_size;
Packit Service 360c39
	unsigned long optimal_io_size;
Packit Service 360c39
	unsigned long physical_sector_size;
Packit Service 360c39
Packit Service 360c39
	unsigned int got_topol:1;
Packit Service 360c39
};
Packit Service 360c39
Packit Service 360c39
struct mkfs_opts {
Packit Service 360c39
	unsigned bsize;
Packit Service 360c39
	unsigned qcsize;
Packit Service 360c39
	unsigned jsize;
Packit Service 360c39
	unsigned rgsize;
Packit Service 360c39
	unsigned long sunit;
Packit Service 360c39
	unsigned long swidth;
Packit Service 360c39
	uint64_t fssize;
Packit Service 360c39
	uint32_t journals;
Packit Service 360c39
	const char *lockproto;
Packit Service 360c39
	const char *locktable;
Packit Service 360c39
	struct mkfs_dev dev;
Packit Service 360c39
	unsigned discard:1;
Packit Service 360c39
Packit Service 360c39
	unsigned got_bsize:1;
Packit Service 360c39
	unsigned got_qcsize:1;
Packit Service 360c39
	unsigned got_jsize:1;
Packit Service 360c39
	unsigned got_rgsize:1;
Packit Service 360c39
	unsigned got_sunit:1;
Packit Service 360c39
	unsigned got_swidth:1;
Packit Service 360c39
	unsigned got_fssize:1;
Packit Service 360c39
	unsigned got_journals:1;
Packit Service 360c39
	unsigned got_lockproto:1;
Packit Service 360c39
	unsigned got_locktable:1;
Packit Service 360c39
	unsigned got_device:1;
Packit Service 360c39
	unsigned got_topol:1;
Packit Service 360c39
Packit Service 360c39
	unsigned override:1;
Packit Service 360c39
	unsigned quiet:1;
Packit Service 360c39
	unsigned debug:1;
Packit Service 360c39
	unsigned confirm:1;
Packit Service 360c39
	unsigned align:1;
Packit Service 360c39
};
Packit Service 360c39
Packit Service 360c39
static void opts_init(struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	memset(opts, 0, sizeof(*opts));
Packit Service 360c39
	opts->discard = 1;
Packit Service 360c39
	opts->journals = 1;
Packit Service 360c39
	opts->bsize = GFS2_DEFAULT_BSIZE;
Packit Service 360c39
	opts->jsize = GFS2_DEFAULT_JSIZE;
Packit Service 360c39
	opts->qcsize = GFS2_DEFAULT_QCSIZE;
Packit Service 360c39
	opts->rgsize = GFS2_DEFAULT_RGSIZE;
Packit Service 360c39
	opts->lockproto = "lock_dlm";
Packit Service 360c39
	opts->locktable = "";
Packit Service 360c39
	opts->confirm = 1;
Packit Service 360c39
	opts->align = 1;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
struct gfs2_inum *mkfs_journals = NULL;
Packit Service 360c39
Packit Service 360c39
#ifndef BLKDISCARD
Packit Service 360c39
#define BLKDISCARD      _IO(0x12,119)
Packit Service 360c39
#endif
Packit Service 360c39
Packit Service 360c39
static int discard_blocks(int fd, uint64_t len, int debug)
Packit Service 360c39
{
Packit Service 360c39
        __uint64_t range[2];
Packit Service 360c39
Packit Service 360c39
	range[0] = 0;
Packit Service 360c39
	range[1] = len;
Packit Service 360c39
	if (debug)
Packit Service 360c39
		/* Translators: "discard" is a request sent to a storage device to
Packit Service 360c39
		 * discard a range of blocks. */
Packit Service 360c39
		printf(_("Issuing discard request: range: %llu - %llu..."),
Packit Service 360c39
		       (unsigned long long)range[0],
Packit Service 360c39
		       (unsigned long long)range[1]);
Packit Service 360c39
	if (ioctl(fd, BLKDISCARD, &range) < 0) {
Packit Service 360c39
		if (debug)
Packit Service 360c39
			printf("%s = %d\n", _("error"), errno);
Packit Service 360c39
		return errno;
Packit Service 360c39
	}
Packit Service 360c39
	if (debug)
Packit Service 360c39
		printf(_("Successful.\n"));
Packit Service 360c39
        return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
/**
Packit Service 360c39
 * Convert a human-readable size string to a long long.
Packit Service 360c39
 * Copied and adapted from xfs_mkfs.c.
Packit Service 360c39
 */
Packit Service 360c39
static long long cvtnum(unsigned int blocksize, unsigned int sectorsize, const char *s)
Packit Service 360c39
{
Packit Service 360c39
        long long i;
Packit Service 360c39
        char *sp;
Packit Service 360c39
Packit Service 360c39
        i = strtoll(s, &sp, 0);
Packit Service 360c39
        if (i == 0 && sp == s)
Packit Service 360c39
                return -1LL;
Packit Service 360c39
        if (*sp == '\0')
Packit Service 360c39
                return i;
Packit Service 360c39
Packit Service 360c39
	*sp = tolower(*sp);
Packit Service 360c39
        if (*sp == 'b' && sp[1] == '\0') {
Packit Service 360c39
                if (blocksize)
Packit Service 360c39
                        return i * blocksize;
Packit Service 360c39
                fprintf(stderr, _("Block size not available yet.\n"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
        }
Packit Service 360c39
        if (*sp == 's' && sp[1] == '\0') {
Packit Service 360c39
                if (sectorsize)
Packit Service 360c39
                        return i * sectorsize;
Packit Service 360c39
                return i * GFS2_BASIC_BLOCK;
Packit Service 360c39
        }
Packit Service 360c39
        if (*sp == 'k' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * i;
Packit Service 360c39
        if (*sp == 'm' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * 1024LL * i;
Packit Service 360c39
        if (*sp == 'g' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * 1024LL * 1024LL * i;
Packit Service 360c39
        if (*sp == 't' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * 1024LL * 1024LL * 1024LL * i;
Packit Service 360c39
        if (*sp == 'p' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
Packit Service 360c39
        if (*sp == 'e' && sp[1] == '\0')
Packit Service 360c39
                return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i;
Packit Service 360c39
        return -1LL;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static unsigned long parse_ulong(struct mkfs_opts *opts, const char *key, const char *val)
Packit Service 360c39
{
Packit Service 360c39
	long long l;
Packit Service 360c39
	if (val == NULL || *val == '\0') {
Packit Service 360c39
		fprintf(stderr, _("Missing argument to '%s'\n"), key);
Packit Service 360c39
		exit(-1);
Packit Service 360c39
	}
Packit Service 360c39
	l = cvtnum(opts->bsize, 0, val);
Packit Service 360c39
	if (l > ULONG_MAX || l < 0) {
Packit Service 360c39
		fprintf(stderr, _("Value of '%s' is invalid\n"), key);
Packit Service 360c39
		exit(-1);
Packit Service 360c39
	}
Packit Service 360c39
	return (unsigned long)l;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static unsigned parse_bool(struct mkfs_opts *opts, const char *key, const char *val)
Packit Service 360c39
{
Packit Service 360c39
	if (strnlen(val, 2) == 1) {
Packit Service 360c39
		if (*val == '0')
Packit Service 360c39
			return 0;
Packit Service 360c39
		if (*val == '1')
Packit Service 360c39
			return 1;
Packit Service 360c39
	}
Packit Service 360c39
	fprintf(stderr, _("Option '%s' must be either 1 or 0\n"), key);
Packit Service 360c39
	exit(-1);
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int parse_topology(struct mkfs_opts *opts, char *str)
Packit Service 360c39
{
Packit Service 360c39
	char *opt;
Packit Service 360c39
	unsigned i = 0;
Packit Service 360c39
	unsigned long *topol[5] = {
Packit Service 360c39
		&opts->dev.alignment_offset,
Packit Service 360c39
		&opts->dev.logical_sector_size,
Packit Service 360c39
		&opts->dev.minimum_io_size,
Packit Service 360c39
		&opts->dev.optimal_io_size,
Packit Service 360c39
		&opts->dev.physical_sector_size
Packit Service 360c39
	};
Packit Service 360c39
Packit Service 360c39
	while ((opt = strsep(&str, ":")) != NULL) {
Packit Service 360c39
		if (i > 4) {
Packit Service 360c39
			fprintf(stderr, "Too many topology values.\n");
Packit Service 360c39
			return 1;
Packit Service 360c39
		}
Packit Service 360c39
		*topol[i] = parse_ulong(opts, "test_topology", opt);
Packit Service 360c39
		i++;
Packit Service 360c39
	}
Packit Service 360c39
	if (i < 5) {
Packit Service 360c39
		fprintf(stderr, "Too few topology values.\n");
Packit Service 360c39
		return 1;
Packit Service 360c39
	}
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void opt_parse_extended(char *str, struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	char *opt;
Packit Service 360c39
	while ((opt = strsep(&str, ",")) != NULL) {
Packit Service 360c39
		char *key = strsep(&opt, "=");
Packit Service 360c39
		char *val = strsep(&opt, "=");
Packit Service 360c39
		if (key == NULL || *key == '\0') {
Packit Service 360c39
			fprintf(stderr, _("Missing argument to '-o' option\n"));
Packit Service 360c39
			exit(-1);
Packit Service 360c39
		}
Packit Service 360c39
		if (strcmp("sunit", key) == 0) {
Packit Service 360c39
			opts->sunit = parse_ulong(opts, "sunit", val);
Packit Service 360c39
			opts->got_sunit = 1;
Packit Service 360c39
		} else if (strcmp("swidth", key) == 0) {
Packit Service 360c39
			opts->swidth = parse_ulong(opts, "swidth", val);
Packit Service 360c39
			opts->got_swidth = 1;
Packit Service 360c39
		} else if (strcmp("align", key) == 0) {
Packit Service 360c39
			opts->align = parse_bool(opts, "align", val);
Packit Service 360c39
		} else if (strcmp("test_topology", key) == 0) {
Packit Service 360c39
			if (parse_topology(opts, val) != 0)
Packit Service 360c39
				exit(-1);
Packit Service 360c39
			opts->got_topol = (opts->dev.logical_sector_size != 0 &&
Packit Service 360c39
	                                   opts->dev.physical_sector_size != 0);
Packit Service 360c39
		} else if (strcmp("help", key) == 0) {
Packit Service 360c39
			print_ext_opts();
Packit Service 360c39
			exit(0);
Packit Service 360c39
		} else {
Packit Service 360c39
			fprintf(stderr, _("Invalid option '%s'\n"), key);
Packit Service 360c39
			exit(-1);
Packit Service 360c39
		}
Packit Service 360c39
	}
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void opts_get(int argc, char *argv[], struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	int c;
Packit Service 360c39
	while (1) {
Packit Service 360c39
		c = getopt(argc, argv, "-b:c:DhJ:j:KOo:p:qr:t:V");
Packit Service 360c39
		if (c == -1)
Packit Service 360c39
			break;
Packit Service 360c39
Packit Service 360c39
		switch (c) {
Packit Service 360c39
		case 'b':
Packit Service 360c39
			opts->bsize = atoi(optarg);
Packit Service 360c39
			opts->got_bsize = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'c':
Packit Service 360c39
			opts->qcsize = atoi(optarg);
Packit Service 360c39
			opts->got_qcsize = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'D':
Packit Service 360c39
			opts->debug = 1;
Packit Service 360c39
			lgfs2_set_debug(1);
Packit Service 360c39
			break;
Packit Service 360c39
		case 'h':
Packit Service 360c39
			print_usage(argv[0]);
Packit Service 360c39
			exit(0);
Packit Service 360c39
		case 'J':
Packit Service 360c39
			opts->jsize = atoi(optarg);
Packit Service 360c39
			opts->got_jsize = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'j':
Packit Service 360c39
			opts->journals = atoi(optarg);
Packit Service 360c39
			opts->got_journals = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'K':
Packit Service 360c39
			opts->discard = 0;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'O':
Packit Service 360c39
			opts->override = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'p':
Packit Service 360c39
			opts->lockproto = optarg;
Packit Service 360c39
			opts->got_lockproto = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 't':
Packit Service 360c39
			opts->locktable = optarg;
Packit Service 360c39
			opts->got_locktable = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'q':
Packit Service 360c39
			opts->quiet = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'r':
Packit Service 360c39
			opts->rgsize = atoi(optarg);
Packit Service 360c39
			opts->got_rgsize = 1;
Packit Service 360c39
			break;
Packit Service 360c39
		case 'o':
Packit Service 360c39
			opt_parse_extended(optarg, opts);
Packit Service 360c39
			break;
Packit Service 360c39
		case 'V':
Packit Service 360c39
			printf("mkfs.gfs2 %s (built %s %s)\n", VERSION,
Packit Service 360c39
			       __DATE__, __TIME__);
Packit Service 360c39
			printf(REDHAT_COPYRIGHT "\n");
Packit Service 360c39
			exit(EXIT_SUCCESS);
Packit Service 360c39
			break;
Packit Service 360c39
		case ':':
Packit Service 360c39
		case '?':
Packit Service 360c39
			fprintf(stderr, _("Please use '-h' for help.\n"));
Packit Service 360c39
			exit(EXIT_FAILURE);
Packit Service 360c39
			break;
Packit Service 360c39
		case 1:
Packit Service 360c39
			if (strcmp(optarg, "gfs2") == 0)
Packit Service 360c39
				continue;
Packit Service 360c39
			if (!opts->got_device) {
Packit Service 360c39
				opts->dev.path = optarg;
Packit Service 360c39
				opts->got_device = 1;
Packit Service 360c39
			} else if (!opts->got_fssize && isdigit(optarg[0])) {
Packit Service 360c39
				opts->fssize = atol(optarg);
Packit Service 360c39
				opts->got_fssize = 1;
Packit Service 360c39
			} else
Packit Service 360c39
				die( _("More than one device specified (try -h for help)\n"));
Packit Service 360c39
			break;
Packit Service 360c39
		default:
Packit Service 360c39
			die( _("Invalid option: %c\n"), c);
Packit Service 360c39
			break;
Packit Service 360c39
		};
Packit Service 360c39
	}
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
/**
Packit Service 360c39
 * test_locking - Make sure the GFS2 is set up to use the right lock protocol
Packit Service 360c39
 * @lockproto: the lock protocol to mount
Packit Service 360c39
 * @locktable: the locktable name
Packit Service 360c39
 *
Packit Service 360c39
 */
Packit Service 360c39
Packit Service 360c39
static void test_locking(struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	const char *c;
Packit Service 360c39
	/* Translators: A lock table is a string identifying a gfs2 file system
Packit Service 360c39
	 * in a cluster, e.g. cluster_name:fs_name */
Packit Service 360c39
	const char *errprefix = _("Invalid lock table:");
Packit Service 360c39
	int table_required = (strcmp(opts->lockproto, "lock_gulm") == 0)
Packit Service 360c39
	                  || (strcmp(opts->lockproto, "lock_dlm") == 0);
Packit Service 360c39
Packit Service 360c39
	if ((strcmp(opts->lockproto, "lock_nolock") != 0) && !table_required)
Packit Service 360c39
		die( _("Invalid lock protocol: %s\n"), opts->lockproto);
Packit Service 360c39
Packit Service 360c39
	/* When lock_*lm is given as the lock protocol, require a lock table too */
Packit Service 360c39
	if (!opts->got_locktable) {
Packit Service 360c39
		if (table_required) {
Packit Service 360c39
			fprintf(stderr, _("No lock table specified.\n"));
Packit Service 360c39
			exit(-1);
Packit Service 360c39
		}
Packit Service 360c39
		return;
Packit Service 360c39
	}
Packit Service 360c39
	/* User gave a lock table option, validate it */
Packit Service 360c39
	if (*opts->locktable == '\0') {
Packit Service 360c39
		fprintf(stderr, _("Lock table is empty.\n"));
Packit Service 360c39
		exit(-1);
Packit Service 360c39
	}
Packit Service 360c39
	for (c = opts->locktable; *c; c++) {
Packit Service 360c39
		if (!isalnum(*c) && (*c != '-') && (*c != '_') && (*c != ':'))
Packit Service 360c39
			die("%s %s '%c'\n", errprefix, _("invalid character"), *c);
Packit Service 360c39
	}
Packit Service 360c39
	c = strstr(opts->locktable, ":");
Packit Service 360c39
	if (!c)
Packit Service 360c39
		die("%s %s\n", errprefix, _("missing colon"));
Packit Service 360c39
Packit Service 360c39
	if (c == opts->locktable)
Packit Service 360c39
		die("%s %s\n", errprefix, _("cluster name is missing"));
Packit Service 360c39
	if (c - opts->locktable > 32)
Packit Service 360c39
		die("%s %s\n", errprefix, _("cluster name is too long"));
Packit Service 360c39
Packit Service 360c39
	c++;
Packit Service 360c39
	if (strstr(c, ":"))
Packit Service 360c39
		die("%s %s\n", errprefix, _("contains more than one colon"));
Packit Service 360c39
	if (!strlen(c))
Packit Service 360c39
		die("%s %s\n", errprefix, _("file system name is missing"));
Packit Service 360c39
	if (strlen(c) > 30)
Packit Service 360c39
		die("%s %s\n", errprefix, _("file system name is too long"));
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void are_you_sure(void)
Packit Service 360c39
{
Packit Service 360c39
	while (1) {
Packit Service 360c39
		char *line = NULL;
Packit Service 360c39
		size_t len = 0;
Packit Service 360c39
		int ret;
Packit Service 360c39
		int res;
Packit Service 360c39
Packit Service 360c39
		/* Translators: We use rpmatch(3) to match the answers to y/n
Packit Service 360c39
		   questions in the user's own language, so the [y/n] here must also be
Packit Service 360c39
		   translated to match one of the letters in the pattern printed by
Packit Service 360c39
		   `locale -k yesexpr` and one of the letters in the pattern printed by
Packit Service 360c39
		   `locale -k noexpr` */
Packit Service 360c39
		printf( _("Are you sure you want to proceed? [y/n] "));
Packit Service 360c39
		ret = getline(&line, &len, stdin);
Packit Service 360c39
		res = rpmatch(line);
Packit Service 360c39
		free(line);
Packit Service 360c39
		if (ret <= 0)
Packit Service 360c39
			continue;
Packit Service 360c39
		if (res == 1) /* Yes */
Packit Service 360c39
			return;
Packit Service 360c39
		if (res == 0) /* No */
Packit Service 360c39
			exit(1);
Packit Service 360c39
		/* Unrecognized input; go again. */
Packit Service 360c39
	};
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static unsigned choose_blocksize(struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	unsigned int x;
Packit Service 360c39
	unsigned int bsize = opts->bsize;
Packit Service 360c39
	struct mkfs_dev *dev = &opts->dev;
Packit Service 360c39
	int got_topol = (dev->got_topol || opts->got_topol);
Packit Service 360c39
Packit Service 360c39
	if (got_topol && opts->debug) {
Packit Service 360c39
		printf("alignment_offset: %lu\n", dev->alignment_offset);
Packit Service 360c39
		printf("logical_sector_size: %lu\n", dev->logical_sector_size);
Packit Service 360c39
		printf("minimum_io_size: %lu\n", dev->minimum_io_size);
Packit Service 360c39
		printf("optimal_io_size: %lu\n", dev->optimal_io_size);
Packit Service 360c39
		printf("physical_sector_size: %lu\n", dev->physical_sector_size);
Packit Service 360c39
	}
Packit Service 360c39
	if (got_topol && dev->alignment_offset != 0) {
Packit Service 360c39
		fprintf(stderr,
Packit Service 360c39
		  _("Warning: device is not properly aligned. This may harm performance.\n"));
Packit Service 360c39
		dev->physical_sector_size = dev->logical_sector_size;
Packit Service 360c39
	}
Packit Service 360c39
	if (!opts->got_bsize && got_topol) {
Packit Service 360c39
		if (dev->optimal_io_size <= getpagesize() &&
Packit Service 360c39
		    dev->optimal_io_size >= dev->minimum_io_size)
Packit Service 360c39
			bsize = dev->optimal_io_size;
Packit Service 360c39
		else if (dev->physical_sector_size <= getpagesize() &&
Packit Service 360c39
		         dev->physical_sector_size >= GFS2_DEFAULT_BSIZE)
Packit Service 360c39
			bsize = dev->physical_sector_size;
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	/* Block sizes must be a power of two from 512 to 65536 */
Packit Service 360c39
	for (x = 512; x; x <<= 1)
Packit Service 360c39
		if (x == bsize)
Packit Service 360c39
			break;
Packit Service 360c39
Packit Service 360c39
	if (!x || bsize > getpagesize())
Packit Service 360c39
		die( _("Block size must be a power of two between 512 and %d\n"),
Packit Service 360c39
		       getpagesize());
Packit Service 360c39
Packit Service 360c39
	if (bsize < dev->logical_sector_size) {
Packit Service 360c39
		die( _("Error: Block size %d is less than minimum logical "
Packit Service 360c39
		       "block size (%lu).\n"), bsize, dev->logical_sector_size);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (bsize < dev->physical_sector_size) {
Packit Service 360c39
		printf( _("Warning: Block size %d is inefficient because it "
Packit Service 360c39
			  "is less than the physical block size (%lu).\n"),
Packit Service 360c39
			  bsize, dev->physical_sector_size);
Packit Service 360c39
		opts->confirm = 1;
Packit Service 360c39
	}
Packit Service 360c39
	return bsize;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void opts_check(struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	if (!opts->got_device) {
Packit Service 360c39
		fprintf(stderr, _("No device specified. Use -h for help\n"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	test_locking(opts);
Packit Service 360c39
Packit Service 360c39
	if (GFS2_MIN_RGSIZE > opts->rgsize || opts->rgsize > GFS2_MAX_RGSIZE)
Packit Service 360c39
		/* Translators: gfs2 file systems are split into equal sized chunks called
Packit Service 360c39
		   resource groups. We're checking that the user gave a valid size for them. */
Packit Service 360c39
		die( _("bad resource group size\n"));
Packit Service 360c39
Packit Service 360c39
	if (!opts->journals)
Packit Service 360c39
		die( _("no journals specified\n"));
Packit Service 360c39
Packit Service 360c39
	if (opts->jsize < GFS2_MIN_JSIZE || opts->jsize > GFS2_MAX_JSIZE)
Packit Service 360c39
		die( _("bad journal size\n"));
Packit Service 360c39
Packit Service 360c39
	if (!opts->qcsize || opts->qcsize > 64)
Packit Service 360c39
		die( _("bad quota change size\n"));
Packit Service 360c39
Packit Service 360c39
	if ((opts->got_sunit && !opts->got_swidth) || (!opts->got_sunit && opts->got_swidth)) {
Packit Service 360c39
		fprintf(stderr, _("Stripe unit and stripe width must be specified together\n"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void print_results(struct gfs2_sb *sb, struct mkfs_opts *opts, uint64_t rgrps, uint64_t fssize)
Packit Service 360c39
{
Packit Service 360c39
	printf("%-27s%s\n", _("Device:"), opts->dev.path);
Packit Service 360c39
	printf("%-27s%u\n", _("Block size:"), sb->sb_bsize);
Packit Service 360c39
	printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Device size:"),
Packit Service 360c39
	       /* Translators: "GB" here means "gigabytes" */
Packit Service 360c39
	       (opts->dev.size / ((float)(1 << 30))), _("GB"),
Packit Service 360c39
	       (opts->dev.size / sb->sb_bsize), _("blocks"));
Packit Service 360c39
	printf("%-27s%.2f %s (%"PRIu64" %s)\n", _("Filesystem size:"),
Packit Service 360c39
	       (fssize / ((float)(1 << 30)) * sb->sb_bsize), _("GB"), fssize, _("blocks"));
Packit Service 360c39
	printf("%-27s%u\n", _("Journals:"), opts->journals);
Packit Service 360c39
	printf("%-27s%uMB\n", _("Journal size:"), opts->jsize);
Packit Service 360c39
	printf("%-27s%"PRIu64"\n", _("Resource groups:"), rgrps);
Packit Service 360c39
	printf("%-27s\"%s\"\n", _("Locking protocol:"), opts->lockproto);
Packit Service 360c39
	printf("%-27s\"%s\"\n", _("Lock table:"), opts->locktable);
Packit Service 360c39
#ifdef GFS2_HAS_UUID
Packit Service 360c39
	{
Packit Service 360c39
	char readable_uuid[36+1];
Packit Service 360c39
Packit Service 360c39
	uuid_unparse(sb->sb_uuid, readable_uuid);
Packit Service 360c39
	/* Translators: "UUID" = universally unique identifier. */
Packit Service 360c39
	printf("%-27s%s\n", _("UUID:"), readable_uuid);
Packit Service 360c39
	}
Packit Service 360c39
#endif
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void warn_of_destruction(const char *path)
Packit Service 360c39
{
Packit Service 360c39
	struct stat lnkstat;
Packit Service 360c39
	char *abspath = NULL;
Packit Service 360c39
Packit Service 360c39
	if (lstat(path, &lnkstat) == -1) {
Packit Service 360c39
		perror(_("Failed to lstat the device"));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	if (S_ISLNK(lnkstat.st_mode)) {
Packit Service 360c39
		abspath = canonicalize_file_name(path);
Packit Service 360c39
		if (abspath == NULL) {
Packit Service 360c39
			perror(_("Could not find the absolute path of the device"));
Packit Service 360c39
			exit(EXIT_FAILURE);
Packit Service 360c39
		}
Packit Service 360c39
		/* Translators: Example: "/dev/vg/lv is a symbolic link to /dev/dm-2" */
Packit Service 360c39
		printf( _("%s is a symbolic link to %s\n"), path, abspath);
Packit Service 360c39
		path = abspath;
Packit Service 360c39
	}
Packit Service 360c39
	printf(_("This will destroy any data on %s\n"), path);
Packit Service 360c39
	free(abspath);
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int zero_gap(struct gfs2_sbd *sdp, uint64_t addr, size_t blocks)
Packit Service 360c39
{
Packit Service 360c39
	struct iovec *iov;
Packit Service 360c39
	char *zerobuf;
Packit Service 360c39
	ssize_t wrote;
Packit Service 360c39
	unsigned i;
Packit Service 360c39
Packit Service 360c39
	if (blocks == 0)
Packit Service 360c39
		return 0;
Packit Service 360c39
	iov = calloc(blocks, sizeof(*iov));
Packit Service 360c39
	if (iov == NULL) {
Packit Service 360c39
		perror(_("Failed to zero blocks\n"));
Packit Service 360c39
		return 1;
Packit Service 360c39
	}
Packit Service 360c39
	zerobuf = calloc(1, sdp->bsize);
Packit Service 360c39
	if (zerobuf == NULL) {
Packit Service 360c39
		perror(_("Failed to zero blocks\n"));
Packit Service 360c39
		free(iov);
Packit Service 360c39
		return 1;
Packit Service 360c39
	}
Packit Service 360c39
	for (i = 0; i < blocks; i++) {
Packit Service 360c39
		iov[i].iov_base = zerobuf;
Packit Service 360c39
		iov[i].iov_len = sdp->bsize;
Packit Service 360c39
	}
Packit Service 360c39
	wrote = pwritev(sdp->device_fd, iov, blocks, addr * sdp->bsize);
Packit Service 360c39
	if (wrote != blocks * sdp->bsize) {
Packit Service 360c39
		fprintf(stderr, _("Zeroing write failed at block %"PRIu64"\n"), addr);
Packit Service 360c39
		free(zerobuf);
Packit Service 360c39
		free(iov);
Packit Service 360c39
		return 1;
Packit Service 360c39
	}
Packit Service 360c39
	free(zerobuf);
Packit Service 360c39
	free(iov);
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static lgfs2_rgrps_t rgs_init(struct mkfs_opts *opts, struct gfs2_sbd *sdp)
Packit Service 360c39
{
Packit Service 360c39
	lgfs2_rgrps_t rgs;
Packit Service 360c39
	uint64_t al_base = 0;
Packit Service 360c39
	uint64_t al_off = 0;
Packit Service 360c39
Packit Service 360c39
	if (opts->align && opts->got_sunit) {
Packit Service 360c39
		if ((opts->sunit % sdp->bsize) != 0) {
Packit Service 360c39
			fprintf(stderr, _("Stripe unit (%lu) must be a multiple of block size (%u)\n"),
Packit Service 360c39
			        opts->sunit, sdp->bsize);
Packit Service 360c39
			exit(1);
Packit Service 360c39
		} else if ((opts->swidth % opts->sunit) != 0) {
Packit Service 360c39
			fprintf(stderr, _("Stripe width (%lu) must be a multiple of stripe unit (%lu)\n"),
Packit Service 360c39
			        opts->swidth, opts->sunit);
Packit Service 360c39
			exit(1);
Packit Service 360c39
		} else {
Packit Service 360c39
			al_base = opts->swidth / sdp->bsize;
Packit Service 360c39
			al_off = opts->sunit / sdp->bsize;
Packit Service 360c39
		}
Packit Service 360c39
	} else if (opts->align) {
Packit Service 360c39
		if (opts->dev.optimal_io_size <= opts->dev.physical_sector_size ||
Packit Service 360c39
		    opts->dev.minimum_io_size <= opts->dev.physical_sector_size ||
Packit Service 360c39
		    (opts->dev.optimal_io_size % opts->dev.minimum_io_size) != 0) {
Packit Service 360c39
			/* If optimal_io_size is not a multiple of minimum_io_size then
Packit Service 360c39
			   the values are not reliable swidth and sunit values, so disable
Packit Service 360c39
			   rgrp alignment */
Packit Service 360c39
			opts->align = 0;
Packit Service 360c39
		} else {
Packit Service 360c39
			al_base = opts->dev.optimal_io_size / sdp->bsize;
Packit Service 360c39
			al_off = opts->dev.minimum_io_size / sdp->bsize;
Packit Service 360c39
		}
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	rgs = lgfs2_rgrps_init(sdp, al_base, al_off);
Packit Service 360c39
	if (rgs == NULL) {
Packit Service 360c39
		perror(_("Could not initialise resource groups"));
Packit Service 360c39
		exit(-1);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (opts->debug) {
Packit Service 360c39
		printf("  rgrp align = ");
Packit Service 360c39
		if (opts->align)
Packit Service 360c39
			printf("%"PRIu64"+%"PRIu64" blocks\n", al_base, al_off);
Packit Service 360c39
		else
Packit Service 360c39
			printf("(disabled)\n");
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	return rgs;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int place_rgrp(struct gfs2_sbd *sdp, lgfs2_rgrp_t rg, int debug)
Packit Service 360c39
{
Packit Service 360c39
	uint64_t prev_end = (GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize) + 1;
Packit Service 360c39
	const struct gfs2_rindex *ri = lgfs2_rgrp_index(rg);
Packit Service 360c39
	lgfs2_rgrp_t prev = lgfs2_rgrp_prev(rg);
Packit Service 360c39
	int err = 0;
Packit Service 360c39
Packit Service 360c39
	if (prev != NULL) {
Packit Service 360c39
		prev_end = lgfs2_rgrp_index(prev)->ri_data0 +
Packit Service 360c39
		           lgfs2_rgrp_index(prev)->ri_data;
Packit Service 360c39
	}
Packit Service 360c39
	err = zero_gap(sdp, prev_end, ri->ri_addr - prev_end);
Packit Service 360c39
	if (err != 0)
Packit Service 360c39
		return -1;
Packit Service 360c39
	err = lgfs2_rgrp_write(sdp->device_fd, rg);
Packit Service 360c39
	if (err != 0) {
Packit Service 360c39
		perror(_("Failed to write resource group"));
Packit Service 360c39
		return -1;
Packit Service 360c39
	}
Packit Service 360c39
	if (debug) {
Packit Service 360c39
		gfs2_rindex_print(ri);
Packit Service 360c39
		printf("\n");
Packit Service 360c39
	}
Packit Service 360c39
	sdp->blks_total += ri->ri_data;
Packit Service 360c39
	sdp->fssize = ri->ri_data0 + ri->ri_data;
Packit Service 360c39
	sdp->rgrps++;
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int add_rgrp(lgfs2_rgrps_t rgs, uint64_t *addr, uint32_t len, lgfs2_rgrp_t *rg)
Packit Service 360c39
{
Packit Service 360c39
	struct gfs2_rindex ri;
Packit Service 360c39
	uint64_t nextaddr;
Packit Service 360c39
Packit Service 360c39
	/* When we get to the end of the device, it's only an error if we have
Packit Service 360c39
	   more structures left to write, i.e. when len is != 0. */
Packit Service 360c39
	nextaddr = lgfs2_rindex_entry_new(rgs, &ri, *addr, len);
Packit Service 360c39
	if (nextaddr == 0) {
Packit Service 360c39
		if (len != 0) {
Packit Service 360c39
			perror(_("Failed to create resource group index entry"));
Packit Service 360c39
			return -1;
Packit Service 360c39
		} else {
Packit Service 360c39
			return 1;
Packit Service 360c39
		}
Packit Service 360c39
	}
Packit Service 360c39
	*rg = lgfs2_rgrps_append(rgs, &ri, nextaddr - *addr);
Packit Service 360c39
	if (*rg == NULL) {
Packit Service 360c39
		perror(_("Failed to create resource group"));
Packit Service 360c39
		return -1;
Packit Service 360c39
	}
Packit Service 360c39
	*addr = nextaddr;
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int place_journals(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, struct mkfs_opts *opts, uint64_t *rgaddr)
Packit Service 360c39
{
Packit Service 360c39
	struct gfs2_progress_bar progress;
Packit Service 360c39
	uint64_t jfsize = lgfs2_space_for_data(sdp, sdp->bsize, opts->jsize << 20);
Packit Service 360c39
	uint32_t rgsize = lgfs2_rgsize_for_data(jfsize, sdp->bsize);
Packit Service 360c39
	unsigned j;
Packit Service 360c39
Packit Service 360c39
	gfs2_progress_init(&progress, opts->journals, _("Adding journals: "), opts->quiet);
Packit Service 360c39
Packit Service 360c39
	/* We'll build the jindex later so remember where we put the journals */
Packit Service 360c39
	mkfs_journals = calloc(opts->journals, sizeof(*mkfs_journals));
Packit Service 360c39
	if (mkfs_journals == NULL)
Packit Service 360c39
		return 1;
Packit Service 360c39
	*rgaddr = lgfs2_rgrp_align_addr(rgs, LGFS2_SB_ADDR(sdp) + 1);
Packit Service 360c39
	rgsize = lgfs2_rgrp_align_len(rgs, rgsize);
Packit Service 360c39
Packit Service 360c39
	for (j = 0; j < opts->journals; j++) {
Packit Service 360c39
		int result;
Packit Service 360c39
		lgfs2_rgrp_t rg;
Packit Service 360c39
		struct gfs2_inode in = {0};
Packit Service 360c39
Packit Service 360c39
		gfs2_progress_update(&progress, (j + 1));
Packit Service 360c39
Packit Service 360c39
		if (opts->debug)
Packit Service 360c39
			printf(_("Placing resource group for journal%u\n"), j);
Packit Service 360c39
Packit Service 360c39
		result = add_rgrp(rgs, rgaddr, rgsize, &rg;;
Packit Service 360c39
		if (result > 0)
Packit Service 360c39
			break;
Packit Service 360c39
		else if (result < 0)
Packit Service 360c39
			return result;
Packit Service 360c39
Packit Service 360c39
		result = lgfs2_rgrp_bitbuf_alloc(rg);
Packit Service 360c39
		if (result != 0) {
Packit Service 360c39
			perror(_("Failed to allocate space for bitmap buffer"));
Packit Service 360c39
			return result;
Packit Service 360c39
		}
Packit Service 360c39
		/* Allocate at the beginning of the rgrp, bypassing extent search */
Packit Service 360c39
		in.i_di.di_num.no_addr = lgfs2_rgrp_index(rg)->ri_data0;
Packit Service 360c39
		/* In order to keep writes sequential here, we have to allocate
Packit Service 360c39
		   the journal, then write the rgrp header (which is now in its
Packit Service 360c39
		   final form) and then write the journal out */
Packit Service 360c39
		result = lgfs2_file_alloc(rg, opts->jsize << 20, &in, GFS2_DIF_SYSTEM, S_IFREG | 0600);
Packit Service 360c39
		if (result != 0) {
Packit Service 360c39
			fprintf(stderr, _("Failed to allocate space for journal %u\n"), j);
Packit Service 360c39
			return result;
Packit Service 360c39
		}
Packit Service 360c39
Packit Service 360c39
		if (opts->debug)
Packit Service 360c39
			gfs2_dinode_print(&in.i_di);
Packit Service 360c39
Packit Service 360c39
		result = place_rgrp(sdp, rg, opts->debug);
Packit Service 360c39
		if (result != 0)
Packit Service 360c39
			return result;
Packit Service 360c39
Packit Service 360c39
		lgfs2_rgrp_bitbuf_free(rg);
Packit Service 360c39
Packit Service 360c39
		result = lgfs2_write_filemeta(&in);
Packit Service 360c39
		if (result != 0) {
Packit Service 360c39
			fprintf(stderr, _("Failed to write journal %u\n"), j);
Packit Service 360c39
			return result;
Packit Service 360c39
		}
Packit Service 360c39
Packit Service 360c39
		result = lgfs2_write_journal_data(&in);
Packit Service 360c39
		if (result != 0) {
Packit Service 360c39
			fprintf(stderr, _("Failed to write data blocks for journal %u\n"), j);
Packit Service 360c39
			return result;
Packit Service 360c39
		}
Packit Service 360c39
		mkfs_journals[j] = in.i_di.di_num;
Packit Service 360c39
	}
Packit Service 360c39
	gfs2_progress_close(&progress, _("Done\n"));
Packit Service 360c39
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int place_rgrps(struct gfs2_sbd *sdp, lgfs2_rgrps_t rgs, uint64_t *rgaddr, struct mkfs_opts *opts)
Packit Service 360c39
{
Packit Service 360c39
	struct gfs2_progress_bar progress;
Packit Service 360c39
	uint32_t rgblks = ((opts->rgsize << 20) / sdp->bsize);
Packit Service 360c39
	uint32_t rgnum;
Packit Service 360c39
	int result;
Packit Service 360c39
Packit Service 360c39
	rgnum = lgfs2_rgrps_plan(rgs, sdp->device.length - *rgaddr, rgblks);
Packit Service 360c39
	gfs2_progress_init(&progress, (rgnum + opts->journals), _("Building resource groups: "), opts->quiet);
Packit Service 360c39
Packit Service 360c39
	while (1) {
Packit Service 360c39
		lgfs2_rgrp_t rg;
Packit Service 360c39
		result = add_rgrp(rgs, rgaddr, 0, &rg;;
Packit Service 360c39
		if (result > 0)
Packit Service 360c39
			break;
Packit Service 360c39
		else if (result < 0)
Packit Service 360c39
			return result;
Packit Service 360c39
Packit Service 360c39
		result = place_rgrp(sdp, rg, opts->debug);
Packit Service 360c39
		if (result != 0) {
Packit Service 360c39
			fprintf(stderr, _("Failed to build resource groups\n"));
Packit Service 360c39
			return result;
Packit Service 360c39
		}
Packit Service 360c39
Packit Service 360c39
		gfs2_progress_update(&progress, (sdp->rgrps));
Packit Service 360c39
	}
Packit Service 360c39
	gfs2_progress_close(&progress, _("Done\n"));
Packit Service 360c39
	posix_fadvise(sdp->device_fd, 0, sdp->fssize * sdp->bsize, POSIX_FADV_DONTNEED);
Packit Service 360c39
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
/*
Packit Service 360c39
 * Find a reasonable journal file size (in blocks) given the number of blocks
Packit Service 360c39
 * in the filesystem.  For very small filesystems, it is not reasonable to
Packit Service 360c39
 * have a journal that fills more than half of the filesystem.
Packit Service 360c39
 *
Packit Service 360c39
 * n.b. comments assume 4k blocks
Packit Service 360c39
 *
Packit Service 360c39
 * This was copied and adapted from e2fsprogs.
Packit Service 360c39
 */
Packit Service 360c39
static int default_journal_size(unsigned bsize, uint64_t num_blocks)
Packit Service 360c39
{
Packit Service 360c39
	int min_blocks = (GFS2_MIN_JSIZE << 20) / bsize;
Packit Service 360c39
Packit Service 360c39
	if (num_blocks < 2 * min_blocks)
Packit Service 360c39
		return -1;
Packit Service 360c39
	if (num_blocks < 131072)        /* 512 MB */
Packit Service 360c39
		return min_blocks;              /* 8 MB */
Packit Service 360c39
	if (num_blocks < 512*1024)      /* 2 GB */
Packit Service 360c39
		return (4096);                  /* 16 MB */
Packit Service 360c39
	if (num_blocks < 2048*1024)     /* 8 GB */
Packit Service 360c39
		return (8192);                  /* 32 MB */
Packit Service 360c39
	if (num_blocks < 4096*1024)     /* 16 GB */
Packit Service 360c39
		return (16384);                 /* 64 MB */
Packit Service 360c39
	if (num_blocks < 262144*1024)   /*  1 TB */
Packit Service 360c39
		return (32768);                 /* 128 MB */
Packit Service 360c39
	if (num_blocks < 2621440UL*1024)  /* 10 TB */
Packit Service 360c39
		return (131072);                /* 512 MB */
Packit Service 360c39
	return 262144;                          /*   1 GB */
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void sbd_init(struct gfs2_sbd *sdp, struct mkfs_opts *opts, unsigned bsize)
Packit Service 360c39
{
Packit Service 360c39
	memset(sdp, 0, sizeof(struct gfs2_sbd));
Packit Service 360c39
	sdp->time = time(NULL);
Packit Service 360c39
	sdp->rgtree.osi_node = NULL;
Packit Service 360c39
	sdp->rgsize = opts->rgsize;
Packit Service 360c39
	sdp->qcsize = opts->qcsize;
Packit Service 360c39
	sdp->jsize = opts->jsize;
Packit Service 360c39
	sdp->md.journals = opts->journals;
Packit Service 360c39
	sdp->device_fd = opts->dev.fd;
Packit Service 360c39
	sdp->bsize = sdp->sd_sb.sb_bsize = bsize;
Packit Service 360c39
Packit Service 360c39
	if (compute_constants(sdp)) {
Packit Service 360c39
		perror(_("Failed to compute file system constants"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
	sdp->device.length = opts->dev.size / sdp->bsize;
Packit Service 360c39
	if (opts->got_fssize) {
Packit Service 360c39
		if (opts->fssize > sdp->device.length) {
Packit Service 360c39
			fprintf(stderr, _("Specified size is bigger than the device."));
Packit Service 360c39
			die("%s %.2f %s (%"PRIu64" %s)\n", _("Device size:"),
Packit Service 360c39
			       opts->dev.size / ((float)(1 << 30)), _("GB"),
Packit Service 360c39
			       opts->dev.size / sdp->bsize, _("blocks"));
Packit Service 360c39
		}
Packit Service 360c39
		sdp->device.length = opts->fssize;
Packit Service 360c39
	}
Packit Service 360c39
	/* opts->jsize has already been max/min checked but we need to check it
Packit Service 360c39
	   makes sense for the device size, or set a sensible default, if one
Packit Service 360c39
	   will fit. For user-provided journal sizes, limit it to half of the fs. */
Packit Service 360c39
	if (!opts->got_jsize) {
Packit Service 360c39
		int default_jsize = default_journal_size(sdp->bsize, sdp->device.length / opts->journals);
Packit Service 360c39
		if (default_jsize < 0) {
Packit Service 360c39
			fprintf(stderr, _("gfs2 will not fit on this device.\n"));
Packit Service 360c39
			exit(1);
Packit Service 360c39
		}
Packit Service 360c39
		opts->jsize = (default_jsize * sdp->bsize) >> 20;
Packit Service 360c39
	} else if ((((opts->jsize * opts->journals) << 20) / sdp->bsize) > (sdp->device.length / 2)) {
Packit Service 360c39
		unsigned max_jsize = (sdp->device.length / 2 * sdp->bsize / opts->journals) >> 20;
Packit Service 360c39
Packit Service 360c39
		fprintf(stderr, _("gfs2 will not fit on this device.\n"));
Packit Service 360c39
		if (max_jsize >= GFS2_MIN_JSIZE)
Packit Service 360c39
			fprintf(stderr, _("Maximum size for %u journals on this device is %uMB.\n"),
Packit Service 360c39
			        opts->journals, max_jsize);
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
	sdp->jsize = opts->jsize;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static int probe_contents(struct mkfs_dev *dev)
Packit Service 360c39
{
Packit Service 360c39
	int ret;
Packit Service 360c39
	const char *contents;
Packit Service 360c39
	blkid_probe pr = blkid_new_probe();
Packit Service 360c39
	if (pr == NULL || blkid_probe_set_device(pr, dev->fd, 0, 0) != 0
Packit Service 360c39
	               || blkid_probe_enable_superblocks(pr, TRUE) != 0
Packit Service 360c39
	               || blkid_probe_enable_partitions(pr, TRUE) != 0) {
Packit Service 360c39
		fprintf(stderr, _("Failed to create probe\n"));
Packit Service 360c39
		return -1;
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (!S_ISREG(dev->stat.st_mode) && blkid_probe_enable_topology(pr, TRUE) != 0) {
Packit Service 360c39
		fprintf(stderr, _("Failed to create probe\n"));
Packit Service 360c39
		return -1;
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	ret = blkid_do_fullprobe(pr);
Packit Service 360c39
	if (ret == -1) {
Packit Service 360c39
		fprintf(stderr, _("Failed to probe device\n"));
Packit Service 360c39
		return -1;
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (ret == 1)
Packit Service 360c39
		return 0;
Packit Service 360c39
Packit Service 360c39
	if (!blkid_probe_lookup_value(pr, "TYPE", &contents, NULL)) {
Packit Service 360c39
		printf(_("It appears to contain an existing filesystem (%s)\n"), contents);
Packit Service 360c39
	} else if (!blkid_probe_lookup_value(pr, "PTTYPE", &contents, NULL)) {
Packit Service 360c39
		printf(_("It appears to contain a partition table (%s).\n"), contents);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (!S_ISREG(dev->stat.st_mode)) {
Packit Service 360c39
		blkid_topology tp = blkid_probe_get_topology(pr);
Packit Service 360c39
		if (tp != NULL) {
Packit Service 360c39
			dev->alignment_offset = blkid_topology_get_alignment_offset(tp);
Packit Service 360c39
			dev->logical_sector_size = blkid_topology_get_logical_sector_size(tp);
Packit Service 360c39
			dev->minimum_io_size = blkid_topology_get_minimum_io_size(tp);
Packit Service 360c39
			dev->optimal_io_size = blkid_topology_get_optimal_io_size(tp);
Packit Service 360c39
			dev->physical_sector_size = blkid_topology_get_physical_sector_size(tp);
Packit Service 360c39
			dev->got_topol = (dev->logical_sector_size != 0 &&
Packit Service 360c39
	                                  dev->physical_sector_size != 0);
Packit Service 360c39
		}
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	blkid_free_probe(pr);
Packit Service 360c39
	return 0;
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
static void open_dev(struct mkfs_dev *dev, int withprobe)
Packit Service 360c39
{
Packit Service 360c39
	int error;
Packit Service 360c39
Packit Service 360c39
	dev->fd = open(dev->path, O_RDWR|O_CLOEXEC|O_EXCL);
Packit Service 360c39
	if (dev->fd < 0) {
Packit Service 360c39
		perror(dev->path);
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	/* Freshen up the cache */
Packit Service 360c39
	posix_fadvise(dev->fd, 0, 0, POSIX_FADV_DONTNEED);
Packit Service 360c39
	/* Turn off readahead, we're just writing new blocks */
Packit Service 360c39
	posix_fadvise(dev->fd, 0, 0, POSIX_FADV_RANDOM);
Packit Service 360c39
Packit Service 360c39
	error = fstat(dev->fd, &dev->stat);
Packit Service 360c39
	if (error < 0) {
Packit Service 360c39
		perror(dev->path);
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (S_ISREG(dev->stat.st_mode)) {
Packit Service 360c39
		dev->size = dev->stat.st_size;
Packit Service 360c39
	} else if (S_ISBLK(dev->stat.st_mode)) {
Packit Service 360c39
		dev->size = lseek(dev->fd, 0, SEEK_END);
Packit Service 360c39
		if (dev->size < 1) {
Packit Service 360c39
			fprintf(stderr, _("Device '%s' is too small\n"), dev->path);
Packit Service 360c39
			exit(1);
Packit Service 360c39
		}
Packit Service 360c39
	} else {
Packit Service 360c39
		fprintf(stderr, _("'%s' is not a block device or regular file\n"), dev->path);
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
	if (withprobe && (probe_contents(dev) != 0))
Packit Service 360c39
		exit(1);
Packit Service 360c39
}
Packit Service 360c39
Packit Service 360c39
int main(int argc, char *argv[])
Packit Service 360c39
{
Packit Service 360c39
	struct gfs2_sbd sbd;
Packit Service 360c39
	struct gfs2_sb sb;
Packit Service 360c39
	struct mkfs_opts opts;
Packit Service 360c39
	lgfs2_rgrps_t rgs;
Packit Service 360c39
	uint64_t rgaddr;
Packit Service 360c39
	int error;
Packit Service 360c39
	unsigned bsize;
Packit Service 360c39
Packit Service 360c39
	setlocale(LC_ALL, "");
Packit Service 360c39
	textdomain("gfs2-utils");
Packit Service 360c39
	srandom(time(NULL) ^ getpid());
Packit Service 360c39
Packit Service 360c39
	opts_init(&opts);
Packit Service 360c39
	opts_get(argc, argv, &opts);
Packit Service 360c39
	opts_check(&opts);
Packit Service 360c39
Packit Service 360c39
	open_dev(&opts.dev, !opts.got_topol);
Packit Service 360c39
	bsize = choose_blocksize(&opts);
Packit Service 360c39
Packit Service 360c39
	if (S_ISREG(opts.dev.stat.st_mode)) {
Packit Service 360c39
		opts.got_bsize = 1; /* Use default block size for regular files */
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	sbd_init(&sbd, &opts, bsize);
Packit Service 360c39
	lgfs2_sb_init(&sb, bsize);
Packit Service 360c39
	if (opts.debug) {
Packit Service 360c39
		printf(_("File system options:\n"));
Packit Service 360c39
		printf("  bsize = %u\n", sbd.bsize);
Packit Service 360c39
		printf("  qcsize = %u\n", sbd.qcsize);
Packit Service 360c39
		printf("  jsize = %u\n", sbd.jsize);
Packit Service 360c39
		printf("  journals = %u\n", sbd.md.journals);
Packit Service 360c39
		printf("  proto = %s\n", opts.lockproto);
Packit Service 360c39
		printf("  table = %s\n", opts.locktable);
Packit Service 360c39
		printf("  rgsize = %u\n", sbd.rgsize);
Packit Service 360c39
		printf("  fssize = %"PRIu64"\n", opts.fssize);
Packit Service 360c39
		printf("  sunit = %lu\n", opts.sunit);
Packit Service 360c39
		printf("  swidth = %lu\n", opts.swidth);
Packit Service 360c39
	}
Packit Service 360c39
	rgs = rgs_init(&opts, &sbd;;
Packit Service 360c39
	warn_of_destruction(opts.dev.path);
Packit Service 360c39
Packit Service 360c39
	if (opts.confirm && !opts.override)
Packit Service 360c39
		are_you_sure();
Packit Service 360c39
Packit Service 360c39
	if (!S_ISREG(opts.dev.stat.st_mode) && opts.discard) {
Packit Service 360c39
		if (!opts.quiet) {
Packit Service 360c39
			printf("%s", _("Discarding device contents (may take a while on large devices): "));
Packit Service 360c39
			fflush(stdout);
Packit Service 360c39
		}
Packit Service 360c39
		discard_blocks(opts.dev.fd, opts.dev.size, opts.debug);
Packit Service 360c39
Packit Service 360c39
		if (!opts.quiet)
Packit Service 360c39
			printf("%s", _("Done\n"));
Packit Service 360c39
	}
Packit Service 360c39
	rgaddr = lgfs2_rgrp_align_addr(rgs, LGFS2_SB_ADDR(&sbd) + 1);
Packit Service 360c39
	error = place_journals(&sbd, rgs, &opts, &rgaddr);
Packit Service 360c39
	if (error != 0) {
Packit Service 360c39
		fprintf(stderr, _("Failed to create journals\n"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
	error = place_rgrps(&sbd, rgs, &rgaddr, &opts);
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Failed to build resource groups\n"));
Packit Service 360c39
		exit(1);
Packit Service 360c39
	}
Packit Service 360c39
	sbd.rgtree.osi_node = lgfs2_rgrps_root(rgs); // Temporary
Packit Service 360c39
Packit Service 360c39
	error = build_master(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "master", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	sb.sb_master_dir = sbd.master_dir->i_di.di_num;
Packit Service 360c39
Packit Service 360c39
	error = lgfs2_build_jindex(sbd.master_dir, mkfs_journals, opts.journals);
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "jindex", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	free(mkfs_journals);
Packit Service 360c39
	error = build_per_node(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "per_node", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	error = build_inum(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "inum", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	gfs2_lookupi(sbd.master_dir, "inum", 4, &sbd.md.inum);
Packit Service 360c39
	error = build_statfs(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "statfs", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	gfs2_lookupi(sbd.master_dir, "statfs", 6, &sbd.md.statfs);
Packit Service 360c39
	error = build_rindex(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "rindex", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	if (!opts.quiet) {
Packit Service 360c39
		printf("%s", _("Creating quota file: "));
Packit Service 360c39
		fflush(stdout);
Packit Service 360c39
	}
Packit Service 360c39
	error = build_quota(&sbd;;
Packit Service 360c39
	if (error) {
Packit Service 360c39
		fprintf(stderr, _("Error building '%s': %s\n"), "quota", strerror(errno));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	if (!opts.quiet)
Packit Service 360c39
		printf("%s", _("Done\n"));
Packit Service 360c39
Packit Service 360c39
	build_root(&sbd;;
Packit Service 360c39
	sb.sb_root_dir = sbd.md.rooti->i_di.di_num;
Packit Service 360c39
Packit Service 360c39
	strncpy(sb.sb_lockproto, opts.lockproto, GFS2_LOCKNAME_LEN);
Packit Service 360c39
	strncpy(sb.sb_locktable, opts.locktable, GFS2_LOCKNAME_LEN);
Packit Service 360c39
	sb.sb_lockproto[GFS2_LOCKNAME_LEN - 1] = '\0';
Packit Service 360c39
	sb.sb_locktable[GFS2_LOCKNAME_LEN - 1] = '\0';
Packit Service 360c39
Packit Service 360c39
	do_init_inum(&sbd;;
Packit Service 360c39
	do_init_statfs(&sbd;;
Packit Service 360c39
Packit Service 360c39
	inode_put(&sbd.md.rooti);
Packit Service 360c39
	inode_put(&sbd.master_dir);
Packit Service 360c39
	inode_put(&sbd.md.inum);
Packit Service 360c39
	inode_put(&sbd.md.statfs);
Packit Service 360c39
Packit Service 360c39
	lgfs2_rgrps_free(&rgs);
Packit Service 360c39
Packit Service 360c39
	if (!opts.quiet) {
Packit Service 360c39
		printf("%s", _("Writing superblock and syncing: "));
Packit Service 360c39
		fflush(stdout);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	error = lgfs2_sb_write(&sb, opts.dev.fd, sbd.bsize);
Packit Service 360c39
	if (error) {
Packit Service 360c39
		perror(_("Failed to write superblock\n"));
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	error = fsync(opts.dev.fd);
Packit Service 360c39
	if (error){
Packit Service 360c39
		perror(opts.dev.path);
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
	posix_fadvise(opts.dev.fd, 0, 0, POSIX_FADV_DONTNEED);
Packit Service 360c39
	error = close(opts.dev.fd);
Packit Service 360c39
	if (error){
Packit Service 360c39
		perror(opts.dev.path);
Packit Service 360c39
		exit(EXIT_FAILURE);
Packit Service 360c39
	}
Packit Service 360c39
Packit Service 360c39
	if (!opts.quiet) {
Packit Service 360c39
		printf("%s", _("Done\n"));
Packit Service 360c39
		print_results(&sb, &opts, sbd.rgrps, sbd.fssize);
Packit Service 360c39
	}
Packit Service 360c39
	return 0;
Packit Service 360c39
}