From df6f17ee97ac47c949c1963ff8d57fb2d4becd06 Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Fri, 19 Jun 2020 16:31:36 -0700 Subject: [PATCH] LU-13621 lnet: utility to print cpt number Added a command to lnetctl to print the cpt of the NID. lnetctl cpt-of-nid --nid --ncpt ex: lnetctl cpt-of-nid --nid 192.28.12.35@tcp9 --ncpt 7 This will return what cpt the NID will hash to within the 0-6 range. If the NI is bound to specific set of CPTs, then the ncpts refers to the number of CPTs the NI is bound to. The cpt value returned will be an index into the list of bound CPTs. For example if an NI is bound to [0,4,5,7], then the ncpt should be 4. And the returned value will be an index in the array: ex: lnetctl cpt-of-nid --nid 192.28.12.35@tcp9 --ncpt 4 cpt: value: 1 therefore, the actual CPT the NID will be bound to is 4. Test-parameters: trivial testlist=sanity-lnet Signed-off-by: Amir Shehata Change-Id: I3cb562842448bfb663c2d41007be65299a919300 Reviewed-on: https://review.whamcloud.com/39113 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- lnet/utils/lnetconfig/liblnetconfig.c | 47 +++++++++++++++ lnet/utils/lnetconfig/liblnetconfig.h | 6 ++ lnet/utils/lnetctl.c | 105 +++++++++++++++++++++++++--------- 3 files changed, 132 insertions(+), 26 deletions(-) diff --git a/lnet/utils/lnetconfig/liblnetconfig.c b/lnet/utils/lnetconfig/liblnetconfig.c index 0b8b110..8db3f4d 100644 --- a/lnet/utils/lnetconfig/liblnetconfig.c +++ b/lnet/utils/lnetconfig/liblnetconfig.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include "liblnd.h" #include @@ -3790,6 +3791,52 @@ out: return rc; } +unsigned int +lnet_nid_cpt_hash(lnet_nid_t nid, long int number) +{ + __u64 key = nid; + unsigned int val; + int cpt_bits = 0; + + if (number == 1) + return 0; + + while ((1 << cpt_bits) < number) + cpt_bits++; + + val = hash_long(key, cpt_bits); + /* NB: LNET_CP_NUMBER doesn't have to be PO2 */ + if (val < number) + return val; + + return (unsigned int)(key + val + (val >> 1)) % number; +} + +int lustre_lnet_calc_cpt_of_nid(char *nidc, long int ncpts) +{ + int rc = LUSTRE_CFG_RC_BAD_PARAM; + lnet_nid_t nid; + + if (!nidc) { + fprintf(stderr, "error:\n msg: \"no NID provided\"\n"); + return rc; + } + + if (ncpts < 0) { + fprintf(stderr, "error:\n msg: \"number of CPTs not provided\"\n"); + return rc; + } + + nid = libcfs_str2nid(nidc); + if (nid == LNET_NID_ANY) { + fprintf(stderr, "error:\n msg: \"bad NID provided %s\"\n", + nidc); + return rc; + } + + return (int)lnet_nid_cpt_hash(nid, ncpts); +} + int show_recovery_queue(enum lnet_health_type type, char *name, int seq_no, struct cYAML **show_rc, struct cYAML **err_rc) { diff --git a/lnet/utils/lnetconfig/liblnetconfig.h b/lnet/utils/lnetconfig/liblnetconfig.h index dae9268..05d186f 100644 --- a/lnet/utils/lnetconfig/liblnetconfig.h +++ b/lnet/utils/lnetconfig/liblnetconfig.h @@ -539,6 +539,12 @@ int lustre_lnet_calc_service_id(__u64 *service_id); int lustre_lnet_setup_mrrouting(struct cYAML **err_rc); /* + * lustre_lnet_calc_cpt_of_nid + * Return the cpt number of the NID provided + */ +int lustre_lnet_calc_cpt_of_nid(char *nidc, long int ncpts); + +/* * lustre_lnet_config_discovery * Enable or disable peer discovery. Peer discovery is enabled by default. * diff --git a/lnet/utils/lnetctl.c b/lnet/utils/lnetctl.c index 6c76812..51dfab6 100644 --- a/lnet/utils/lnetctl.c +++ b/lnet/utils/lnetctl.c @@ -91,6 +91,7 @@ static int jt_set_response_tracking(int argc, char **argv); static int jt_set_recovery_limit(int argc, char **argv); static int jt_udsp(int argc, char **argv); static int jt_setup_mrrouting(int argc, char **argv); +static int jt_calc_cpt_of_nid(int argc, char **argv); command_t cmd_list[] = { {"lnet", jt_lnet, 0, "lnet {configure | unconfigure} [--all]"}, @@ -115,6 +116,9 @@ command_t cmd_list[] = { {"udsp", jt_udsp, 0, "udsp {add | del | help}"}, {"setup-mrrouting", jt_setup_mrrouting, 0, "setup linux routing tables\n"}, + {"cpt-of-nid", jt_calc_cpt_of_nid, 0, "Calculate the CPT associated with NID\n" + "\t--nid: NID to calculate the CPT of\n" + "\t--ncpt: Number of CPTs to consider in the calculation\n"}, {"help", Parser_help, 0, "help"}, {"exit", Parser_quit, 0, "quit"}, {"quit", Parser_quit, 0, "quit"}, @@ -287,22 +291,18 @@ command_t udsp_cmds[] = { { 0, 0, 0, NULL } }; -static int jt_calc_service_id(int argc, char **argv) +static int parse_long(const char *number, long int *value) { - int rc; - __u64 service_id; + char *end; - rc = lustre_lnet_calc_service_id(&service_id); - if (rc != LUSTRE_CFG_RC_NO_ERR) - return rc; + if (!number) + return -1; - /* - * cYAML currently doesn't support printing hex values. - * Therefore just print it locally here - */ - printf("service id:\n value: 0x%jx\n", (uintmax_t)service_id); + *value = strtol(number, &end, 0); + if (end != NULL && *end != 0) + return -1; - return rc; + return 0; } static int jt_setup_mrrouting(int argc, char **argv) @@ -338,20 +338,6 @@ static inline void print_help(const command_t cmds[], const char *cmd_type, } } -static int parse_long(const char *number, long int *value) -{ - char *end; - - if (!number) - return -1; - - *value = strtol(number, &end, 0); - if (end != NULL && *end != 0) - return -1; - - return 0; -} - static int check_cmd(const command_t *cmd_list, const char *cmd, const char *sub_cmd, const int min_args, int argc, char **argv) @@ -423,6 +409,73 @@ static int jt_set_response_tracking(int argc, char **argv) return rc; } +static int jt_calc_service_id(int argc, char **argv) +{ + int rc; + __u64 service_id; + + rc = lustre_lnet_calc_service_id(&service_id); + if (rc != LUSTRE_CFG_RC_NO_ERR) + return rc; + + /* cYAML currently doesn't support printing hex values. + * Therefore just print it locally here + */ + printf("service_id:\n value: 0x%llx\n", + (unsigned long long)(service_id)); + + return rc; +} + +static int jt_calc_cpt_of_nid(int argc, char **argv) +{ + int rc, opt; + int cpt; + long int ncpts = -1; + char *nid = NULL; + struct cYAML *err_rc = NULL; + const char *const short_options = "n:c:h"; + static const struct option long_options[] = { + { .name = "nid", .has_arg = required_argument, .val = 'n' }, + { .name = "ncpt", .has_arg = required_argument, .val = 'c' }, + { .name = NULL } }; + + rc = check_cmd(cmd_list, "", "cpt-of-nid", 0, argc, argv); + if (rc) + return rc; + + while ((opt = getopt_long(argc, argv, short_options, + long_options, NULL)) != -1) { + switch (opt) { + case 'n': + nid = optarg; + break; + case 'c': + rc = parse_long(optarg, &ncpts); + if (rc != 0) { + cYAML_build_error(-1, -1, "cpt", "get", + "cannot parse input", &err_rc); + cYAML_print_tree2file(stderr, err_rc); + cYAML_free_tree(err_rc); + return -1; + } + break; + case '?': + print_help(cmd_list, "", "cpt-of-nid"); + default: + return 0; + } + } + + cpt = lustre_lnet_calc_cpt_of_nid(nid, ncpts); + if (cpt < 0) + return -1; + + printf("cpt:\n value: %d\n", cpt); + + return 0; +} + static int jt_set_recovery_limit(int argc, char **argv) { long int value; -- 1.8.3.1