Blame gfs2/mkfs/main_mkfs.c

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