18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Feature set bits and string conversion. 48c2ecf20Sopenharmony_ci * Inspired by ext4's features compat/incompat/ro_compat related code. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright 2020 Coly Li <colyli@suse.de> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/bcache.h> 108c2ecf20Sopenharmony_ci#include "bcache.h" 118c2ecf20Sopenharmony_ci#include "features.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistruct feature { 148c2ecf20Sopenharmony_ci int compat; 158c2ecf20Sopenharmony_ci unsigned int mask; 168c2ecf20Sopenharmony_ci const char *string; 178c2ecf20Sopenharmony_ci}; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic struct feature feature_list[] = { 208c2ecf20Sopenharmony_ci {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE, 218c2ecf20Sopenharmony_ci "large_bucket"}, 228c2ecf20Sopenharmony_ci {0, 0, 0 }, 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define compose_feature_string(type) \ 268c2ecf20Sopenharmony_ci({ \ 278c2ecf20Sopenharmony_ci struct feature *f; \ 288c2ecf20Sopenharmony_ci bool first = true; \ 298c2ecf20Sopenharmony_ci \ 308c2ecf20Sopenharmony_ci for (f = &feature_list[0]; f->compat != 0; f++) { \ 318c2ecf20Sopenharmony_ci if (f->compat != BCH_FEATURE_ ## type) \ 328c2ecf20Sopenharmony_ci continue; \ 338c2ecf20Sopenharmony_ci if (BCH_HAS_ ## type ## _FEATURE(&c->cache->sb, f->mask)) { \ 348c2ecf20Sopenharmony_ci if (first) { \ 358c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, \ 368c2ecf20Sopenharmony_ci "["); \ 378c2ecf20Sopenharmony_ci } else { \ 388c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, \ 398c2ecf20Sopenharmony_ci " ["); \ 408c2ecf20Sopenharmony_ci } \ 418c2ecf20Sopenharmony_ci } else if (!first) { \ 428c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, " "); \ 438c2ecf20Sopenharmony_ci } \ 448c2ecf20Sopenharmony_ci \ 458c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, "%s", f->string);\ 468c2ecf20Sopenharmony_ci \ 478c2ecf20Sopenharmony_ci if (BCH_HAS_ ## type ## _FEATURE(&c->cache->sb, f->mask)) \ 488c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, "]"); \ 498c2ecf20Sopenharmony_ci \ 508c2ecf20Sopenharmony_ci first = false; \ 518c2ecf20Sopenharmony_ci } \ 528c2ecf20Sopenharmony_ci if (!first) \ 538c2ecf20Sopenharmony_ci out += snprintf(out, buf + size - out, "\n"); \ 548c2ecf20Sopenharmony_ci}) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ciint bch_print_cache_set_feature_compat(struct cache_set *c, char *buf, int size) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci char *out = buf; 598c2ecf20Sopenharmony_ci compose_feature_string(COMPAT); 608c2ecf20Sopenharmony_ci return out - buf; 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciint bch_print_cache_set_feature_ro_compat(struct cache_set *c, char *buf, int size) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci char *out = buf; 668c2ecf20Sopenharmony_ci compose_feature_string(RO_COMPAT); 678c2ecf20Sopenharmony_ci return out - buf; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciint bch_print_cache_set_feature_incompat(struct cache_set *c, char *buf, int size) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci char *out = buf; 738c2ecf20Sopenharmony_ci compose_feature_string(INCOMPAT); 748c2ecf20Sopenharmony_ci return out - buf; 758c2ecf20Sopenharmony_ci} 76