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)
{
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");
(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[];
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 *);
#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;
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;
/* 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;
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},
{
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) {
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;
"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"),