bcacheadm add list-cachesets and query-devs

Change-Id: Ie2bc7ba8293d1d493c0a215119456e4bb9e659aa
Signed-off-by: Jacob Malevich <jam@daterainc.com>
This commit is contained in:
Jacob Malevich 2014-10-15 19:00:40 -07:00
parent 82ac2a0338
commit bc69c8fe04
3 changed files with 198 additions and 99 deletions

155
bcache.c
View File

@ -15,12 +15,17 @@
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <uuid/uuid.h>
#include <blkid.h>
#include "bcache.h"
#define __KERNEL__
#include <linux/bcache-ioctl.h>
#undef __KERNEL__
const char * const cache_state[] = {
"active",
"ro",
@ -802,7 +807,7 @@ void show_super_backingdev(struct cache_sb *sb, bool force_csum)
bdev_state[BDEV_STATE(sb)]);
}
void show_cache_member(struct cache_sb *sb, unsigned i)
static void show_cache_member(struct cache_sb *sb, unsigned i)
{
struct cache_member *m = ((struct cache_member *) sb->d) + i;
@ -845,3 +850,151 @@ void show_super_cache(struct cache_sb *sb, bool force_csum)
show_cache_member(sb, sb->nr_this_dev);
}
void query_dev(char *dev, bool force_csum)
{
struct cache_sb sb_stack, *sb = &sb_stack;
size_t bytes = sizeof(*sb);
int fd = open(dev, O_RDONLY);
if (fd < 0) {
printf("Can't open dev %s: %s\n", dev, strerror(errno));
exit(2);
}
if (pread(fd, sb, bytes, SB_START) != bytes) {
fprintf(stderr, "Couldn't read\n");
exit(2);
}
if (sb->keys) {
bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t);
sb = malloc(bytes);
if (pread(fd, sb, bytes, SB_START) != bytes) {
fprintf(stderr, "Couldn't read\n");
exit(2);
}
}
if (!SB_IS_BDEV(sb))
show_super_cache(sb, force_csum);
else
show_super_backingdev(sb, force_csum);
}
int list_cachesets(char *cset_dir)
{
struct dirent *ent;
DIR *dir = opendir(cset_dir);
if (!dir) {
fprintf(stderr, "Failed to open dir %s\n", cset_dir);
return 1;
}
while ((ent = readdir(dir)) != NULL) {
struct stat statbuf;
char entry[100];
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
strcpy(entry, cset_dir);
strcat(entry, "/");
strcat(entry, ent->d_name);
if(stat(entry, &statbuf) == -1) {
fprintf(stderr, "Failed to stat %s\n", entry);
return 1;
}
if (S_ISDIR(statbuf.st_mode)) {
printf("%s\n", ent->d_name);
}
}
closedir(dir);
return 0;
}
char *parse_array_to_list(char *const *args)
{
int i, len = 0;
char *space = " ";
for(i=0; args[i] != NULL; i++) {
len+=strlen(args[i]) + 1;
}
char *arg_list = (char*)malloc(sizeof(char)*len);
strcpy(arg_list, args[0]);
strcat(arg_list, space);
for(i=1; args[i] != NULL; i++) {
strcat(arg_list, args[i]);
strcat(arg_list, space);
}
return arg_list;
}
int register_bcache(char *devs)
{
int ret, bcachefd;
bcachefd = open("/dev/bcache", O_RDWR);
if (bcachefd < 0) {
perror("Can't open bcache device");
exit(EXIT_FAILURE);
}
ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, devs);
if (ret < 0) {
fprintf(stderr, "ioctl error %d", ret);
exit(EXIT_FAILURE);
}
return 0;
}
int probe(char *dev, int udev)
{
struct cache_sb sb;
char uuid[40];
blkid_probe pr;
int fd = open(dev, O_RDONLY);
if (fd == -1)
return -1;
if (!(pr = blkid_new_probe()))
return -1;
if (blkid_probe_set_device(pr, fd, 0, 0))
return -1;
/* probe partitions too */
if (blkid_probe_enable_partitions(pr, true))
return -1;
/* bail if anything was found
* probe-bcache isn't needed once blkid recognizes bcache */
if (!blkid_do_probe(pr)) {
return -1;
}
if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
return -1;
if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic)))
return -1;
uuid_unparse(sb.uuid.b, uuid);
if (udev)
printf("ID_FS_UUID=%s\n"
"ID_FS_UUID_ENC=%s\n"
"ID_FS_TYPE=bcache\n",
uuid, uuid);
else
printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
return 0;
}

View File

@ -54,9 +54,16 @@ unsigned get_blocksize(const char *);
long strtoul_or_die(const char *, size_t, const char *);
void show_super_backingdev(struct cache_sb *, bool);
void show_cache_member(struct cache_sb *, unsigned);
void show_super_cache(struct cache_sb *, bool);
void query_dev(char *dev, bool force_csum);
int list_cachesets(char *cset_dir);
char *parse_array_to_list(char *const *args);
int register_bcache();
int probe(char *dev, int udev);
#define csum_set(i, type) \
({ \
void *start = ((void *) (i)) + sizeof(uint64_t); \

View File

@ -28,9 +28,6 @@
#include <sys/stat.h>
#include <uuid/uuid.h>
#include <bcache.h> //libbcache
#define __KERNEL__
#include <linux/bcache-ioctl.h>
#undef __KERNEL__
#define PACKAGE_NAME "bcacheadm"
#define PACKAGE_VERSION "1.0"
@ -77,14 +74,12 @@ enum long_opts {
/* super-show globals */
bool force_csum = false;
char *show_dev = NULL;
/* probe globals */
bool udev = false;
/* register globals */
int bcachefd;
/* list globals */
char *cset_dir = "/sys/fs/bcache";
/* make-bcache option setters */
static int set_CACHE_SET_UUID(NihOption *option, const char *arg)
@ -178,7 +173,6 @@ static NihOption make_bcache_options[] = {
{'t', "tier", N_("tier of subsequent devices"), NULL,NULL, &tier, NULL},
{'p', "cache_replacement_policy", N_("one of (lru|fifo|random)"), NULL,NULL, &replacement_policy, NULL},
{'o', "data_offset", N_("data offset in sectors"), NULL,NULL, &data_offset, NULL},
{'h', "help", N_("display this help and exit"), NULL,NULL, NULL, NULL},
{0, "cset-uuid", N_("UUID for the cache set"), NULL, NULL, NULL, set_CACHE_SET_UUID },
{0, "csum-type", N_("One of (none|crc32c|crc64)"), NULL, NULL, NULL, set_CSUM_TYPE },
@ -193,13 +187,6 @@ static NihOption make_bcache_options[] = {
NIH_OPTION_LAST
};
static NihOption super_show_options[] = {
{'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL},
{0, "dev", N_("dev"), NULL, NULL, &show_dev, NULL},
NIH_OPTION_LAST
};
static NihOption probe_bcache_options[] = {
{'o', "udev", N_("udev"), NULL, NULL, NULL, set_udev},
NIH_OPTION_LAST
@ -209,6 +196,16 @@ static NihOption bcache_register_options[] = {
NIH_OPTION_LAST
};
static NihOption query_devs_options[] = {
{'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL},
NIH_OPTION_LAST
};
static NihOption list_cachesets_options[] = {
{'d', "dir", N_("directory"), NULL, NULL, &cset_dir, NULL},
NIH_OPTION_LAST
};
static NihOption options[] = {
NIH_OPTION_LAST
};
@ -280,80 +277,12 @@ int make_bcache (NihCommand *command, char *const *args)
return 0;
}
int super_show (NihCommand *command, char *const *args)
{
struct cache_sb sb_stack, *sb = &sb_stack;
size_t bytes = sizeof(*sb);
int fd = open(show_dev, O_RDONLY);
if (fd < 0) {
printf("Can't open dev %s: %s\n", show_dev, strerror(errno));
exit(2);
}
if (pread(fd, sb, bytes, SB_START) != bytes) {
fprintf(stderr, "Couldn't read\n");
exit(2);
}
if (sb->keys) {
bytes = sizeof(*sb) + sb->keys * sizeof(uint64_t);
sb = malloc(bytes);
if (pread(fd, sb, bytes, SB_START) != bytes) {
fprintf(stderr, "Couldn't read\n");
exit(2);
}
}
if (!SB_IS_BDEV(sb))
show_super_cache(sb, force_csum);
else
show_super_backingdev(sb, force_csum);
return 0;
}
int probe_bcache (NihCommand *command, char *const *args)
{
int i;
struct cache_sb sb;
char uuid[40];
blkid_probe pr;
for (i = 0; args[i]!=NULL; i++) {
int fd = open(args[i], O_RDONLY);
if (fd == -1)
continue;
if (!(pr = blkid_new_probe()))
continue;
if (blkid_probe_set_device(pr, fd, 0, 0))
continue;
/* probe partitions too */
if (blkid_probe_enable_partitions(pr, true))
continue;
/* bail if anything was found
* probe-bcache isn't needed once blkid recognizes bcache */
if (!blkid_do_probe(pr)) {
continue;
}
if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
continue;
if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic)))
continue;
uuid_unparse(sb.uuid.b, uuid);
if (udev)
printf("ID_FS_UUID=%s\n"
"ID_FS_UUID_ENC=%s\n"
"ID_FS_TYPE=bcache\n",
uuid, uuid);
else
printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
for (i = 0; args[i] != NULL; i++) {
probe(args[i], udev);
}
return 0;
@ -362,26 +291,36 @@ int probe_bcache (NihCommand *command, char *const *args)
int bcache_register (NihCommand *command, char *const *args)
{
int ret;
char *arg_list = parse_array_to_list(args);
bcachefd = open("/dev/bcache", O_RDWR);
if (bcachefd < 0) {
perror("Can't open bcache device");
exit(EXIT_FAILURE);
if(arg_list) {
ret = register_bcache(arg_list);
free(arg_list);
}
ret = ioctl(bcachefd, BCH_IOCTL_REGISTER, args);
if (ret < 0) {
fprintf(stderr, "ioctl error %d", ret);
exit(EXIT_FAILURE);
return ret;
}
int bcache_list_cachesets (NihCommand *command, char *const *args)
{
return list_cachesets(cset_dir);
}
int bcache_query_devs (NihCommand *command, char *const *args)
{
int i;
for (i = 0; args[i]!=NULL; i++) {
query_dev(args[i], false);
}
return 0;
}
static NihCommand commands[] = {
{"format", N_("format <list of drives>"), "Format one or a list of devices with bcache datastructures. You need to do this before you create a volume", N_("format drive[s] with bcache"), NULL, make_bcache_options, make_bcache},
{"show-sb", N_("show-sb <list of drives>"), "View a superblock on one or a list of bcache formated devices", N_("show superblock on each of the listed drive"), NULL, super_show_options, super_show},
{"probe", N_("probe <list of drives>"), NULL, NULL, NULL, probe_bcache_options, probe_bcache},
{"register", N_("register <list of devices>"), NULL, NULL, NULL, bcache_register_options, bcache_register},
{"probe", N_("probe <list of devices>"), "Does a blkid_probe on a device", N_("Does a blkid_probe on a device"), NULL, probe_bcache_options, probe_bcache},
{"register", N_("register <list of devices>"), "Registers a list of devices", N_("Registers a list of devices"), NULL, bcache_register_options, bcache_register},
{"list-cachesets", N_("list-cachesets"), "Lists cachesets in /sys/fs/bcache", N_("Lists cachesets in /sys/fs/bcache"), NULL, list_cachesets_options, bcache_list_cachesets},
{"query-devs", N_("query <list of devices>"), "Gives info about the superblock of a list of devices", N_("show superblock on each of the listed drive"), NULL, query_devs_options, bcache_query_devs},
NIH_COMMAND_LAST
};