mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-20 15:04:42 +00:00
Add resize_devices ioctl and scoutfs command
Add a scoutfs command that uses an ioctl to send a request to the server to safely use a device that has grown. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
@@ -103,6 +103,63 @@ Ignore presence of existing data on the data and metadata devices.
|
||||
.PD
|
||||
|
||||
.TP
|
||||
.BI "resize-devices [-p|--path PATH] [-m|--meta-size SIZE] [-d|--data-size SIZE]"
|
||||
.sp
|
||||
Resize the metadata or data devices of a mounted ScoutFS filesystem.
|
||||
.sp
|
||||
ScoutFS metadata has free extent records and fields in the super block
|
||||
that reflect the size of the devices in use. This command sends a
|
||||
request to the server to change the size of the device that can be used
|
||||
by updating free extents and setting the super block fields.
|
||||
.sp
|
||||
The specified sizes are in bytes and are translated into block counts.
|
||||
If the specified sizes are not a multiple of the metadata or data block
|
||||
sizes then a message is output and the resized size is truncated down to
|
||||
the next whole block. Specifying either a size of 0 or the current
|
||||
device size makes no change. The current size of the devices can be
|
||||
seen, in units of their respective block sizes, in the total_meta_blocks
|
||||
and total_data_blocks fields returned by the scoutfs statfs command (via
|
||||
the statfs_more ioctl).
|
||||
.sp
|
||||
Shrinking is not supported. Specifying a smaller size for either device
|
||||
will return an error and neither device will be resized.
|
||||
.sp
|
||||
Specifying a larger size will expand the initial size of the device that
|
||||
will be used. Free space records are added for the expanded region and
|
||||
can be used once the resizing transaction is complete.
|
||||
.sp
|
||||
The resizing action is performed in a transaction on the server. This
|
||||
command will hang until a server is elected and running and can service
|
||||
the reqeust. The server serializes any concurrent requests to resize.
|
||||
.sp
|
||||
The new sizes must fit within the current sizes of the mounted devices.
|
||||
Presumably this command is being performed as part of a larger
|
||||
coordinated resize of the underlying devices. The device must be
|
||||
expanded before ScoutFS can use the larger device and ScoutFS must stop
|
||||
using a region to shrink before it could be removed from the device
|
||||
(which is not currently supported).
|
||||
.sp
|
||||
The resize will be committed by the server before the response is sent
|
||||
to the client. The system can be using the new device size before the
|
||||
result is communicated through the client and this command completes.
|
||||
The client could crash and the server could still have performed the
|
||||
resize.
|
||||
.RS 1.0i
|
||||
.PD 0
|
||||
.TP
|
||||
.sp
|
||||
.B "-p, --path PATH"
|
||||
A path in the mounted ScoutFS filesystem which will have its devices
|
||||
resized.
|
||||
.TP
|
||||
.B "-m, --meta-size SIZE"
|
||||
.B "-d, --data-size SIZE"
|
||||
The new size of the metadata or data device to use, in bytes. Size is given as
|
||||
an integer followed by a units digit: "K", "M", "G", "T", "P", to denote
|
||||
kibibytes, mebibytes, etc.
|
||||
.RE
|
||||
.PD
|
||||
|
||||
.BI "stat FILE [-s|--single-field FIELD-NAME]"
|
||||
.sp
|
||||
Display ScoutFS-specific metadata fields for the given file.
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <argp.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "parse.h"
|
||||
#include "util.h"
|
||||
#include "format.h"
|
||||
#include "ioctl.h"
|
||||
#include "cmd.h"
|
||||
|
||||
struct resize_args {
|
||||
char *path;
|
||||
u64 meta_size;
|
||||
u64 data_size;
|
||||
};
|
||||
|
||||
static int do_resize_devices(struct resize_args *args)
|
||||
{
|
||||
struct scoutfs_ioctl_resize_devices rd;
|
||||
int ret;
|
||||
int fd;
|
||||
|
||||
if (args->meta_size & SCOUTFS_BLOCK_LG_MASK) {
|
||||
printf("metadata device size %llu is not a multiple of %u metadata block size, truncating down to %llu byte size\n",
|
||||
args->meta_size, SCOUTFS_BLOCK_LG_SIZE,
|
||||
args->meta_size & ~(u64)SCOUTFS_BLOCK_LG_MASK);
|
||||
}
|
||||
|
||||
if (args->data_size & SCOUTFS_BLOCK_SM_MASK) {
|
||||
printf("data device size %llu is not a multiple of %u data block size, truncating down to %llu byte size\n",
|
||||
args->data_size, SCOUTFS_BLOCK_SM_SIZE,
|
||||
args->data_size & ~(u64)SCOUTFS_BLOCK_SM_MASK);
|
||||
}
|
||||
|
||||
fd = get_path(args->path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
rd.new_total_meta_blocks = args->meta_size >> SCOUTFS_BLOCK_LG_SHIFT;
|
||||
rd.new_total_data_blocks = args->data_size >> SCOUTFS_BLOCK_SM_SHIFT;
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_RESIZE_DEVICES, &rd);
|
||||
if (ret < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "resize_devices ioctl failed: %s (%d)\n", strerror(errno), errno);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct resize_args *args = state->input;
|
||||
int ret;
|
||||
|
||||
switch (key) {
|
||||
case 'm': /* meta-size */
|
||||
{
|
||||
ret = parse_human(arg, &args->meta_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
case 'd': /* data-size */
|
||||
{
|
||||
ret = parse_human(arg, &args->data_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
args->path = strdup_or_error(state, arg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{ "path", 'p', "PATH", 0, "Path to ScoutFS filesystem"},
|
||||
{ "meta-size", 'm', "SIZE", 0, "New metadata device size (bytes or KMGTP units)"},
|
||||
{ "data-size", 'd', "SIZE", 0, "New data device size (bytes or KMGTP units)"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct argp argp = {
|
||||
options,
|
||||
parse_opt,
|
||||
"",
|
||||
"Online resize of metadata and/or data devices",
|
||||
};
|
||||
|
||||
static int resize_devices_cmd(int argc, char **argv)
|
||||
{
|
||||
|
||||
struct resize_args resize_args = {NULL,};
|
||||
int ret;
|
||||
|
||||
ret = argp_parse(&argp, argc, argv, 0, NULL, &resize_args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return do_resize_devices(&resize_args);
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) read_xattr_totals_ctor(void)
|
||||
{
|
||||
cmd_register_argp("resize-devices", &argp, GROUP_CORE, resize_devices_cmd);
|
||||
}
|
||||
Reference in New Issue
Block a user