From 5a71c13062427832c355811f6d606b4b5fe341d7 Mon Sep 17 00:00:00 2001 From: Claudio Fleiner Date: Wed, 24 Dec 2014 10:18:26 -0800 Subject: [PATCH 01/12] update version and build Change-Id: I2f9e09ee6a927f7f89207914745ef50b6493e4b9 --- autogen.sh | 18 ------------------ bcache-tools.spec | 21 +++++++++++++++++---- configure.ac | 14 ++------------ 3 files changed, 19 insertions(+), 34 deletions(-) delete mode 100755 autogen.sh diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 8a566d46..00000000 --- a/autogen.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e - -export ACLOCAL_FLAGS="" -export ACLOCAL_AMFLAGS="-I m4" - -aclocal $ACLOCAL_FLAGS - -if glibtoolize -h > /dev/null 2>&1 ; then - glibtoolize --copy --force -else - libtoolize --copy --force -fi - -autoheader -automake --copy --add-missing --foreign -Wall -Wno-portability -autoconf diff --git a/bcache-tools.spec b/bcache-tools.spec index 5242ee2f..1f71ee19 100644 --- a/bcache-tools.spec +++ b/bcache-tools.spec @@ -1,9 +1,9 @@ -Summary: bcache-tools -Name: bcache-tools -Version: 0.1 +Summary: bcache-tools: manage local bcache devices +Name: %{package_name} +Version: %{datera_version} Release: %{?release:%{release}}%{!?release:eng} Source0: %{name}-%{version}.tar.gz -License: GPL +License: GPL2 Group: tools BuildRoot: %{_tmppath}/%{name}-root Requires: libblkid @@ -14,4 +14,17 @@ Summary: tools to manage bcache %description bcache tools +%install +make DESTDIR=%buildroot INSTALL=/usr/bin/install -C /bld/$RPM_PACKAGE_NAME install + %files +%_bindir/bcacheadm +%_bindir/bcachectl +%_bindir/make-bcache +%_bindir/probe-bcache +%_bindir/bcache-super-show +%_prefix/etc/initramfs-tools/hooks/bcache +%_prefix/lib/udev/bcache-register +%_prefix/lib/udev/rules.d/69-bcache.rules +%_libdir/libbcache.a +%_mandir/man8/*.gz diff --git a/configure.ac b/configure.ac index cf75d352..5c86f950 100644 --- a/configure.ac +++ b/configure.ac @@ -2,22 +2,12 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT(bcache-tools, 0.1, support@datera.io) -AM_INIT_AUTOMAKE +AC_INIT(m4_esyscmd([echo -n $PACKAGE]), m4_esyscmd([echo -n $DATERA_VERSION]), m4_esyscmd([echo -n $SUPPORT_EMAIL])) LT_INIT AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) -# Checks for programs. -AC_PROG_CC - -# Checks for libraries. - -# Checks for header files. - -# Checks for typedefs, structures, and compiler characteristics. - -# Checks for library functions. +m4_include([../BTools/cscript/ccpp.m4]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT From 75a34da9d0adbe773b5989e726ec8277a1887269 Mon Sep 17 00:00:00 2001 From: Claudio Fleiner Date: Sat, 27 Dec 2014 20:13:20 -0800 Subject: [PATCH 02/12] exclude some files from rpm that gets installed Change-Id: Id7b749358dcae30f448acc5c1c71e42b2687395b --- bcache-tools.spec | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bcache-tools.spec b/bcache-tools.spec index 1f71ee19..0215f632 100644 --- a/bcache-tools.spec +++ b/bcache-tools.spec @@ -1,14 +1,15 @@ Summary: bcache-tools: manage local bcache devices Name: %{package_name} -Version: %{datera_version} +Version: 0.datera.%{datera_version} Release: %{?release:%{release}}%{!?release:eng} Source0: %{name}-%{version}.tar.gz -License: GPL2 +License: GPLv2 Group: tools BuildRoot: %{_tmppath}/%{name}-root Requires: libblkid BuildRequires: pkgconfig libblkid-devel linux-headers libnih-devel Summary: tools to manage bcache +Epoch: 5 %description @@ -23,8 +24,8 @@ make DESTDIR=%buildroot INSTALL=/usr/bin/install -C /bld/$RPM_PACKAGE_NAME insta %_bindir/make-bcache %_bindir/probe-bcache %_bindir/bcache-super-show -%_prefix/etc/initramfs-tools/hooks/bcache -%_prefix/lib/udev/bcache-register -%_prefix/lib/udev/rules.d/69-bcache.rules %_libdir/libbcache.a %_mandir/man8/*.gz +%exclude %_prefix/etc/initramfs-tools/hooks/bcache +%exclude %_prefix/lib/udev/bcache-register +%exclude %_prefix/lib/udev/rules.d/69-bcache.rules From 27ff3c134c38655e18c0272d3b8985a32d761412 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Dec 2014 19:20:03 -0800 Subject: [PATCH 03/12] bcacheadm fixes Change-Id: I3f6024d54aee263ef843705a0e9a02869e2a53e9 --- Makefile | 19 ++++++++++++++----- bcache.c | 1 - bcacheadm.c | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 5b95af19..cda51875 100644 --- a/Makefile +++ b/Makefile @@ -3,15 +3,16 @@ PREFIX=/usr UDEVLIBDIR=/lib/udev DRACUTLIBDIR=/lib/dracut INSTALL=install -CFLAGS+=-O2 -Wall -Werror -g +CFLAGS+=-O2 -Wall -Werror -g -I. -all: make-bcache probe-bcache bcache-super-show bcachectl +all: bcacheadm make-bcache probe-bcache bcachectl -install: make-bcache probe-bcache bcache-super-show - $(INSTALL) -m0755 make-bcache bcache-super-show bcachectl $(DESTDIR)${PREFIX}/sbin/ +install: bcacheadm make-bcache probe-bcache + $(INSTALL) -m0755 bcacheadm bcachectl $(DESTDIR)${PREFIX}/sbin/ + $(INSTALL) -m0755 make-bcache bcachectl $(DESTDIR)${PREFIX}/sbin/ $(INSTALL) -m0755 probe-bcache bcache-register $(DESTDIR)$(UDEVLIBDIR)/ $(INSTALL) -m0644 69-bcache.rules $(DESTDIR)$(UDEVLIBDIR)/rules.d/ - -$(INSTALL) -T -m0755 initramfs/hook $(DESTDIR)/usr/share/initramfs-tools/hooks/bcache + #-$(INSTALL) -T -m0755 initramfs/hook $(DESTDIR)/usr/share/initramfs-tools/hooks/bcache if [ -d $(DESTDIR)$(DRACUTLIBDIR)/modules.d ]; \ then $(INSTALL) -D -m0755 dracut/module-setup.sh $(DESTDIR)$(DRACUTLIBDIR)/modules.d/90bcache/module-setup.sh; \ fi @@ -22,12 +23,20 @@ clean: $(RM) -f make-bcache probe-bcache bcache-super-show bcache-test bcachectl *.o bcache-test: LDLIBS += `pkg-config --libs openssl` + +bcacheadm: LDLIBS += `pkg-config --libs uuid blkid libnih` +bcacheadm: CFLAGS += `pkg-config --cflags uuid blkid libnih` +bcacheadm: bcache.o + make-bcache: LDLIBS += `pkg-config --libs uuid blkid` make-bcache: CFLAGS += `pkg-config --cflags uuid blkid` make-bcache: bcache.o + probe-bcache: LDLIBS += `pkg-config --libs uuid blkid` probe-bcache: CFLAGS += `pkg-config --cflags uuid blkid` + bcache-super-show: LDLIBS += `pkg-config --libs uuid` bcache-super-show: CFLAGS += -std=gnu99 bcache-super-show: bcache.o + bcachectl: bcachectl.o diff --git a/bcache.c b/bcache.c index 2c1f2322..7484f3d0 100644 --- a/bcache.c +++ b/bcache.c @@ -1042,7 +1042,6 @@ char *list_cachesets(char *cset_dir, bool list_devs) while ((ent = readdir(dir)) != NULL) { struct stat statbuf; char entry[MAX_PATH]; - struct dirent *cache_ent; if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; diff --git a/bcacheadm.c b/bcacheadm.c index 7ff4eea0..118d104e 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -125,6 +125,8 @@ static int set_cache(NihOption *option, const char *arg) devs++; nr_cache_devices++; + + return 0; } static int set_bdev(NihOption *option, const char *arg) @@ -401,12 +403,14 @@ int bcache_query_devs(NihCommand *command, char *const *args) { int i; - for (i = 0; args[i] != NULL; i++){ + for (i = 0; args[i] != NULL; i++) { char dev_uuid[40]; query_dev(args[i], force_csum, true, uuid_only, dev_uuid); if(uuid_only) printf("%s\n", dev_uuid); } + + return 0; } int bcache_status(NihCommand *command, char *const *args) @@ -421,19 +425,23 @@ int bcache_status(NihCommand *command, char *const *args) sb->nr_this_dev; long long unsigned cache_tier = CACHE_TIER(m); - if (!cache_tier) + if (!cache_tier) { if (!sb_tier0 || sb->seq > sb_tier0->seq) { sb_tier0 = sb; dev0 = args[i]; } - else if (cache_tier == 1) + } else if (cache_tier == 1) { if (!sb_tier1 || sb->seq > sb_tier1->seq) { sb_tier1 = sb; dev1 = args[i]; } + } } + if (sb_tier0) sb_state(sb_tier0, dev0); if (sb_tier1) sb_state(sb_tier1, dev1); + + return 0; } static char *stats_subdir(char* stats_dir) @@ -565,4 +573,6 @@ int main(int argc, char *argv[]) exit (1); nih_signal_reset(); + + return 0; } From c43d8cf6833d2c2bd43be3de1073f34e9cf8f703 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Tue, 25 Nov 2014 18:36:05 -0800 Subject: [PATCH 04/12] bcacheadm: add-devs and rm-dev options Option to add multiple devices and remove single devices. bcacheadm add-devs --set=uuid bcacheadm rm-dev Change-Id: I4f0a287c02dfad76d8263554e455c408191ea7ba Signed-off-by: Jacob Malevich --- bcache.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ bcache.h | 9 +++++++-- bcacheadm.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 2 deletions(-) diff --git a/bcache.c b/bcache.c index 7484f3d0..4cc6949b 100644 --- a/bcache.c +++ b/bcache.c @@ -879,6 +879,7 @@ struct cache_sb *query_dev(char *dev, bool force_csum, printf("Can't open dev %s: %s\n", dev, strerror(errno)); exit(2); } + printf("opened sb for %s\n", dev); if (pread(fd, sb, bytes, SB_START) != bytes) { fprintf(stderr, "Couldn't read\n"); @@ -1117,6 +1118,62 @@ err: return err; } +char *add_devices(char *const *devs, char *uuid) +{ + int ret, bcachefd; + char *err = NULL; + + bcachefd = open("/dev/bcache", O_RDWR); + if (bcachefd < 0) { + err = "Can't open bcache device"; + goto err; + } + + struct bch_ioctl_add_disks ia; + ia.devs = devs; + ia.uuid = uuid; + + ret = ioctl(bcachefd, BCH_IOCTL_ADD_DISKS, &ia); + if (ret < 0) { + char tmp[128]; + snprintf(tmp, 128, "ioctl add disk error: %s\n", + strerror(ret)); + err = strdup(tmp); + } + +err: + close(bcachefd); + return err; +} + +char *remove_device(const char *dev, bool force) +{ + int ret, bcachefd; + char *err = NULL; + + bcachefd = open("/dev/bcache", O_RDWR); + if (bcachefd < 0) { + err = "Can't open bcache device"; + goto err; + } + + struct bch_ioctl_rm_disk ir; + ir.dev = dev; + ir.force = force ? 1 : 0; + + ret = ioctl(bcachefd, BCH_IOCTL_RM_DISK, &ir); + if (ret < 0) { + char tmp[128]; + snprintf(tmp, 128, "ioctl add disk error: %s\n", + strerror(ret)); + err = strdup(tmp); + } + +err: + close(bcachefd); + return err; +} + char *probe(char *dev, int udev) { struct cache_sb sb; diff --git a/bcache.h b/bcache.h index 99307e64..c0315677 100644 --- a/bcache.h +++ b/bcache.h @@ -30,6 +30,11 @@ typedef __s64 s64; (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) +struct add_msg { + char *const *devs; + char *uuid; + int tier; +}; extern const char * const cache_state[]; extern const char * const replacement_policies[]; @@ -67,8 +72,8 @@ char *probe(char *, int); void sb_state(struct cache_sb *, char *); char *read_stat_dir(DIR *, char *, char *, bool); char *find_matching_uuid(char *, char *, const char*); -//int add_device(char *); -//int remove_device(char *); +char *add_devices(char *const *, char *); +char *remove_device(const char *, bool); #define csum_set(i, type) \ ({ \ diff --git a/bcacheadm.c b/bcacheadm.c index 118d104e..97883154 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -76,6 +76,11 @@ char *metadata_replicas = 0; char *data_replicas = 0; char *tier = 0; +/* add-dev globals */ +char *add_dev_uuid = NULL; + +/* rm-dev globals */ +bool force_remove = false; /* query-dev globals */ bool force_csum = false; @@ -203,6 +208,16 @@ static NihOption bcache_unregister_options[] = { NIH_OPTION_LAST }; +static NihOption bcache_add_device_options[] = { + {'u', "set", N_("cacheset uuid"), NULL, "UUID", &add_dev_uuid, NULL}, + NIH_OPTION_LAST +}; + +static NihOption bcache_rm_device_options[] = { + {'f', "force", N_("force cache removal"), NULL, NULL, &force_remove, NULL}, + NIH_OPTION_LAST +}; + static NihOption query_devs_options[] = { {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL}, {'u', "uuid-only", N_("only print out the uuid for the devices, not the whole superblock"), NULL, NULL, &uuid_only, NULL}, @@ -387,6 +402,35 @@ int bcache_unregister(NihCommand *command, char *const *args) return 0; } +int bcache_add_devices(NihCommand *command, char *const *args) +{ + char *err; + + if (!add_dev_uuid) + printf("Must specify a cacheset uuid to add the disk to\n"); + + err = add_devices(args, add_dev_uuid); + if (err) { + printf("bcache_add_devices error: %s\n", err); + return -1; + } + + return 0; +} + +int bcache_rm_device(NihCommand *command, char *const *args) +{ + char *err; + + err = remove_device(args[0], force_remove); + if (err) { + printf("bcache_rm_devices error: %s\n", err); + return -1; + } + + return 0; +} + int bcache_list_cachesets(NihCommand *command, char *const *args) { char *err = NULL; @@ -539,6 +583,14 @@ static NihCommand commands[] = { "Unregisters a list of devices", N_("Unregisters a list of devices"), NULL, bcache_unregister_options, bcache_unregister}, + {"add-devs", N_("add-devs --set=UUID --tier=# "), + "Adds a list of devices to a cacheset", + N_("Adds a list of devices to a cacheset"), + NULL, bcache_add_device_options, bcache_add_devices}, + {"rm-dev", N_("rm-dev "), + "Removes a device from its cacheset", + N_("Removes a device from its cacheset"), + NULL, bcache_rm_device_options, bcache_rm_device}, {"list-cachesets", N_("list-cachesets"), "Lists cachesets in /sys/fs/bcache", N_("Lists cachesets in /sys/fs/bcache"), From e977913cc8c34ca2728d31fe71ffc4b0e27e8c31 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Tue, 9 Dec 2014 18:26:13 -0800 Subject: [PATCH 05/12] bcacheadm: fix status command previously it wasn't properly looking through the list of member info in the cache that has the highest seq. Change-Id: I2a6ebf6bd0814055ec1247d0f4d79dab683115d3 Signed-off-by: Jacob Malevich --- bcache.c | 12 ------------ bcache.h | 1 - bcacheadm.c | 47 ++++++++++++++++++++++++++++------------------- 3 files changed, 28 insertions(+), 32 deletions(-) diff --git a/bcache.c b/bcache.c index 4cc6949b..1373d1ac 100644 --- a/bcache.c +++ b/bcache.c @@ -1236,18 +1236,6 @@ err: return err; } -void sb_state(struct cache_sb *sb, char *dev) -{ - struct cache_member *m = ((struct cache_member *) sb->d) + - sb->nr_this_dev; - - printf("device %s\n", dev); - printf("\tcache state\t%s\n", cache_state[CACHE_STATE(m)]); - printf("\tcache_tier\t%llu\n", CACHE_TIER(m)); - printf("\tseq#: \t%llu\n", sb->seq); - -} - char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val) { struct stat statbuf; diff --git a/bcache.h b/bcache.h index c0315677..07e9733c 100644 --- a/bcache.h +++ b/bcache.h @@ -69,7 +69,6 @@ char *parse_array_to_list(char *const *); char *register_bcache(char *const *); char *unregister_bcache(char *const *); char *probe(char *, int); -void sb_state(struct cache_sb *, char *); char *read_stat_dir(DIR *, char *, char *, bool); char *find_matching_uuid(char *, char *, const char*); char *add_devices(char *const *, char *); diff --git a/bcacheadm.c b/bcacheadm.c index 97883154..a0c95369 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -459,31 +459,40 @@ int bcache_query_devs(NihCommand *command, char *const *args) int bcache_status(NihCommand *command, char *const *args) { - int i; - struct cache_sb *sb_tier0 = NULL, *sb_tier1 = NULL; - char *dev0 = NULL, *dev1 = NULL; + int i, seq, nr_in_set = 0; + struct cache_sb *seq_sb = NULL; for (i = 0; args[i] != NULL; i++) { - struct cache_sb *sb = query_dev(args[i], false, false, false, NULL); - struct cache_member *m = ((struct cache_member *) sb->d) + - sb->nr_this_dev; - long long unsigned cache_tier = CACHE_TIER(m); + struct cache_sb *sb = query_dev(args[i], false, false, + false, NULL); - if (!cache_tier) { - if (!sb_tier0 || sb->seq > sb_tier0->seq) { - sb_tier0 = sb; - dev0 = args[i]; - } - } else if (cache_tier == 1) { - if (!sb_tier1 || sb->seq > sb_tier1->seq) { - sb_tier1 = sb; - dev1 = args[i]; - } + if(!sb) { + printf("Unable to open superblock, bad path\n"); + return -1; + } + + if(!seq_sb || sb->seq > seq) { + seq = sb->seq; + seq_sb = sb; + nr_in_set = sb->nr_in_set; } } - if (sb_tier0) sb_state(sb_tier0, dev0); - if (sb_tier1) sb_state(sb_tier1, dev1); + if(!seq_sb) + printf("Unable to find a superblock\n"); + else + printf("%-50s%-15s%-4s\n", "uuid", "state", "tier"); + + for (i = 0; i < seq_sb->nr_in_set; i++) { + char uuid_str[40]; + struct cache_member *m = ((struct cache_member *) seq_sb->d) + i; + + uuid_unparse(m->uuid.b, uuid_str); + + printf("%-50s%-15s%-4llu\n", uuid_str, + cache_state[CACHE_STATE(m)], + CACHE_TIER(m)); + } return 0; } From 1c113a126b499dea3bbf3b4f93836f60763edff3 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Tue, 9 Dec 2014 18:03:47 -0800 Subject: [PATCH 06/12] bcacheadm: add command to modify sysfs attributes for a cache or cacheset bcacheadm modify -u csetuuid -d cacheuuid attr val bcacheadm modify -u csetuuid attr val bcacheadm modify --list Change-Id: I7b8ddfb6a7cd12a7bc71870dcc10787a7d3d9e8d Signed-off-by: Jacob Malevich --- bcache.c | 35 +++++++++++++++- bcache.h | 47 +++++++++++++++++++--- bcacheadm.c | 113 +++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 170 insertions(+), 25 deletions(-) diff --git a/bcache.c b/bcache.c index 1373d1ac..ec88ffc9 100644 --- a/bcache.c +++ b/bcache.c @@ -868,6 +868,40 @@ void show_super_cache(struct cache_sb *sb, bool force_csum) show_cache_member(sb, sb->nr_this_dev); } +static int __sysfs_attr_type(char *attr, const char **attr_arr) { + int i, j; + for(i = 0; attr_arr[i] != NULL; i++) + if(!strcmp(attr, attr_arr[i])) + return 1; + return 0; +} + +enum sysfs_attr sysfs_attr_type(char *attr) { + int ret; + if(__sysfs_attr_type(attr, set_attrs)) + return SET_ATTR; + if(__sysfs_attr_type(attr, cache_attrs)) + return CACHE_ATTR; + if(__sysfs_attr_type(attr, internal_attrs)) + return INTERNAL_ATTR; + + printf("No attribute called %s, try --list to see options\n", attr); + + return -1; +} + +static void __sysfs_attr_list(const char **attr_arr) { + int i, j; + for (i = 0; attr_arr[i] != NULL; i++) + printf("%s\n", attr_arr[i]); +} + +void sysfs_attr_list() { + __sysfs_attr_list(set_attrs); + __sysfs_attr_list(cache_attrs); + __sysfs_attr_list(internal_attrs); +} + struct cache_sb *query_dev(char *dev, bool force_csum, bool print_sb, bool uuid_only, char *dev_uuid) { @@ -879,7 +913,6 @@ struct cache_sb *query_dev(char *dev, bool force_csum, printf("Can't open dev %s: %s\n", dev, strerror(errno)); exit(2); } - printf("opened sb for %s\n", dev); if (pread(fd, sb, bytes, SB_START) != bytes) { fprintf(stderr, "Couldn't read\n"); diff --git a/bcache.h b/bcache.h index 07e9733c..dc79d066 100644 --- a/bcache.h +++ b/bcache.h @@ -30,12 +30,6 @@ typedef __s64 s64; (void) (&_max1 == &_max2); \ _max1 > _max2 ? _max1 : _max2; }) -struct add_msg { - char *const *devs; - char *uuid; - int tier; -}; - extern const char * const cache_state[]; extern const char * const replacement_policies[]; extern const char * const csum_types[]; @@ -63,6 +57,47 @@ long strtoul_or_die(const char *, size_t, const char *); void show_super_backingdev(struct cache_sb *, bool); void show_super_cache(struct cache_sb *, bool); +enum sysfs_attr {SET_ATTR, CACHE_ATTR, INTERNAL_ATTR}; + +static const char *set_attrs[] = { + "btree_flush_delay", + "btree_scan_ratelimit", + "bucket_reserve_percent", + "cache_reserve_percent", + "checksum_type", + "congested_read_threshold_us", + "congested_write_threshold_us", + "data_replicas", + "errors", + "foreground_target_percent", + "gc_sector_percent", + "journal_delay_ms", + "meta_replicas", + "sector_reserve_percent", + "tiering_percent", + NULL +}; + +static const char *cache_attrs[] = { + "cache_replacement_policy", + "discard", + "state", + "tier", + NULL +}; + +static const char *internal_attrs[] = { + "btree_shrinker_disabled", + "copy_gc_enabled", + "foreground_write_rate", + "tiering_enabled", + "tiering_rate", + NULL +}; + +enum sysfs_attr sysfs_attr_type(char *attr); +void sysfs_attr_list(); + struct cache_sb *query_dev(char *, bool, bool, bool, char *dev_uuid); char *list_cachesets(char *, bool); char *parse_array_to_list(char *const *); diff --git a/bcacheadm.c b/bcacheadm.c index a0c95369..67f26b17 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -37,16 +37,6 @@ #define MAX_DEVS MAX_CACHES_PER_SET -/* bcacheadm globals */ -enum exit { - EXIT_OK = 0, /* Ok */ - EXIT_ERROR = 1, /* General/OS error */ - EXIT_SHELL = 2, /* Start maintenance shell */ - EXIT_SHELL_REBOOT = 3, /* Start maintenance shell, reboot when done */ - EXIT_REBOOT = 4, /* System must reboot */ -}; - - /* make-bcache globals */ int bdev = -1; int devs = 0; @@ -63,13 +53,6 @@ unsigned replication_set = 0, replacement_policy = 0; uint64_t data_offset = BDEV_DATA_START_DEFAULT; char *label = NULL; struct cache_sb *cache_set_sb = NULL; -enum long_opts { - CACHE_SET_UUID = 256, - CSUM_TYPE, - REPLICATION_SET, - META_REPLICAS, - DATA_REPLICAS, -}; const char *cache_set_uuid = 0; const char *csum_type = 0; char *metadata_replicas = 0; @@ -82,6 +65,11 @@ char *add_dev_uuid = NULL; /* rm-dev globals */ bool force_remove = false; +/* Modify globals */ +bool modify_list_attrs = false; +static const char *modify_set_uuid = NULL; +static const char *modify_dev_uuid = NULL; + /* query-dev globals */ bool force_csum = false; bool uuid_only = false; @@ -218,6 +206,13 @@ static NihOption bcache_rm_device_options[] = { NIH_OPTION_LAST }; +static NihOption bcache_modify_options[] = { + {'l', "list", N_("list attributes"), NULL, NULL, &modify_list_attrs, NULL}, + {'u', "set", N_("cacheset uuid"), NULL, "UUID", &modify_set_uuid, NULL}, + {'d', "dev", N_("device uuid"), NULL, "UUID", &modify_dev_uuid, NULL}, + NIH_OPTION_LAST +}; + static NihOption query_devs_options[] = { {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL}, {'u', "uuid-only", N_("only print out the uuid for the devices, not the whole superblock"), NULL, NULL, &uuid_only, NULL}, @@ -406,8 +401,10 @@ int bcache_add_devices(NihCommand *command, char *const *args) { char *err; - if (!add_dev_uuid) + if (!add_dev_uuid) { printf("Must specify a cacheset uuid to add the disk to\n"); + return -1; + } err = add_devices(args, add_dev_uuid); if (err) { @@ -431,6 +428,82 @@ int bcache_rm_device(NihCommand *command, char *const *args) return 0; } +int bcache_modify(NihCommand *command, char *const *args) +{ + char *err; + char path[MAX_PATH]; + DIR *path_dir; + struct stat cache_stat; + char *attr = args[0]; + char *val = NULL; + int fd = -1; + + if (modify_list_attrs) { + sysfs_attr_list(); + return 0; + } + + if (!modify_set_uuid) { + printf("Must provide a cacheset uuid\n"); + return -1; + } + + snprintf(path, MAX_PATH, "%s/%s", cset_dir, modify_set_uuid); + + if(!attr) { + printf("Must provide the name of an attribute to modify\n"); + goto err; + } + + enum sysfs_attr type = sysfs_attr_type(attr); + + if (type == -1) + goto err; + else if(type == INTERNAL_ATTR) + strcat(path, "/internal"); + else if(type == CACHE_ATTR) { + if(modify_dev_uuid) { + /* searches all cache# for a matching uuid, + * path gets modified to the correct cache path */ + char subdir[10] = "/cache"; + err = find_matching_uuid(path, subdir, + modify_dev_uuid); + if (err) { + printf("Failed to find " + "matching dev %s\n", err); + goto err; + } else { + strcat(path, subdir); + } + } else { + printf("Must provide a device uuid\n"); + } + } + /* SET_ATTRs are just in the current dir */ + + strcat(path, "/"); + strcat(path, attr); + + val = args[1]; + if (!val) { + printf("Must provide a value to change the attribute to\n"); + goto err; + } + + fd = open(path, O_WRONLY); + if (fd < 0) { + printf("Unable to open modify attr with path %s\n", path); + goto err; + } + + write(fd, val, strlen(val)); + +err: + if(fd) + close(fd); + return 0; +} + int bcache_list_cachesets(NihCommand *command, char *const *args) { char *err = NULL; @@ -600,6 +673,10 @@ static NihCommand commands[] = { "Removes a device from its cacheset", N_("Removes a device from its cacheset"), NULL, bcache_rm_device_options, bcache_rm_device}, + {"modify", N_("modify --set=UUID (dev=UUID) name value"), + "Modifies attributes related to the cacheset", + N_("Modifies attributes related to the cacheset"), + NULL, bcache_modify_options, bcache_modify}, {"list-cachesets", N_("list-cachesets"), "Lists cachesets in /sys/fs/bcache", N_("Lists cachesets in /sys/fs/bcache"), From d8e72eb615b56a87cc91a07d050857110e2977c6 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Thu, 11 Dec 2014 13:43:14 -0800 Subject: [PATCH 07/12] bcacheadm: add query-devs --brief command bcacheadm query-devs --brief /dev/sdb /dev/sdc /dev/sdd will output table showing only the dev name, dev uuid, server uuid, and cluster uuid for each device Change-Id: I47a375c9a8f9284942befa0151fae32b0b856a53 Signed-off-by: Jacob Malevich --- bcache.c | 15 ++++++++++----- bcacheadm.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/bcache.c b/bcache.c index ec88ffc9..52745519 100644 --- a/bcache.c +++ b/bcache.c @@ -911,12 +911,12 @@ struct cache_sb *query_dev(char *dev, bool force_csum, int fd = open(dev, O_RDONLY); if (fd < 0) { printf("Can't open dev %s: %s\n", dev, strerror(errno)); - exit(2); + return NULL; } if (pread(fd, sb, bytes, SB_START) != bytes) { fprintf(stderr, "Couldn't read\n"); - exit(2); + return NULL; } if (sb->keys) { @@ -925,7 +925,7 @@ struct cache_sb *query_dev(char *dev, bool force_csum, if (pread(fd, sb, bytes, SB_START) != bytes) { fprintf(stderr, "Couldn't read\n"); - exit(2); + return NULL; } } @@ -1029,6 +1029,7 @@ char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uu buf[len] = '\0'; int i, end = strlen(buf); char tmp[32], devname[32]; + struct cache_sb *sb; /* Chop off "/bcache", then look for the * next '/' from the end @@ -1042,10 +1043,14 @@ char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uu strcpy(devname, "/dev"); strcat(devname, tmp); - query_dev(devname, false, false, true, dev_uuid); + err = "Unable to open superblock"; + sb = query_dev(devname, false, false, true, dev_uuid); + if(!sb) + return err; + if(!strcmp(stats_dev_uuid, dev_uuid)) { strcat(subdir, intbuf); - return err; + return NULL; } } diff --git a/bcacheadm.c b/bcacheadm.c index 67f26b17..10ffb3fa 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -73,6 +73,7 @@ static const char *modify_dev_uuid = NULL; /* query-dev globals */ bool force_csum = false; bool uuid_only = false; +bool query_brief = false; /* probe globals */ bool udev = false; @@ -216,6 +217,7 @@ static NihOption bcache_modify_options[] = { static NihOption query_devs_options[] = { {'f', "force_csum", N_("force_csum"), NULL, NULL, &force_csum, NULL}, {'u', "uuid-only", N_("only print out the uuid for the devices, not the whole superblock"), NULL, NULL, &uuid_only, NULL}, + {'b', "brief", N_("only print out the cluster,server,and disk uuids"), NULL, NULL, &query_brief, NULL}, NIH_OPTION_LAST }; @@ -520,11 +522,37 @@ int bcache_query_devs(NihCommand *command, char *const *args) { int i; + if (query_brief) + printf("%-10s%-40s%-40s%-40s\n", "dev name", "disk uuid", + "server uuid", "cluster uuid"); + for (i = 0; args[i] != NULL; i++) { char dev_uuid[40]; - query_dev(args[i], force_csum, true, uuid_only, dev_uuid); - if(uuid_only) + struct cache_sb *sb = query_dev(args[i], force_csum, + !query_brief, uuid_only, dev_uuid); + + if (!sb) { + printf("error opening the superblock for %s\n", + args[i]); + return -1; + } + + if (uuid_only) { printf("%s\n", dev_uuid); + } else if (query_brief) { + char set_uuid_str[40], dev_uuid_str[40]; + char *clus_uuid = (char *)sb->label; + + uuid_unparse(sb->set_uuid.b, set_uuid_str); + uuid_unparse(sb->uuid.b, dev_uuid_str); + if (!strcmp(clus_uuid, "")) + clus_uuid = "None"; + + printf("%-10s%-40s%-40s%-40s\n", args[i], + dev_uuid_str, + set_uuid_str, + clus_uuid); + } } return 0; From 5ec1b6cb6cbd882e41670eb02fa6c21125222517 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Mon, 15 Dec 2014 18:10:25 -0800 Subject: [PATCH 08/12] bcacheadm: add capacity command prints the device capacity, and free space for a cacheset example: bcacheadm capacity -u UUID --devs Device Name Capacity (512 Blocks) Free (512 Blocks) /dev/sdb 1048576.00 1024128.00 /dev/sdc 1048576.00 1024128.00 /dev/sdd 1048576.00 1024128.00 Total 3145728.00 3072384.00 Also did some bcacheadm stats refactoring. Change-Id: Iff5562191478c5fd9f03399a9479d3d75740904d Signed-off-by: Jacob Malevich --- bcache.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++----- bcache.h | 5 +- bcacheadm.c | 44 ++++++++++++++++-- 3 files changed, 160 insertions(+), 18 deletions(-) diff --git a/bcache.c b/bcache.c index 52745519..f6fcb24c 100644 --- a/bcache.c +++ b/bcache.c @@ -829,6 +829,7 @@ static void show_cache_member(struct cache_sb *sb, unsigned i) struct cache_member *m = ((struct cache_member *) sb->d) + i; printf("cache.state\t%s\n", cache_state[CACHE_STATE(m)]); + printf("cache.tier\t%llu\n", CACHE_TIER(m)); printf("cache.replication_set\t%llu\n", CACHE_REPLICATION_SET(m)); @@ -944,7 +945,7 @@ struct cache_sb *query_dev(char *dev, bool force_csum, return sb; } -static void dev_name(const char *ugly_path) { +static char *dev_name(const char *ugly_path) { char buf[32]; int i, end = strlen(ugly_path); @@ -958,7 +959,7 @@ static void dev_name(const char *ugly_path) { // Is the dev guaranteed to be in /dev? // This is needed for finding the superblock with a query-dev - printf("/dev%s\n", buf); + return strdup(buf); } static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) { @@ -974,6 +975,7 @@ static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_n while(true) { char buf[MAX_PATH]; int len; + char *tmp; if((cachedir = opendir(entry)) == NULL) break; @@ -983,10 +985,13 @@ static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_n if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) { buf[len] = '\0'; - if(parse_dev_name) - dev_name(buf); - else + if(parse_dev_name) { + tmp = dev_name(buf); + printf("/dev%s\n", tmp); + free(tmp); + } else { printf("\t%s\n", buf); + } } /* remove i from end and append i++ */ @@ -1274,7 +1279,7 @@ err: return err; } -char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val) +char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, char *ret) { struct stat statbuf; char entry[MAX_PATH]; @@ -1299,14 +1304,114 @@ char *read_stat_dir(DIR *dir, char *stats_dir, char *stat_name, bool print_val) return NULL; } - while(fgets(buf, MAX_PATH, fp)); - - if(print_val) - printf("%s\n", buf); - else - printf("%s\n", stat_name); + while(fgets(ret, MAX_PATH, fp)); fclose(fp); } err: return err; } + +char *bcache_get_capacity(const char *cset_dir, const char *capacity_uuid, + bool show_devs) +{ + char *err = NULL; + char bucket_size_path[MAX_PATH]; + char nbuckets_path[MAX_PATH]; + char avail_buckets_path[MAX_PATH]; + char cache_path[MAX_PATH]; + + double bucket_sizes[MAX_DEVS]; + double nbuckets[MAX_DEVS]; + double avail_buckets[MAX_DEVS]; + char *dev_names[MAX_DEVS]; + int dev_count = 0, i; + char intbuf[4]; + double total_cap = 0, total_free = 0; + int precision = 2; + + snprintf(intbuf, 4, "%d", i); + snprintf(bucket_size_path, MAX_PATH, "%s/%s/%s/%s", cset_dir, + capacity_uuid, "cache0", "bucket_size_bytes"); + snprintf(nbuckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir, + capacity_uuid, "cache0", "nbuckets"); + snprintf(avail_buckets_path, MAX_PATH, "%s/%s/%s/%s", cset_dir, + capacity_uuid, "cache0", "available_buckets"); + snprintf(cache_path, MAX_PATH, "%s/%s/%s", cset_dir, capacity_uuid, + "cache0"); + + while(true) { + char buf[MAX_PATH]; + int len; + DIR *cache_dir; + + if((cache_dir = opendir(cache_path)) == NULL) + break; + + err = read_stat_dir(cache_dir, cache_path, + "bucket_size_bytes", buf); + if (err) + goto err; + else + bucket_sizes[dev_count] = atof(buf); + + err = read_stat_dir(cache_dir, cache_path, + "nbuckets", buf); + if (err) + goto err; + else + nbuckets[dev_count] = atof(buf); + + err = read_stat_dir(cache_dir, cache_path, + "available_buckets", buf); + if (err) + goto err; + else + avail_buckets[dev_count] = atof(buf); + + if((len = readlink(cache_path, buf, sizeof(buf) - 1)) != -1) { + buf[len] = '\0'; + dev_names[dev_count] = dev_name(buf); + } + + /* remove i/stat and append i++/stat */ + bucket_size_path[strlen(cache_path) - strlen(intbuf)] = 0; + nbuckets_path[strlen(cache_path) - strlen(intbuf)] = 0; + avail_buckets_path[strlen(cache_path) - strlen(intbuf)] = 0; + cache_path[strlen(cache_path) - strlen(intbuf)] = 0; + + dev_count++; + + snprintf(intbuf, 4, "%d", dev_count); + strcat(cache_path, intbuf); + strcat(bucket_size_path, intbuf); + strcat(nbuckets_path, intbuf); + strcat(avail_buckets_path, intbuf); + } + + printf("%-15s%-25s%-25s\n", "Device Name", "Capacity (512 Blocks)", "Free (512 Blocks)"); + + if (show_devs) { + for (i = 0; i < dev_count; i++) { + printf("%s%-11s%-25.*f%-25.*f\n", "/dev", dev_names[i], + precision, + (bucket_sizes[i] * nbuckets[i]) / 512, + precision, + (bucket_sizes[i] * avail_buckets[i]) / 512); + } + } + + for (i = 0; i < dev_count; i++) { + total_cap += (bucket_sizes[i] * nbuckets[i]) / 512; + total_free += (bucket_sizes[i] * avail_buckets[i]) / 512; + + } + + printf("%-15s%-25.*f%-25.*f\n", "Total", precision, total_cap, + precision, total_free); + +err: + for (i = 0; i < dev_count; i++) + if (dev_names[i]) + free(dev_names[i]); + return err; +} diff --git a/bcache.h b/bcache.h index dc79d066..4cfac71f 100644 --- a/bcache.h +++ b/bcache.h @@ -22,7 +22,7 @@ typedef __s64 s64; #define SB_START (SB_SECTOR * 512) #define MAX_PATH 256 - +#define MAX_DEVS MAX_CACHES_PER_SET #define max(x, y) ({ \ typeof(x) _max1 = (x); \ @@ -104,10 +104,11 @@ char *parse_array_to_list(char *const *); char *register_bcache(char *const *); char *unregister_bcache(char *const *); char *probe(char *, int); -char *read_stat_dir(DIR *, char *, char *, bool); +char *read_stat_dir(DIR *, char *, char *, char *); char *find_matching_uuid(char *, char *, const char*); char *add_devices(char *const *, char *); char *remove_device(const char *, bool); +char *bcache_get_capacity(const char *, const char *, bool); #define csum_set(i, type) \ ({ \ diff --git a/bcacheadm.c b/bcacheadm.c index 10ffb3fa..ea9fc751 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -34,7 +34,6 @@ #define PACKAGE_VERSION "1.0" #define PACKAGE_BUGREPORT "bugreport" -#define MAX_DEVS MAX_CACHES_PER_SET /* make-bcache globals */ @@ -85,6 +84,10 @@ bool list_devs = false; /* status globals */ bool status_all = false; +/* capacity globals */ +static const char *capacity_uuid = NULL; +bool capacity_devs = false; + /* stats globals */ bool stats_all = false; bool stats_list = false; @@ -232,6 +235,12 @@ static NihOption status_options[] = { NIH_OPTION_LAST }; +static NihOption capacity_options[] = { + {'u', "set", N_("cache_set UUID"), NULL, "UUID", &capacity_uuid, NULL}, + {'d', "devs", N_("dev UUID"), NULL, NULL, &capacity_devs, NULL}, + NIH_OPTION_LAST +}; + static NihOption stats_options[] = { {'a', "all", N_("all"), NULL, NULL, &stats_all, NULL}, {'l', "list", N_("list"), NULL, NULL, &stats_list, NULL}, @@ -598,6 +607,24 @@ int bcache_status(NihCommand *command, char *const *args) return 0; } +int bcache_capacity(NihCommand *command, char *const *args) +{ + char *err = "Must provide a cacheset uuid"; + if(!capacity_uuid) + goto err; + + err = bcache_get_capacity(cset_dir, capacity_uuid, capacity_devs); + if (err) + goto err; + + return 0; + +err: + printf("bcache_capacity failed with error: %s\n", err); + return -1; + +} + static char *stats_subdir(char* stats_dir) { char tmp[50] = "/"; @@ -634,6 +661,7 @@ int bcache_stats(NihCommand *command, char *const *args) DIR *dir = NULL; struct dirent *ent = NULL; char *err = NULL; + char buf[MAX_PATH]; if (stats_uuid) { snprintf(stats_dir, MAX_PATH, "%s/%s", cset_dir, stats_uuid); @@ -653,17 +681,21 @@ int bcache_stats(NihCommand *command, char *const *args) if(stats_list || stats_all) { while ((ent = readdir(dir)) != NULL) { - err = read_stat_dir(dir, stats_dir, ent->d_name, stats_all); + err = read_stat_dir(dir, stats_dir, ent->d_name, buf); if (err) goto err; + if(stats_list) + printf("%s\n", ent->d_name); + if(stats_all) + printf("\t%s\n", buf); } } - for (i = 0; args[i] != NULL; i++) { - err = read_stat_dir(dir, stats_dir, args[i], true); + err = read_stat_dir(dir, stats_dir, args[i], buf); if (err) goto err; + printf("%s\n", buf); } closedir(dir); @@ -717,6 +749,10 @@ static NihCommand commands[] = { "Finds the status of the most up to date superblock", N_("Finds the status of the most up to date superblock"), NULL, status_options, bcache_status}, + {"capacity", N_("capacity --set=UUID"), + "Shows the capacity of the cacheset", + N_("Shows the capacity of the cacheset"), + NULL, capacity_options, bcache_capacity}, {"stats", N_("stats "), "List various bcache statistics", N_("List various bcache statistics"), From 4a5a7690505ec6dbb085f7720689dfc777b736e7 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Wed, 17 Dec 2014 12:10:47 -0800 Subject: [PATCH 09/12] bcacheadm: only fail csum check when -f is passed Change-Id: I710f2b59940414830d08c7d018b53b84c6cbde05 Signed-off-by: Jacob Malevich --- bcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bcache.c b/bcache.c index f6fcb24c..7dc08bfe 100644 --- a/bcache.c +++ b/bcache.c @@ -755,7 +755,7 @@ static void show_super_common(struct cache_sb *sb, bool force_csum) printf(" [match]\n"); } else { printf(" [expected %" PRIX64 "]\n", expected_csum); - if (!force_csum) { + if (force_csum) { fprintf(stderr, "Corrupt superblock (bad csum)\n"); exit(2); } From 45d1cb0527b082c26747236ef9d391964cd1bf0f Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Wed, 17 Dec 2014 16:02:13 -0800 Subject: [PATCH 10/12] bcacheadm: fix list-cachesets --list-devs list-cachesets now searches through all cache# symlinks instead of iterating with i++. This is because bcache doesn't immediately reuse a cache# symlink when a dev gets removed. Fixes DAT-1635 Progress DAT-1646 Change-Id: I6901e29dc13f4e2a76bdc49871e87f07667ec786 Signed-off-by: Jacob Malevich --- bcache.c | 61 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/bcache.c b/bcache.c index 7dc08bfe..fb3931ed 100644 --- a/bcache.c +++ b/bcache.c @@ -964,41 +964,50 @@ static char *dev_name(const char *ugly_path) { static void list_cacheset_devs(char *cset_dir, char *cset_name, bool parse_dev_name) { int i = 0; - DIR *cachedir; + DIR *cachedir, *dir; struct stat cache_stat; - char intbuf[4]; char entry[MAX_PATH]; + struct dirent *ent; + snprintf(entry, MAX_PATH, "%s/%s", cset_dir, cset_name); - snprintf(entry, MAX_PATH, "%s/%s/cache0", cset_dir, cset_name); - snprintf(intbuf, 4, "%d", i); + if((dir = opendir(entry)) != NULL) { + while((ent = readdir(dir)) != NULL) { + char buf[MAX_PATH]; + int len; + char *tmp; - while(true) { - char buf[MAX_PATH]; - int len; - char *tmp; + /* + * We are looking for all cache# directories + * do a strlen < 9 to skip over other entries + * that also start with "cache" + */ + if(strncmp(ent->d_name, "cache", 5) || + !(strlen(ent->d_name) < 9)) + continue; - if((cachedir = opendir(entry)) == NULL) - break; + snprintf(entry, MAX_PATH, "%s/%s/%s", + cset_dir, + cset_name, + ent->d_name); - if(stat(entry, &cache_stat)) - break; + if((cachedir = opendir(entry)) == NULL) + continue; - if((len = readlink(entry, buf, sizeof(buf) - 1)) != -1) { - buf[len] = '\0'; - if(parse_dev_name) { - tmp = dev_name(buf); - printf("/dev%s\n", tmp); - free(tmp); - } else { - printf("\t%s\n", buf); + if(stat(entry, &cache_stat)) + continue; + + if((len = readlink(entry, buf, sizeof(buf) - 1)) != + -1) { + buf[len] = '\0'; + if(parse_dev_name) { + tmp = dev_name(buf); + printf("/dev%s\n", tmp); + free(tmp); + } else { + printf("\t%s\n", buf); + } } } - - /* remove i from end and append i++ */ - entry[strlen(entry)-strlen(intbuf)] = 0; - i++; - snprintf(intbuf, 4, "%d", i); - strcat(entry, intbuf); } } From 474f0889f0a19416d87fcf1a6b3e5cc9e49731c8 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Thu, 18 Dec 2014 19:19:21 -0800 Subject: [PATCH 11/12] bcacheadm: fix status and query-devs Previously we were reading old superblocks stuck in the cache. Pass in O_DIRECT when opening the device. This requires that the dest buffer be memaligned. If we are unable to read the entire superblock then increase the buffer and try again. Also since we now have to alloc the sb, make sure it is freed everywhere in bcacheadm. Fixes DAT-1609 DAT-1626 Change-Id: I04b5337b992a8569809835b5826a2656df753214 Signed-off-by: Jacob Malevich --- bcache.c | 39 +++++++++++++++++++++++++-------------- bcacheadm.c | 7 ++++++- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/bcache.c b/bcache.c index fb3931ed..a69a46fb 100644 --- a/bcache.c +++ b/bcache.c @@ -906,30 +906,39 @@ void sysfs_attr_list() { struct cache_sb *query_dev(char *dev, bool force_csum, bool print_sb, bool uuid_only, char *dev_uuid) { - struct cache_sb sb_stack, *sb = &sb_stack; - size_t bytes = sizeof(*sb); + size_t bytes = 4096; + struct cache_sb *sb = aligned_alloc(bytes, bytes); - int fd = open(dev, O_RDONLY); + int fd = open(dev, O_RDONLY|O_DIRECT); if (fd < 0) { printf("Can't open dev %s: %s\n", dev, strerror(errno)); return NULL; } - if (pread(fd, sb, bytes, SB_START) != bytes) { - fprintf(stderr, "Couldn't read\n"); - return NULL; - } - - 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"); + while (true) { + int ret = pread(fd, sb, bytes, SB_START); + if (ret < 0) { + fprintf(stderr, "Couldn't read superblock: %s\n", + strerror(errno)); + close(fd); + free(sb); return NULL; + } else if (bytes > sizeof(sb) + sb->keys * sizeof(u64)) { + /* We read the whole superblock */ + break; } + + /* + * otherwise double the size of our dest + * and read again + */ + free(sb); + bytes *= 2; + sb = aligned_alloc(4096, bytes); } + close(fd); + if(uuid_only) { show_uuid_only(sb, dev_uuid); return sb; @@ -1061,6 +1070,8 @@ char *find_matching_uuid(char *stats_dir, char *subdir, const char *stats_dev_uu sb = query_dev(devname, false, false, true, dev_uuid); if(!sb) return err; + else + free(sb); if(!strcmp(stats_dev_uuid, dev_uuid)) { strcat(subdir, intbuf); diff --git a/bcacheadm.c b/bcacheadm.c index ea9fc751..9cbf3462 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -562,6 +562,7 @@ int bcache_query_devs(NihCommand *command, char *const *args) set_uuid_str, clus_uuid); } + free(sb); } return 0; @@ -585,7 +586,8 @@ int bcache_status(NihCommand *command, char *const *args) seq = sb->seq; seq_sb = sb; nr_in_set = sb->nr_in_set; - } + } else + free(sb); } if(!seq_sb) @@ -604,6 +606,9 @@ int bcache_status(NihCommand *command, char *const *args) CACHE_TIER(m)); } + if(seq_sb) + free(seq_sb); + return 0; } From 10d4938f07151bd632493e89e3a6478085e84457 Mon Sep 17 00:00:00 2001 From: Jacob Malevich Date: Fri, 19 Dec 2014 15:35:13 -0800 Subject: [PATCH 12/12] bcacheadm: Fix bcacheadm status segfault if no devs given Fixes DAT-1655 Change-Id: I79cfc78fb8513f3e751332d65310d65020c15e3e Signed-off-by: Jacob Malevich --- bcacheadm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bcacheadm.c b/bcacheadm.c index 9cbf3462..837219ed 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -590,10 +590,12 @@ int bcache_status(NihCommand *command, char *const *args) free(sb); } - if(!seq_sb) + if(!seq_sb) { printf("Unable to find a superblock\n"); - else + return -1; + } else { printf("%-50s%-15s%-4s\n", "uuid", "state", "tier"); + } for (i = 0; i < seq_sb->nr_in_set; i++) { char uuid_str[40];