Rework option handling

This commit is contained in:
Kent Overstreet 2016-08-23 19:50:31 -08:00
parent 932ece1567
commit cdd61de630
20 changed files with 411 additions and 441 deletions

View File

@ -4,6 +4,10 @@ INSTALL=install
CFLAGS+=-std=gnu99 -O2 -Wall -g -D_FILE_OFFSET_BITS=64 -I. CFLAGS+=-std=gnu99 -O2 -Wall -g -D_FILE_OFFSET_BITS=64 -I.
LDFLAGS+=-static LDFLAGS+=-static
PKGCONFIG_LIBS="blkid uuid libnih"
CFLAGS+=`pkg-config --cflags ${PKGCONFIG_LIBS}`
LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lscrypt -lsodium -lkeyutils
ifeq ($(PREFIX), "/usr") ifeq ($(PREFIX), "/usr")
ROOT_SBINDIR=/sbin ROOT_SBINDIR=/sbin
else else
@ -17,7 +21,7 @@ install: bcache
$(INSTALL) -m0644 -- bcache.8 $(DESTDIR)$(PREFIX)/share/man/man8/ $(INSTALL) -m0644 -- bcache.8 $(DESTDIR)$(PREFIX)/share/man/man8/
clean: clean:
$(RM) -f bcache *.o *.a $(RM) bcache *.o *.a
CCANSRCS=$(wildcard ccan/*/*.c) CCANSRCS=$(wildcard ccan/*/*.c)
CCANOBJS=$(patsubst %.c,%.o,$(CCANSRCS)) CCANOBJS=$(patsubst %.c,%.o,$(CCANSRCS))
@ -25,16 +29,10 @@ CCANOBJS=$(patsubst %.c,%.o,$(CCANSRCS))
libccan.a: $(CCANOBJS) libccan.a: $(CCANOBJS)
$(AR) r $@ $(CCANOBJS) $(AR) r $@ $(CCANOBJS)
util.o: CFLAGS += `pkg-config --cflags blkid uuid`
bcache.o: CFLAGS += `pkg-config --cflags libnih`
bcache-objs = bcache.o bcache-assemble.o bcache-device.o bcache-format.o\ bcache-objs = bcache.o bcache-assemble.o bcache-device.o bcache-format.o\
bcache-fs.o bcache-run.o bcache-key.o libbcache.o crypto.o bcache-fs.o bcache-run.o bcache-key.o libbcache.o crypto.o util.o
bcache: LDLIBS += `pkg-config --libs uuid blkid libnih` -lscrypt -lsodium -lkeyutils bcache: $(bcache-objs) libccan.a
bcache: $(bcache-objs) util.o libccan.a
bcache-test: LDLIBS += `pkg-config --libs openssl`
deb: deb:
debuild -nc -us -uc -i -I debuild -nc -us -uc -i -I

View File

@ -8,19 +8,14 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <nih/command.h>
#include <nih/option.h>
#include "bcache.h" #include "bcache.h"
#include "bcache-assemble.h"
NihOption opts_assemble[] = { int cmd_assemble(int argc, char *argv[])
NIH_OPTION_LAST
};
int cmd_assemble(NihCommand *command, char *const *args)
{ {
unsigned nr_devs = nr_args(args); unsigned nr_devs = argc - 1;
if (argc <= 1)
die("Please supply at least one device");
struct bch_ioctl_assemble *assemble = struct bch_ioctl_assemble *assemble =
alloca(sizeof(*assemble) + sizeof(__u64) * nr_devs); alloca(sizeof(*assemble) + sizeof(__u64) * nr_devs);
@ -28,8 +23,8 @@ int cmd_assemble(NihCommand *command, char *const *args)
memset(assemble, 0, sizeof(*assemble)); memset(assemble, 0, sizeof(*assemble));
assemble->nr_devs = nr_devs; assemble->nr_devs = nr_devs;
for (unsigned i = 0; i < nr_devs; i++) for (unsigned i = 1; i < argc; i++)
assemble->devs[i] = (__u64) args[i]; assemble->devs[i] = (__u64) argv[i];
int ret = ioctl(bcachectl_open(), BCH_IOCTL_ASSEMBLE, assemble); int ret = ioctl(bcachectl_open(), BCH_IOCTL_ASSEMBLE, assemble);
if (ret < 0) if (ret < 0)
@ -38,17 +33,13 @@ int cmd_assemble(NihCommand *command, char *const *args)
return 0; return 0;
} }
NihOption opts_incremental[] = { int cmd_incremental(int argc, char *argv[])
NIH_OPTION_LAST
};
int cmd_incremental(NihCommand *command, char *const *args)
{ {
if (nr_args(args) != 1) if (argc != 2)
die("Please supply exactly one device"); die("Please supply exactly one device");
struct bch_ioctl_incremental incremental = { struct bch_ioctl_incremental incremental = {
.dev = (__u64) args[0], .dev = (__u64) argv[1],
}; };
int ret = ioctl(bcachectl_open(), BCH_IOCTL_INCREMENTAL, &incremental); int ret = ioctl(bcachectl_open(), BCH_IOCTL_INCREMENTAL, &incremental);

View File

@ -1,10 +0,0 @@
#ifndef _BCACHE_ASSEMBLE_H
#define _BCACHE_ASSEMBLE_H
extern NihOption opts_assemble[];
int cmd_assemble(NihCommand *, char * const *);
extern NihOption opts_incremental[];
int cmd_incremental(NihCommand *, char * const *);
#endif /* _BCACHE_ASSEMBLE_H */

View File

@ -13,11 +13,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <nih/command.h>
#include <nih/option.h> #include <nih/option.h>
#include "bcache.h" #include "bcache.h"
#include "bcache-device.h"
struct bcache_dev { struct bcache_dev {
unsigned nr; unsigned nr;
@ -82,23 +80,20 @@ static void show_dev(struct bcache_dev *dev)
(dev->bytes_dirty * 100) / capacity); (dev->bytes_dirty * 100) / capacity);
} }
static int human_readable; int cmd_device_show(int argc, char *argv[])
NihOption opts_device_show[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
{ 'h', "human-readable", N_("print sizes in powers of 1024 (e.g., 1023M)"),
NULL, NULL, &human_readable, NULL},
NIH_OPTION_LAST
};
int cmd_device_show(NihCommand *command, char * const *args)
{ {
if (!args[0]) int human_readable = 0;
die("Please supply a filesystem"); NihOption opts[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
if (args[1]) { 'h', "human-readable", N_("print sizes in powers of 1024 (e.g., 1023M)"),
die("Please supply a single filesystem"); NULL, NULL, &human_readable, NULL},
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) != 1)
die("Please supply a single device");
struct bcache_handle fs = bcache_fs_open(args[0]); struct bcache_handle fs = bcache_fs_open(args[0]);
struct dirent *entry; struct dirent *entry;
@ -168,13 +163,14 @@ int cmd_device_show(NihCommand *command, char * const *args)
return 0; return 0;
} }
NihOption opts_device_add[] = { int cmd_device_add(int argc, char *argv[])
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
int cmd_device_add(NihCommand *command, char * const *args)
{ {
NihOption opts[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) < 2) if (nr_args(args) < 2)
die("Please supply a filesystem and at least one device to add"); die("Please supply a filesystem and at least one device to add");
@ -192,20 +188,20 @@ int cmd_device_add(NihCommand *command, char * const *args)
return 0; return 0;
} }
static int force_data, force_metadata; int cmd_device_remove(int argc, char *argv[])
NihOption opts_device_remove[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
{ 'f', "force", N_("force if data present"),
NULL, NULL, &force_data, NULL },
{ '\0', "force-metadata", N_("force if metadata present"),
NULL, NULL, &force_metadata, NULL},
NIH_OPTION_LAST
};
int cmd_device_remove(NihCommand *command, char *const *args)
{ {
int force_data = 0, force_metadata = 0;
NihOption opts[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
{ 'f', "force", N_("force if data present"),
NULL, NULL, &force_data, NULL },
{ '\0', "force-metadata", N_("force if metadata present"),
NULL, NULL, &force_metadata, NULL},
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) < 2) if (nr_args(args) < 2)
die("Please supply a filesystem and at least one device to add"); die("Please supply a filesystem and at least one device to add");

View File

@ -1,14 +0,0 @@
#ifndef _BCACHE_DEVICE_H
#define _BCACHE_DEVICE_H
extern NihOption opts_device_show[];
int cmd_device_show(NihCommand *, char * const *);
extern NihOption opts_device_add[];
int cmd_device_add(NihCommand *, char * const *);
extern NihOption opts_device_remove[];
int cmd_device_remove(NihCommand *, char * const *);
#endif /* _BCACHE_FORMAT_H */

View File

@ -5,196 +5,238 @@
* *
* GPLv2 * GPLv2
*/ */
#define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <blkid.h>
#include <uuid/uuid.h> #include <uuid/uuid.h>
#include <nih/command.h>
#include <nih/option.h>
#include "ccan/darray/darray.h" #include "ccan/darray/darray.h"
#include "bcache.h" #include "bcache.h"
#include "libbcache.h" #include "libbcache.h"
#include "bcache-format.h"
#include "crypto.h" #include "crypto.h"
/* All in units of 512 byte sectors */ /* Open a block device, do magic blkid stuff: */
static int open_for_format(const char *dev, bool force)
static darray(struct dev_opts) cache_devices;
static unsigned block_size, btree_node_size;
static unsigned meta_csum_type = BCH_CSUM_CRC32C;
static unsigned data_csum_type = BCH_CSUM_CRC32C;
static unsigned compression_type = BCH_COMPRESSION_NONE;
static int encrypted;
static unsigned meta_replicas = 1, data_replicas = 1;
static unsigned on_error_action;
static char *label = NULL;
static uuid_le uuid;
/* Device specific options: */
static u64 filesystem_size;
static unsigned bucket_size;
static unsigned tier;
static unsigned replacement_policy;
static int discard;
static int set_cache(NihOption *option, const char *arg)
{ {
darray_append(cache_devices, (struct dev_opts) { blkid_probe pr;
.fd = dev_open(arg), const char *fs_type = NULL, *fs_label = NULL;
.dev = strdup(arg), size_t fs_type_len, fs_label_len;
.size = filesystem_size, int fd;
.bucket_size = bucket_size,
.tier = tier, if ((fd = open(dev, O_RDWR|O_EXCL)) == -1)
.replacement_policy = replacement_policy, die("Can't open dev %s: %s\n", dev, strerror(errno));
.discard = discard,
}); if (force)
return 0; return fd;
if (!(pr = blkid_new_probe()))
die("blkid error 1");
if (blkid_probe_set_device(pr, fd, 0, 0))
die("blkid error 2");
if (blkid_probe_enable_partitions(pr, true))
die("blkid error 3");
if (blkid_do_fullprobe(pr) < 0)
die("blkid error 4");
blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
if (fs_type) {
if (fs_label)
printf("%s contains a %s filesystem labelled '%s'\n",
dev, fs_type, fs_label);
else
printf("%s contains a %s filesystem\n",
dev, fs_type);
if (!ask_proceed())
exit(EXIT_FAILURE);
}
blkid_free_probe(pr);
return fd;
} }
static int set_uuid(NihOption *option, const char *arg) static void usage(void)
{ {
if (uuid_parse(arg, uuid.b)) puts("bcache format - create a new bcache filesystem on one or more devices\n"
die("Bad uuid"); "Usage: bcache format [OPTION]... <devices>\n"
return 0; "\n"
"Options:\n"
" -b, --block=size\n"
" --btree_node=size Btree node size, default 256k\n"
" --metadata_checksum_type=(none|crc32c|crc64)\n"
" --data_checksum_type=(none|crc32c|crc64)\n"
" --compression_type=(none|lz4|gzip)\n"
" --encrypted\n"
" --error_action=(continue|readonly|panic)\n"
" Action to take on filesystem error\n"
" -l, --label=label\n"
" --uuid=uuid\n"
" -f, --force\n"
"\n"
"Device specific options:\n"
" --fs_size=size Size of filesystem on device\n"
" --bucket=size bucket size\n"
" --discard Enable discards\n"
" -t, --tier=# tier of subsequent devices\n"
"\n"
" -h, --help display this help and exit\n"
"\n"
"Device specific options must come before corresponding devices, e.g.\n"
" bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc\n"
"\n"
"Report bugs to <linux-bcache@vger.kernel.org>");
exit(EXIT_SUCCESS);
} }
static int set_block_size(NihOption *option, const char *arg) #define OPTS \
{ OPT('b', block_size, required_argument) \
block_size = hatoi_validate(arg, "block size"); OPT(0, btree_node_size, required_argument) \
return 0; OPT(0, metadata_checksum_type, required_argument) \
} OPT(0, data_checksum_type, required_argument) \
OPT(0, compression_type, required_argument) \
OPT(0, encrypted, no_argument) \
OPT('e', error_action, required_argument) \
OPT('L', label, required_argument) \
OPT('U', uuid, required_argument) \
OPT('f', force, no_argument) \
OPT(0, fs_size, required_argument) \
OPT(0, bucket_size, required_argument) \
OPT('t', tier, required_argument) \
OPT(0, discard, no_argument) \
OPT('h', help, no_argument)
static int set_bucket_sizes(NihOption *option, const char *arg) enum {
{ Opt_no_opt = 1,
bucket_size = hatoi_validate(arg, "bucket size"); #define OPT(shortopt, longopt, has_arg) Opt_##longopt,
return 0; OPTS
} #undef OPT
static int set_btree_node_size(NihOption *option, const char *arg)
{
btree_node_size = hatoi_validate(arg, "btree node size");
return 0;
}
static int set_filesystem_size(NihOption *option, const char *arg)
{
filesystem_size = hatoi(arg) >> 9;
return 0;
}
static int set_replacement_policy(NihOption *option, const char *arg)
{
replacement_policy = read_string_list_or_die(arg, replacement_policies,
"replacement policy");
return 0;
}
static int set_csum_type(NihOption *option, const char *arg)
{
unsigned *csum_type = option->value;
*csum_type = read_string_list_or_die(arg, csum_types, "checksum type");
return 0;
}
static int set_compression_type(NihOption *option, const char *arg)
{
compression_type = read_string_list_or_die(arg, compression_types,
"compression type");
return 0;
}
static int set_on_error_action(NihOption *option, const char *arg)
{
on_error_action = read_string_list_or_die(arg, error_actions,
"error action");
return 0;
}
static int set_tier(NihOption *option, const char *arg)
{
tier = strtoul_or_die(arg, CACHE_TIERS, "tier");
return 0;
}
static int set_meta_replicas(NihOption *option, const char *arg)
{
meta_replicas = strtoul_or_die(arg, CACHE_SET_META_REPLICAS_WANT_MAX,
"meta_replicas");
return 0;
}
static int set_data_replicas(NihOption *option, const char *arg)
{
data_replicas = strtoul_or_die(arg, CACHE_SET_DATA_REPLICAS_WANT_MAX,
"data_replicas");
return 0;
}
NihOption opts_format[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
{ 'C', "cache", N_("Format a cache device"),
NULL, "dev", NULL, set_cache },
{ 'w', "block", N_("block size"),
NULL, "size", NULL, set_block_size },
{ 'n', "btree_node", N_("Btree node size, default 256k"),
NULL, "size", NULL, set_btree_node_size },
{ 0, "metadata_csum_type", N_("Checksum type"),
NULL, "(none|crc32c|crc64)", &meta_csum_type, set_csum_type },
{ 0, "data_csum_type", N_("Checksum type"),
NULL, "(none|crc32c|crc64)", &data_csum_type, set_csum_type },
{ 0, "compression_type", N_("Compression type"),
NULL, "(none|gzip)", NULL, set_compression_type },
{ 0, "encrypted", N_("enable encryption"),
NULL, NULL, &encrypted, NULL },
{ 0, "meta_replicas", N_("number of metadata replicas"),
NULL, "#", NULL, set_meta_replicas },
{ 0, "data_replicas", N_("number of data replicas"),
NULL, "#", NULL, set_data_replicas },
{ 0, "error_action", N_("Action to take on filesystem error"),
NULL, "(continue|readonly|panic)", NULL, set_on_error_action },
{ 'l', "label", N_("label"),
NULL, "label", &label, NULL},
{ 0, "uuid", N_("filesystem UUID"),
NULL, "uuid", NULL, set_uuid },
/* Device specific options: */
{ 0, "fs_size", N_("Size of filesystem on device" ),
NULL, "size", NULL, set_filesystem_size },
{ 'b', "bucket", N_("bucket size"),
NULL, "size", NULL, set_bucket_sizes },
{ 't', "tier", N_("tier of subsequent devices"),
NULL, "#", NULL, set_tier },
{ 'p', "cache_replacement_policy", NULL,
NULL, "(lru|fifo|random)", NULL, set_replacement_policy },
{ 0, "discard", N_("Enable discards"),
NULL, NULL, &discard, NULL },
NIH_OPTION_LAST
}; };
int cmd_format(NihCommand *command, char * const *args) static const struct option format_opts[] = {
{ #define OPT(shortopt, longopt, has_arg) { \
char *passphrase = NULL; #longopt, has_arg, NULL, Opt_##longopt \
},
OPTS
#undef OPT
{ NULL }
};
if (!darray_size(cache_devices)) int cmd_format(int argc, char *argv[])
{
darray(struct dev_opts) devices;
struct dev_opts *dev;
unsigned block_size = 0;
unsigned btree_node_size = 0;
unsigned meta_csum_type = BCH_CSUM_CRC32C;
unsigned data_csum_type = BCH_CSUM_CRC32C;
unsigned compression_type = BCH_COMPRESSION_NONE;
bool encrypted = false;
unsigned on_error_action = BCH_ON_ERROR_RO;
char *label = NULL;
uuid_le uuid;
bool force = false;
/* Device specific options: */
u64 filesystem_size = 0;
unsigned bucket_size = 0;
unsigned tier = 0;
bool discard = false;
char *passphrase = NULL;
int opt;
darray_init(devices);
uuid_clear(uuid.b);
while ((opt = getopt_long(argc, argv,
"-b:e:L:U:ft:h",
format_opts,
NULL)) != -1)
switch (opt) {
case Opt_block_size:
case 'b':
block_size = hatoi_validate(optarg,
"block size");
break;
case Opt_btree_node_size:
btree_node_size = hatoi_validate(optarg,
"btree node size");
break;
case Opt_metadata_checksum_type:
meta_csum_type = read_string_list_or_die(optarg,
csum_types, "checksum type");
break;
case Opt_data_checksum_type:
data_csum_type = read_string_list_or_die(optarg,
csum_types, "checksum type");
break;
case Opt_compression_type:
compression_type = read_string_list_or_die(optarg,
compression_types, "compression type");
break;
case Opt_encrypted:
encrypted = true;
break;
case Opt_error_action:
case 'e':
on_error_action = read_string_list_or_die(optarg,
error_actions, "error action");
break;
case Opt_label:
case 'L':
label = strdup(optarg);
break;
case Opt_uuid:
case 'U':
if (uuid_parse(optarg, uuid.b))
die("Bad uuid");
break;
case Opt_force:
case 'f':
force = true;
break;
case Opt_fs_size:
filesystem_size = hatoi(optarg) >> 9;
break;
case Opt_bucket_size:
bucket_size = hatoi_validate(optarg, "bucket size");
break;
case Opt_tier:
case 't':
tier = strtoul_or_die(optarg, CACHE_TIERS, "tier");
break;
case Opt_discard:
discard = true;
break;
case Opt_no_opt:
darray_append(devices, (struct dev_opts) {
.path = strdup(optarg),
.size = filesystem_size,
.bucket_size = bucket_size,
.tier = tier,
.discard = discard,
});
break;
case Opt_help:
case 'h':
usage();
break;
}
if (!darray_size(devices))
die("Please supply a device"); die("Please supply a device");
if (uuid_is_null(uuid.b)) if (uuid_is_null(uuid.b))
@ -216,15 +258,18 @@ int cmd_format(NihCommand *command, char * const *args)
free(pass2); free(pass2);
} }
bcache_format(cache_devices.item, darray_size(cache_devices), darray_foreach(dev, devices)
dev->fd = open_for_format(dev->path, force);
bcache_format(devices.item, darray_size(devices),
block_size, block_size,
btree_node_size, btree_node_size,
meta_csum_type, meta_csum_type,
data_csum_type, data_csum_type,
compression_type, compression_type,
passphrase, passphrase,
meta_replicas, 1,
data_replicas, 1,
on_error_action, on_error_action,
label, label,
uuid); uuid);

View File

@ -1,7 +0,0 @@
#ifndef _BCACHE_FORMAT_H
#define _BCACHE_FORMAT_H
extern NihOption opts_format[];
int cmd_format(NihCommand *, char * const *);
#endif /* _BCACHE_FORMAT_H */

View File

@ -1,9 +1,7 @@
#include <nih/command.h>
#include <nih/option.h> #include <nih/option.h>
#include "bcache.h" #include "bcache.h"
#include "bcache-fs.h"
struct bcache_fs { struct bcache_fs {
/* options... */ /* options... */
@ -20,13 +18,14 @@ static struct bcache_fs fill_fs(struct bcache_handle fs)
}; };
} }
NihOption opts_fs_show[] = { int cmd_fs_show(int argc, char *argv[])
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
int cmd_fs_show(NihCommand *command, char *const *args)
{ {
NihOption opts[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) != 1) if (nr_args(args) != 1)
die("Please supply a filesystem"); die("Please supply a filesystem");
@ -35,13 +34,14 @@ int cmd_fs_show(NihCommand *command, char *const *args)
return 0; return 0;
} }
NihOption opts_fs_set[] = { int cmd_fs_set(int argc, char *argv[])
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
int cmd_fs_set(NihCommand *command, char *const *args)
{ {
NihOption opts[] = {
// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter}
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) < 1) if (nr_args(args) < 1)
die("Please supply a filesystem"); die("Please supply a filesystem");

View File

@ -1,10 +0,0 @@
#ifndef _BCACHE_FS_H
#define _BCACHE_FS_H
extern NihOption opts_fs_show[];
int cmd_fs_show(NihCommand *, char * const *);
extern NihOption opts_fs_set[];
int cmd_fs_set(NihCommand *, char * const *);
#endif /* _BCACHE_FS_H */

View File

@ -9,12 +9,13 @@
#include "libbcache.h" #include "libbcache.h"
#include "crypto.h" #include "crypto.h"
NihOption opts_unlock[] = { int cmd_unlock(int argc, char *argv[])
NIH_OPTION_LAST
};
int cmd_unlock(NihCommand *command, char * const *args)
{ {
NihOption opts[] = {
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
struct bcache_disk_key disk_key; struct bcache_disk_key disk_key;
struct bcache_key key; struct bcache_key key;
struct cache_sb sb; struct cache_sb sb;
@ -38,7 +39,7 @@ int cmd_unlock(NihCommand *command, char * const *args)
passphrase = read_passphrase("Enter passphrase: "); passphrase = read_passphrase("Enter passphrase: ");
derive_passphrase(&key, passphrase); derive_passphrase(&key, passphrase);
disk_key_encrypt(&disk_key, &key); disk_key_encrypt(&sb, &disk_key, &key);
if (memcmp(&disk_key, bch_key_header, sizeof(bch_key_header))) if (memcmp(&disk_key, bch_key_header, sizeof(bch_key_header)))
die("incorrect passphrase"); die("incorrect passphrase");

View File

@ -1,7 +0,0 @@
#ifndef _BCACHE_KEY_H
#define _BCACHE_KEY_H
extern NihOption opts_unlock[];
int cmd_unlock(NihCommand *, char * const *);
#endif /* _BCACHE_KEY_H */

View File

@ -9,29 +9,29 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
#include <nih/command.h>
#include <nih/option.h> #include <nih/option.h>
#include <uuid/uuid.h> #include <uuid/uuid.h>
#include "bcache.h" #include "bcache.h"
#include "bcache-run.h"
NihOption opts_run[] = { int cmd_run(int argc, char *argv[])
NIH_OPTION_LAST
};
int cmd_run(NihCommand *command, char *const *args)
{ {
NihOption opts[] = {
NIH_OPTION_LAST
};
bch_nih_init(argc, argv, opts);
return 0; return 0;
} }
NihOption opts_stop[] = { int cmd_stop(int argc, char *argv[])
NIH_OPTION_LAST
};
int cmd_stop(NihCommand *command, char *const *args)
{ {
NihOption opts[] = {
NIH_OPTION_LAST
};
char **args = bch_nih_init(argc, argv, opts);
if (nr_args(args) != 1) if (nr_args(args) != 1)
die("Please supply a filesystem"); die("Please supply a filesystem");

View File

@ -1,10 +0,0 @@
#ifndef _BCACHE_RUN_H
#define _BCACHE_RUN_H
extern NihOption opts_run[];
int cmd_run(NihCommand *, char * const *);
extern NihOption opts_stop[];
int cmd_stop(NihCommand *, char * const *);
#endif /* _BCACHE_RUN_H */

140
bcache.c
View File

@ -6,10 +6,6 @@
* GPLv2 * GPLv2
*/ */
#include <nih/option.h>
#include <nih/command.h>
#include <nih/main.h>
#include <nih/logging.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
@ -26,16 +22,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include "bcache.h" #include "bcache.h"
#include "bcache-assemble.h"
#include "bcache-device.h"
#include "bcache-format.h"
#include "bcache-fs.h"
#include "bcache-run.h"
#include "bcache-key.h"
#define PACKAGE_NAME "bcache"
#define PACKAGE_VERSION "1.0"
#define PACKAGE_BUGREPORT "linux-bcache@vger.kernel.org"
const char * const cache_state[] = { const char * const cache_state[] = {
"active", "active",
@ -89,82 +75,70 @@ const char * const bdev_state[] = {
NULL NULL
}; };
#define CMD(_command, _usage, _synopsis) \ static void usage(void)
{ \ {
.command = #_command, \ puts("bcache - tool for managing bcache volumes/filesystems\n"
.usage = _usage, \ "usage: bcache <command> [<args>]\n"
.synopsis = _synopsis, \ "\n"
.help = NULL, \ "Commands for formatting, startup and shutdown\n"
.group = NULL, \ " format Format a new filesystem\n"
.options = opts_##_command, \ " unlock Unlock an encrypted filesystem prior to running/mounting\n"
.action = cmd_##_command, \ " assemble Assemble an existing multi device filesystem\n"
" incremental Incrementally assemble an existing multi device filesystem\n"
" run Start a partially assembled filesystem\n"
" stop Stop a running filesystem\n"
"\n"
"Commands for managing a running filesystem\n"
" fs_show Show various information about a filesystem\n"
" fs_set Modify filesystem options\n"
"\n"
"Commands for managing a specific device in a filesystem\n"
" device_show Show information about a formatted device\n"
" device_add Add a device to an existing (running) filesystem\n"
" device_remove Remove a device from an existing (running) filesystem\n");
exit(EXIT_SUCCESS);
} }
static NihCommand commands[] = {
CMD(format, N_("<list of devices>"),
"Create a new bcache volume from one or more devices"),
/* Bringup, shutdown */
CMD(assemble, N_("<devices>"),
"Assembles one or more devices into a bcache volume"),
CMD(incremental, N_("<device"),
"Incrementally assemble a bcache filesystem"),
CMD(run, N_("<volume>"),
"Start a partially assembled volume"),
CMD(stop, N_("<volume>"),
"Stops a running bcache volume"),
/* Filesystem commands: */
CMD(fs_show, N_("<fs>"),
"Show information about a filesystem"),
CMD(fs_set, N_("<fs>"),
"Change various filesystem options"),
/* Device commands: */
CMD(device_show, N_("<fs>"),
"Show information about component devices of a filesystem"),
CMD(device_add, N_("<volume> <devices>"),
"Adds a list of devices to a volume"),
CMD(device_remove, N_("<volume> <devices>"),
"Removes a device from its volume"),
/* Crypto */
CMD(unlock, N_("<device>"),
"Unlock an encrypted filesystem"),
#if 0
CMD(modify, N_("<options>"),
"Modifies attributes related to the volume",
N_("Modifies attributes related to the volume")),
CMD(list, N_("list-cachesets"),
"Lists cachesets in /sys/fs/bcache"),
CMD(query, N_("query <list of devices>"),
"Gives info about the superblock of a list of devices"),
CMD(status, N_("status <list of devices>"),
"Finds the status of the most up to date superblock"),
#endif
NIH_COMMAND_LAST
};
static NihOption options[] = {
NIH_OPTION_LAST
};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
nih_main_init(argv[0]); char *cmd;
nih_option_set_synopsis(_("Manage bcache devices"));
nih_option_set_help( _("Helps you manage bcache devices"));
int ret = nih_command_parser(NULL, argc, argv, options, commands); if (argc < 2) {
if (ret < 0) printf("%s: missing command\n", argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
nih_signal_reset(); cmd = argv[1];
memmove(&argv[1], &argv[2], argc * sizeof(argv[0]));
argc--;
if (!strcmp(cmd, "format"))
return cmd_format(argc, argv);
if (!strcmp(cmd, "assemble"))
return cmd_assemble(argc, argv);
if (!strcmp(cmd, "incremental"))
return cmd_incremental(argc, argv);
if (!strcmp(cmd, "run"))
return cmd_run(argc, argv);
if (!strcmp(cmd, "stop"))
return cmd_stop(argc, argv);
if (!strcmp(cmd, "fs_show"))
return cmd_fs_show(argc, argv);
if (!strcmp(cmd, "fs_set"))
return cmd_fs_set(argc, argv);
if (!strcmp(cmd, "device_show"))
return cmd_device_show(argc, argv);
if (!strcmp(cmd, "device_add"))
return cmd_device_add(argc, argv);
if (!strcmp(cmd, "device_remove"))
return cmd_device_remove(argc, argv);
if (!strcmp(cmd, "unlock"))
return cmd_unlock(argc, argv);
usage();
return 0; return 0;
} }

View File

@ -17,4 +17,19 @@ extern const char * const error_actions[];
extern const char * const bdev_cache_mode[]; extern const char * const bdev_cache_mode[];
extern const char * const bdev_state[]; extern const char * const bdev_state[];
int cmd_format(int argc, char *argv[]);
int cmd_unlock(int argc, char *argv[]);
int cmd_assemble(int argc, char *argv[]);
int cmd_incremental(int argc, char *argv[]);
int cmd_run(int argc, char *argv[]);
int cmd_stop(int argc, char *argv[]);
int cmd_fs_show(int argc, char *argv[]);
int cmd_fs_set(int argc, char *argv[]);
int cmd_device_show(int argc, char *argv[]);
int cmd_device_add(int argc, char *argv[]);
int cmd_device_remove(int argc, char *argv[]);
#endif /* _BCACHE_H */ #endif /* _BCACHE_H */

View File

@ -21,7 +21,6 @@ char *read_passphrase(const char *prompt)
struct termios old, new; struct termios old, new;
char *buf = NULL; char *buf = NULL;
size_t buflen = 0; size_t buflen = 0;
ssize_t ret;
fprintf(stderr, "%s", prompt); fprintf(stderr, "%s", prompt);
fflush(stderr); fflush(stderr);
@ -34,8 +33,7 @@ char *read_passphrase(const char *prompt)
if (tcsetattr(fileno(stdin), TCSAFLUSH, &new)) if (tcsetattr(fileno(stdin), TCSAFLUSH, &new))
die("error setting terminal attrs"); die("error setting terminal attrs");
ret = getline(&buf, &buflen, stdin); if (getline(&buf, &buflen, stdin) <= 0)
if (ret <= 0)
die("error reading passphrase"); die("error reading passphrase");
tcsetattr(fileno(stdin), TCSAFLUSH, &old); tcsetattr(fileno(stdin), TCSAFLUSH, &old);

View File

@ -59,12 +59,12 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs,
if (!block_size) if (!block_size)
for (i = devs; i < devs + nr_devs; i++) for (i = devs; i < devs + nr_devs; i++)
block_size = max(block_size, block_size = max(block_size,
get_blocksize(i->dev, i->fd)); get_blocksize(i->path, i->fd));
/* calculate bucket sizes: */ /* calculate bucket sizes: */
for (i = devs; i < devs + nr_devs; i++) { for (i = devs; i < devs + nr_devs; i++) {
if (!i->size) if (!i->size)
i->size = get_size(i->dev, i->fd); i->size = get_size(i->path, i->fd);
if (!i->bucket_size) { if (!i->bucket_size) {
u64 bytes = i->size << 9; u64 bytes = i->size << 9;
@ -125,8 +125,7 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs,
SET_CACHE_SET_DATA_REPLICAS_WANT(sb, data_replicas); SET_CACHE_SET_DATA_REPLICAS_WANT(sb, data_replicas);
SET_CACHE_SET_DATA_REPLICAS_HAVE(sb, data_replicas); SET_CACHE_SET_DATA_REPLICAS_HAVE(sb, data_replicas);
SET_CACHE_SET_ERROR_ACTION(sb, on_error_action); SET_CACHE_SET_ERROR_ACTION(sb, on_error_action);
SET_CACHE_SET_STR_HASH_TYPE(sb, BCH_STR_HASH_SIPHASH);
SET_CACHE_SET_STR_HASH_TYPE(sb, BCH_STR_HASH_SIPHASH);
if (passphrase) { if (passphrase) {
struct bcache_key key; struct bcache_key key;
@ -153,7 +152,7 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs,
m->bucket_size = __cpu_to_le16(i->bucket_size); m->bucket_size = __cpu_to_le16(i->bucket_size);
SET_CACHE_TIER(m, i->tier); SET_CACHE_TIER(m, i->tier);
SET_CACHE_REPLACEMENT(m, i->replacement_policy); SET_CACHE_REPLACEMENT(m, CACHE_REPLACEMENT_LRU);
SET_CACHE_DISCARD(m, i->discard); SET_CACHE_DISCARD(m, i->discard);
} }

View File

@ -6,11 +6,10 @@
struct dev_opts { struct dev_opts {
int fd; int fd;
const char *dev; const char *path;
u64 size; /* 512 byte sectors */ u64 size; /* 512 byte sectors */
unsigned bucket_size; unsigned bucket_size;
unsigned tier; unsigned tier;
unsigned replacement_policy;
bool discard; bool discard;
u64 first_bucket; u64 first_bucket;

62
util.c
View File

@ -12,7 +12,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <blkid.h>
#include <uuid/uuid.h> #include <uuid/uuid.h>
#include "ccan/crc/crc.h" #include "ccan/crc/crc.h"
@ -248,32 +247,6 @@ unsigned get_blocksize(const char *path, int fd)
return ret >> 9; return ret >> 9;
} }
/* Open a block device, do magic blkid stuff: */
int dev_open(const char *dev)
{
blkid_probe pr;
int fd;
if ((fd = open(dev, O_RDWR|O_EXCL)) == -1)
die("Can't open dev %s: %s\n", dev, strerror(errno));
if (!(pr = blkid_new_probe()))
die("Failed to create a new probe");
if (blkid_probe_set_device(pr, fd, 0, 0))
die("failed to set probe to device");
/* enable ptable probing; superblock probing is enabled by default */
if (blkid_probe_enable_partitions(pr, true))
die("Failed to enable partitions on probe");
if (!blkid_do_probe(pr))
/* XXX wipefs doesn't know how to remove partition tables */
die("Device %s already has a non-bcache superblock, "
"remove it using wipefs and wipefs -a\n", dev);
return fd;
}
/* Checksums: */ /* Checksums: */
/* /*
@ -488,8 +461,43 @@ struct bcache_handle bcache_fs_open(const char *path)
return ret; return ret;
} }
bool ask_proceed(void)
{
const char *short_yes = "yY";
char *buf = NULL;
size_t buflen = 0;
bool ret;
fputs("Proceed anyway? (y,n) ", stdout);
if (getline(&buf, &buflen, stdin) < 0)
die("error reading from standard input");
ret = strchr(short_yes, buf[0]);
free(buf);
return ret;
}
void memzero_explicit(void *buf, size_t len) void memzero_explicit(void *buf, size_t len)
{ {
void *(* volatile memset_s)(void *s, int c, size_t n) = memset; void *(* volatile memset_s)(void *s, int c, size_t n) = memset;
memset_s(buf, 0, len); memset_s(buf, 0, len);
} }
/* libnih options: */
#include <nih/option.h>
#include <nih/main.h>
#define PACKAGE_NAME "bcache"
#define PACKAGE_VERSION "1.0"
#define PACKAGE_BUGREPORT "linux-bcache@vger.kernel.org"
char **bch_nih_init(int argc, char *argv[], NihOption *options)
{
nih_main_init(argv[0]);
nih_option_set_synopsis(_("Manage bcache devices"));
nih_option_set_help( _("Helps you manage bcache devices"));
return nih_option_parser(NULL, argc, argv, options, 0);
}

8
util.h
View File

@ -1,6 +1,7 @@
#ifndef _UTIL_H #ifndef _UTIL_H
#define _UTIL_H #define _UTIL_H
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
@ -59,8 +60,6 @@ void print_string_list(const char * const[], size_t);
u64 get_size(const char *, int); u64 get_size(const char *, int);
unsigned get_blocksize(const char *, int); unsigned get_blocksize(const char *, int);
int dev_open(const char *);
#include "bcache-ondisk.h" #include "bcache-ondisk.h"
#include "bcache-ioctl.h" #include "bcache-ioctl.h"
@ -93,6 +92,11 @@ struct bcache_handle {
struct bcache_handle bcache_fs_open(const char *); struct bcache_handle bcache_fs_open(const char *);
bool ask_proceed(void);
void memzero_explicit(void *, size_t); void memzero_explicit(void *, size_t);
struct nih_option;
char **bch_nih_init(int argc, char *argv[], struct nih_option *options);
#endif /* _UTIL_H */ #endif /* _UTIL_H */