Add mkfs -A for small device sizes

Normally mkfs would fail if we specify meta or data devices that are too
small.  We'd like to use small devices for test scenarios, though, so
add an option to allow specifying sizes smaller than the minumum
required sizes.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2021-06-24 14:47:18 -07:00
parent 29cfa81574
commit 84454b38c5
4 changed files with 27 additions and 9 deletions

View File

@@ -32,7 +32,7 @@ A path within a ScoutFS filesystem.
.PD
.TP
.BI "mkfs META-DEVICE DATA-DEVICE {-Q|--quorum-slot} NR,ADDR,PORT [-m|--max-meta-size SIZE] [-d|--max-data-size SIZE] [-z|--data-alloc-zone-blocks BLOCKS] [-f|--force]"
.BI "mkfs META-DEVICE DATA-DEVICE {-Q|--quorum-slot} NR,ADDR,PORT [-m|--max-meta-size SIZE] [-d|--max-data-size SIZE] [-z|--data-alloc-zone-blocks BLOCKS] [-f|--force] [-A|--allow-small-size]"
.sp
Initialize a new ScoutFS filesystem on the target devices. Since ScoutFS uses
separate block devices for its metadata and data storage, two are required.
@@ -40,7 +40,10 @@ The internal structures and nature of metadata and data transactions
lead to minimum viable device sizes.
.B mkfs
will check both devices and fail with an error if either are under the
minimum size.
minimum size. If
.B --allow-small-size
is given then sizes under the minimum size will be
allowed after printing an informational warning.
.sp
If
.B --force
@@ -86,6 +89,10 @@ kibibytes, mebibytes, etc.
.B "-d, --max-data-size SIZE"
Same as previous, but for limiting the size of the data device.
.TP
.B "-A, --allow-small-size"
Allows use of specified device sizes less than the minimum. This can
result in bad behaviour and is only intended for testing.
.TP
.B "-z, --data-alloc-zone-blocks BLOCKS"
Set the data_alloc_zone_blocks volume option, as described in
.BR scoutfs (5).

View File

@@ -6,12 +6,13 @@
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <errno.h>
#include <stdbool.h>
#include "sparse.h"
#include "dev.h"
int device_size(char *path, int fd,
u64 min_size, u64 max_size,
u64 min_size, u64 max_size, bool allow_small_size,
char *use_type, u64 *size_ret)
{
struct stat st;
@@ -63,10 +64,13 @@ int device_size(char *path, int fd,
if (size < min_size) {
fprintf(stderr,
BASE_SIZE_FMT" %s too small for min "
BASE_SIZE_FMT" %s device\n",
BASE_SIZE_FMT" %s device%s\n",
BASE_SIZE_ARGS(size), target_type,
BASE_SIZE_ARGS(min_size), use_type);
return -EINVAL;
BASE_SIZE_ARGS(min_size), use_type,
allow_small_size ? ", allowing with -A" : "");
if (!allow_small_size)
return -EINVAL;
}
*size_ret = size;

View File

@@ -1,6 +1,8 @@
#ifndef _DEV_H_
#define _DEV_H_
#include <stdbool.h>
#define BASE_SIZE_FMT "%.2f%s"
#define BASE_SIZE_ARGS(sz) size_flt(sz, 1), size_str(sz, 1)
@@ -8,7 +10,7 @@
#define SIZE_ARGS(nr, sz) (nr), size_flt(nr, sz), size_str(nr, sz)
int device_size(char *path, int fd,
u64 min_size, u64 max_size,
u64 min_size, u64 max_size, bool allow_small_size,
char *use_type, u64 *size_ret);
float size_flt(u64 nr, unsigned size);
char *size_str(u64 nr, unsigned size);

View File

@@ -135,6 +135,7 @@ struct mkfs_args {
unsigned long long max_data_size;
u64 data_alloc_zone_blocks;
bool force;
bool allow_small_size;
int nr_slots;
struct scoutfs_quorum_slot slots[SCOUTFS_QUORUM_MAX_SLOTS];
};
@@ -217,13 +218,13 @@ static int do_mkfs(struct mkfs_args *args)
/* minumum meta device size to make reserved blocks reasonably large */
ret = device_size(args->meta_device, meta_fd, 64ULL * (1024 * 1024 * 1024),
args->max_meta_size, "meta", &meta_size);
args->max_meta_size, args->allow_small_size, "meta", &meta_size);
if (ret)
goto out;
/* .. then arbitrarily the same minimum data device size */
ret = device_size(args->data_device, data_fd, 64ULL * (1024 * 1024 * 1024),
args->max_data_size, "data", &data_size);
args->max_data_size, args->allow_small_size, "data", &data_size);
if (ret)
goto out;
@@ -522,6 +523,9 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
prev_val, args->max_data_size);
break;
}
case 'A':
args->allow_small_size = true;
break;
case 'z': /* data-alloc-zone-blocks */
{
ret = parse_u64(arg, &args->data_alloc_zone_blocks);
@@ -561,6 +565,7 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
static struct argp_option options[] = {
{ "quorum-slot", 'Q', "NR,ADDR,PORT", 0, "Specify quorum slot addresses [Required]"},
{ "force", 'f', NULL, 0, "Overwrite existing data on block devices"},
{ "allow-small-size", 'A', NULL, 0, "Allow specified meta/data devices less than minimum, still warns"},
{ "max-meta-size", 'm', "SIZE", 0, "Use a size less than the base metadata device size (bytes or KMGTP units)"},
{ "max-data-size", 'd', "SIZE", 0, "Use a size less than the base data device size (bytes or KMGTP units)"},
{ "data-alloc-zone-blocks", 'z', "BLOCKS", 0, "Divide data device into block zones so each mounts writes to a zone (4KB blocks)"},