PKGCONFIG_LIBS="blkid uuid"
CFLAGS+=`pkg-config --cflags ${PKGCONFIG_LIBS}`
-LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lscrypt -lsodium -lkeyutils -lm
+LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lm
ifeq ($(PREFIX),/usr)
ROOT_SBINDIR=/sbin
$(AR) r $@ $(CCANOBJS)
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 util.o
+ bcache-fs.o bcache-run.o libbcache.o util.o
-include $(bcache-objs:.o=.d)
.PHONY: deb
deb: all
- debuild -nc -us -uc -i -I
+ debuild --unsigned-source \
+ --unsigned-changes \
+ --no-pre-clean \
+ --build=binary \
+ --diff-ignore \
+ --tar-ignore
#include "bcache.h"
#include "libbcache.h"
-#include "crypto.h"
/* Open a block device, do magic blkid stuff: */
static int open_for_format(const char *dev, bool force)
" --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"
+ " --max_journal_entry_size=size\n"
" -l, --label=label\n"
" --uuid=uuid\n"
" -f, --force\n"
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(0, max_journal_entry_size, required_argument) \
OPT('L', label, required_argument) \
OPT('U', uuid, required_argument) \
OPT('f', force, no_argument) \
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;
unsigned bucket_size = 0;
unsigned tier = 0;
bool discard = false;
+ unsigned max_journal_entry_size = 0;
char *passphrase = NULL;
int opt;
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_max_journal_entry_size:
+ max_journal_entry_size = hatoi_validate(optarg,
+ "journal entry size");
+ break;
case Opt_label:
case 'L':
label = strdup(optarg);
if (uuid_is_null(uuid.b))
uuid_generate(uuid.b);
- if (encrypted) {
- char *pass2;
-
- passphrase = read_passphrase("Enter passphrase: ");
- pass2 = read_passphrase("Enter same passphrase again: ");
-
- if (strcmp(passphrase, pass2)) {
- memzero_explicit(passphrase, strlen(passphrase));
- memzero_explicit(pass2, strlen(pass2));
- die("Passphrases do not match");
- }
-
- memzero_explicit(pass2, strlen(pass2));
- free(pass2);
- }
-
darray_foreach(dev, devices)
dev->fd = open_for_format(dev->path, force);
meta_csum_type,
data_csum_type,
compression_type,
- passphrase,
1,
1,
on_error_action,
+ max_journal_entry_size,
label,
uuid);
+++ /dev/null
-#include <errno.h>
-#include <unistd.h>
-#include <keyutils.h>
-#include <uuid/uuid.h>
-
-#include "bcache.h"
-#include "libbcache.h"
-#include "crypto.h"
-
-int cmd_unlock(int argc, char *argv[])
-{
- struct bcache_disk_key disk_key;
- struct bcache_key key;
- struct cache_sb *sb;
- char *passphrase;
- char uuid[40];
- char description[60];
-
- if (argc != 2)
- die("please supply a single device");
-
- sb = bcache_super_read(argv[1]);
-
- if (!CACHE_SET_ENCRYPTION_KEY(sb))
- die("filesystem is not encrypted");
-
- memcpy(&disk_key, sb->encryption_key, sizeof(disk_key));
-
- if (!memcmp(&disk_key, bch_key_header, sizeof(bch_key_header)))
- die("filesystem does not have encryption key");
-
- passphrase = read_passphrase("Enter passphrase: ");
-
- derive_passphrase(&key, passphrase);
- disk_key_encrypt(sb, &disk_key, &key);
-
- if (memcmp(&disk_key, bch_key_header, sizeof(bch_key_header)))
- die("incorrect passphrase");
-
- uuid_unparse_lower(sb->user_uuid.b, uuid);
- sprintf(description, "bcache:%s", uuid);
-
- if (add_key("logon", description, &key, sizeof(key),
- KEY_SPEC_USER_KEYRING) < 0)
- die("add_key error: %s", strerror(errno));
-
- memzero_explicit(&disk_key, sizeof(disk_key));
- memzero_explicit(&key, sizeof(key));
- memzero_explicit(passphrase, strlen(passphrase));
- free(passphrase);
- return 0;
-}
*/
LE64_BITMASK(CACHE_SET_CLEAN, struct cache_sb, flags2, 6, 7);
-/*
- * If nonzero, encryption is enabled; overrides DATA/META_CSUM_TYPE. Also
- * indicates encryption algorithm in use, if/when we get more than one:
- *
- */
-LE64_BITMASK(CACHE_SET_ENCRYPTION_TYPE, struct cache_sb, flags2, 6, 10);
-
-/*
- * If nonzero, we have an encryption key in the superblock, which is the key
- * used to encrypt all other data/metadata. The key will normally be encrypted
- * with the key userspace provides, but if encryption has been turned off we'll
- * just store the master key unencrypted in the superblock so we can access the
- * previously encrypted data.
- */
-LE64_BITMASK(CACHE_SET_ENCRYPTION_KEY, struct cache_sb, flags2, 10, 11);
+LE64_BITMASK(CACHE_SET_JOURNAL_ENTRY_SIZE, struct cache_sb, flags2, 7, 15);
/* options: */
"\n"
"Commands for formatting, startup and shutdown\n"
" format Format a new filesystem\n"
- " unlock Unlock an encrypted filesystem prior to running/mounting\n"
" assemble Assemble an existing multi device filesystem\n"
" incremental Incrementally assemble an existing multi device filesystem\n"
" run Start a partially assembled filesystem\n"
if (!strcmp(cmd, "device_remove"))
return cmd_device_remove(argc, argv);
- if (!strcmp(cmd, "unlock"))
- return cmd_unlock(argc, argv);
-
usage();
return 0;
}
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[]);
+++ /dev/null
-#include <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <linux/random.h>
-#include <libscrypt.h>
-#include <sodium/crypto_stream_chacha20.h>
-
-#include "crypto.h"
-
-char *read_passphrase(const char *prompt)
-{
- struct termios old, new;
- char *buf = NULL;
- size_t buflen = 0;
-
- fprintf(stderr, "%s", prompt);
- fflush(stderr);
-
- if (tcgetattr(fileno(stdin), &old))
- die("error getting terminal attrs");
-
- new = old;
- new.c_lflag &= ~ECHO;
- if (tcsetattr(fileno(stdin), TCSAFLUSH, &new))
- die("error setting terminal attrs");
-
- if (getline(&buf, &buflen, stdin) <= 0)
- die("error reading passphrase");
-
- tcsetattr(fileno(stdin), TCSAFLUSH, &old);
- fprintf(stderr, "\n");
- return buf;
-}
-
-void derive_passphrase(struct bcache_key *key, const char *passphrase)
-{
- const unsigned char salt[] = "bcache";
- int ret;
-
- ret = libscrypt_scrypt((void *) passphrase, strlen(passphrase),
- salt, sizeof(salt),
- SCRYPT_N, SCRYPT_r, SCRYPT_p,
- (void *) key, sizeof(*key));
- if (ret)
- die("scrypt error: %i", ret);
-}
-
-void disk_key_encrypt(struct cache_sb *sb,
- struct bcache_disk_key *disk_key,
- struct bcache_key *key)
-{
- __le32 nonce[2];
- int ret;
-
- memcpy(nonce, &sb->set_magic, sizeof(sb->set_magic));
-
- ret = crypto_stream_chacha20_xor((void *) disk_key,
- (void *) disk_key, sizeof(*disk_key),
- (void *) nonce,
- (void *) key);
- if (ret)
- die("chacha20 error: %i", ret);
-}
-
-void disk_key_init(struct bcache_disk_key *disk_key)
-{
- ssize_t ret;
-
- memcpy(&disk_key->header, bch_key_header, sizeof(bch_key_header));
-#if 0
- ret = getrandom(disk_key->key, sizeof(disk_key->key), GRND_RANDOM);
- if (ret != sizeof(disk_key->key))
- die("error getting random bytes for key");
-#else
- int fd = open("/dev/random", O_RDONLY|O_NONBLOCK);
- if (fd < 0)
- die("error opening /dev/random");
-
- size_t n = 0;
- struct timespec start;
- bool printed = false;
-
- clock_gettime(CLOCK_MONOTONIC, &start);
-
- while (n < sizeof(disk_key->key)) {
- struct timeval timeout = { 1, 0 };
- fd_set set;
-
- FD_ZERO(&set);
- FD_SET(fd, &set);
-
- if (select(fd + 1, &set, NULL, NULL, &timeout) < 0)
- die("select error");
-
- ret = read(fd,
- (void *) disk_key->key + n,
- sizeof(disk_key->key) - n);
- if (ret == -1 && errno != EINTR && errno != EAGAIN)
- die("error reading from /dev/random");
- if (ret > 0)
- n += ret;
-
- struct timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
-
- now.tv_sec -= start.tv_sec;
- now.tv_nsec -= start.tv_nsec;
-
- while (now.tv_nsec < 0) {
- long nsec_per_sec = 1000 * 1000 * 1000;
- long sec = now.tv_nsec / nsec_per_sec - 1;
- now.tv_nsec -= sec * nsec_per_sec;
- now.tv_sec += sec;
- }
-
- if (!printed && now.tv_sec >= 3) {
- printf("Reading from /dev/random is taking a long time...\n)");
- printed = true;
- }
- }
- close(fd);
-#endif
-}
+++ /dev/null
-#ifndef _CRYPTO_H
-#define _CRYPTO_H
-
-#include "util.h"
-
-struct bcache_key {
- u64 key[4];
-};
-
-struct bcache_disk_key {
- u64 header;
- u64 key[4];
-};
-
-static const char bch_key_header[8] = BCACHE_MASTER_KEY_HEADER;
-static const struct nonce bch_master_key_nonce = BCACHE_MASTER_KEY_NONCE;
-
-char *read_passphrase(const char *);
-void derive_passphrase(struct bcache_key *, const char *);
-void disk_key_encrypt(struct cache_sb *sb, struct bcache_disk_key *,
- struct bcache_key *);
-void disk_key_init(struct bcache_disk_key *);
-
-#endif /* _CRYPTO_H */
#include "bcache-ondisk.h"
#include "libbcache.h"
-#include "crypto.h"
const char * const cache_state[] = {
"active",
unsigned meta_csum_type,
unsigned data_csum_type,
unsigned compression_type,
- const char *passphrase,
unsigned meta_replicas,
unsigned data_replicas,
unsigned on_error_action,
+ unsigned max_journal_entry_size,
char *label,
uuid_le uuid)
{
btree_node_size = min(btree_node_size, i->bucket_size);
}
+ if (!max_journal_entry_size) {
+ /* 2 MB default: */
+ max_journal_entry_size = 4096;
+ }
+
+ max_journal_entry_size = roundup_pow_of_two(max_journal_entry_size);
+
sb = calloc(1, sizeof(*sb) + sizeof(struct cache_member) * nr_devs);
sb->offset = __cpu_to_le64(SB_SECTOR);
SET_CACHE_SET_DATA_REPLICAS_HAVE(sb, data_replicas);
SET_CACHE_SET_ERROR_ACTION(sb, on_error_action);
SET_CACHE_SET_STR_HASH_TYPE(sb, BCH_STR_HASH_SIPHASH);
-
- if (passphrase) {
- struct bcache_key key;
- struct bcache_disk_key disk_key;
-
- derive_passphrase(&key, passphrase);
- disk_key_init(&disk_key);
- disk_key_encrypt(sb, &disk_key, &key);
-
- memcpy(sb->encryption_key, &disk_key, sizeof(disk_key));
- SET_CACHE_SET_ENCRYPTION_TYPE(sb, 1);
- SET_CACHE_SET_ENCRYPTION_KEY(sb, 1);
-
- memzero_explicit(&disk_key, sizeof(disk_key));
- memzero_explicit(&key, sizeof(key));
- }
+ SET_CACHE_SET_JOURNAL_ENTRY_SIZE(sb, ilog2(max_journal_entry_size));
for (i = devs; i < devs + nr_devs; i++) {
struct cache_member *m = sb->members + (i - devs);
"Version: %llu\n"
"Block_size: %s\n"
"Btree node size: %s\n"
+ "Max journal entry size: %s\n"
"Error action: %s\n"
"Clean: %llu\n"
le64_to_cpu(sb->version),
pr_units(le16_to_cpu(sb->block_size), units).b,
pr_units(CACHE_SET_BTREE_NODE_SIZE(sb), units).b,
+ pr_units(1U << CACHE_SET_JOURNAL_ENTRY_SIZE(sb), units).b,
CACHE_SET_ERROR_ACTION(sb) < BCH_NR_ERROR_ACTIONS
? error_actions[CACHE_SET_ERROR_ACTION(sb)]
unsigned meta_csum_type,
unsigned data_csum_type,
unsigned compression_type,
- const char *passphrase,
unsigned meta_replicas,
unsigned data_replicas,
unsigned on_error_action,
+ unsigned max_journal_entry_size,
char *label,
uuid_le uuid);
#include <alloca.h>
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
/* Integer stuff: */
-u64 rounddown_pow_of_two(u64 n)
-{
- u64 ret;
-
- do {
- ret = n;
- n &= n - 1;
- } while (n);
-
- return ret;
-}
-
unsigned ilog2(u64 n)
{
unsigned ret = 0;
- while (n) {
+ assert(n > 0);
+
+ while (n > 1) {
ret++;
n >>= 1;
}
return ret;
}
+u64 rounddown_pow_of_two(u64 n)
+{
+ return 1ULL << ilog2(n);
+}
+
+u64 roundup_pow_of_two(u64 n)
+{
+ return 1ULL << (ilog2(n - 1) + 1);
+}
+
char *skip_spaces(const char *str)
{
while (isspace(*str))
(void) (&_max1 == &_max2); \
_max1 > _max2 ? _max1 : _max2; })
+#define max_t(type, x, y) ({ \
+ type __max1 = (x); \
+ type __max2 = (y); \
+ __max1 > __max2 ? __max1: __max2; })
+
#define die(arg, ...) \
do { \
fprintf(stderr, arg "\n", ##__VA_ARGS__); \
exit(EXIT_FAILURE); \
} while (0)
-u64 rounddown_pow_of_two(u64);
unsigned ilog2(u64);
+u64 rounddown_pow_of_two(u64);
+u64 roundup_pow_of_two(u64);
char *skip_spaces(const char *str);
char *strim(char *s);