diff options
Diffstat (limited to 'drivers/staging/lustre/lustre/libcfs/nidstrings.c')
-rw-r--r-- | drivers/staging/lustre/lustre/libcfs/nidstrings.c | 842 |
1 files changed, 0 insertions, 842 deletions
diff --git a/drivers/staging/lustre/lustre/libcfs/nidstrings.c b/drivers/staging/lustre/lustre/libcfs/nidstrings.c deleted file mode 100644 index 087449f4e6c1..000000000000 --- a/drivers/staging/lustre/lustre/libcfs/nidstrings.c +++ /dev/null @@ -1,842 +0,0 @@ -/* - * GPL HEADER START - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License version 2 for more details (a copy is included - * in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - * GPL HEADER END - */ -/* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Use is subject to license terms. - * - * Copyright (c) 2011, 2012, Intel Corporation. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. - * - * libcfs/libcfs/nidstrings.c - * - * Author: Phil Schwan <phil@clusterfs.com> - */ - -#define DEBUG_SUBSYSTEM S_LNET - -#include "../../include/linux/libcfs/libcfs.h" -#include "../../include/linux/lnet/lnet.h" - -/* CAVEAT VENDITOR! Keep the canonical string representation of nets/nids - * consistent in all conversion functions. Some code fragments are copied - * around for the sake of clarity... - */ - -/* CAVEAT EMPTOR! Racey temporary buffer allocation! - * Choose the number of nidstrings to support the MAXIMUM expected number of - * concurrent users. If there are more, the returned string will be volatile. - * NB this number must allow for a process to be descheduled for a timeslice - * between getting its string and using it. - */ - -static char libcfs_nidstrings[LNET_NIDSTR_COUNT][LNET_NIDSTR_SIZE]; -static int libcfs_nidstring_idx; - -static spinlock_t libcfs_nidstring_lock; - -void libcfs_init_nidstrings(void) -{ - spin_lock_init(&libcfs_nidstring_lock); -} - -static char * -libcfs_next_nidstring(void) -{ - char *str; - unsigned long flags; - - spin_lock_irqsave(&libcfs_nidstring_lock, flags); - - str = libcfs_nidstrings[libcfs_nidstring_idx++]; - if (libcfs_nidstring_idx == ARRAY_SIZE(libcfs_nidstrings)) - libcfs_nidstring_idx = 0; - - spin_unlock_irqrestore(&libcfs_nidstring_lock, flags); - return str; -} - -static int libcfs_lo_str2addr(const char *str, int nob, __u32 *addr) -{ - *addr = 0; - return 1; -} - -static void libcfs_ip_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", - (addr >> 24) & 0xff, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff); -} - -static int libcfs_ip_str2addr(const char *str, int nob, __u32 *addr) -{ - unsigned int a; - unsigned int b; - unsigned int c; - unsigned int d; - int n = nob; /* XscanfX */ - - /* numeric IP? */ - if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && - n == nob && - (a & ~0xff) == 0 && (b & ~0xff) == 0 && - (c & ~0xff) == 0 && (d & ~0xff) == 0) { - *addr = ((a<<24)|(b<<16)|(c<<8)|d); - return 1; - } - - return 0; -} - -static void libcfs_decnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); -} - -static void libcfs_hexnum_addr2str(__u32 addr, char *str) -{ - snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); -} - -static int libcfs_num_str2addr(const char *str, int nob, __u32 *addr) -{ - int n; - - n = nob; - if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) - return 1; - - n = nob; - if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) - return 1; - - return 0; -} - -/** - * Nf_parse_addrlist method for networks using numeric addresses. - * - * Examples of such networks are gm and elan. - * - * \retval 0 if \a str parsed to numeric address - * \retval errno otherwise - */ -static int -libcfs_num_parse(char *str, int len, struct list_head *list) -{ - struct cfs_expr_list *el; - int rc; - - rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el); - if (rc == 0) - list_add_tail(&el->el_link, list); - - return rc; -} - -/* - * Nf_match_addr method for networks using numeric addresses - * - * \retval 1 on match - * \retval 0 otherwise - */ -static int -libcfs_num_match(__u32 addr, struct list_head *numaddr) -{ - struct cfs_expr_list *el; - - LASSERT(!list_empty(numaddr)); - el = list_entry(numaddr->next, struct cfs_expr_list, el_link); - - return cfs_expr_list_match(addr, el); -} - -struct netstrfns { - int nf_type; - char *nf_name; - char *nf_modname; - void (*nf_addr2str)(__u32 addr, char *str); - int (*nf_str2addr)(const char *str, int nob, __u32 *addr); - int (*nf_parse_addrlist)(char *str, int len, - struct list_head *list); - int (*nf_match_addr)(__u32 addr, struct list_head *list); -}; - -static struct netstrfns libcfs_netstrfns[] = { - {/* .nf_type */ LOLND, - /* .nf_name */ "lo", - /* .nf_modname */ "klolnd", - /* .nf_addr2str */ libcfs_decnum_addr2str, - /* .nf_str2addr */ libcfs_lo_str2addr, - /* .nf_parse_addr*/ libcfs_num_parse, - /* .nf_match_addr*/ libcfs_num_match}, - {/* .nf_type */ SOCKLND, - /* .nf_name */ "tcp", - /* .nf_modname */ "ksocklnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ O2IBLND, - /* .nf_name */ "o2ib", - /* .nf_modname */ "ko2iblnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ CIBLND, - /* .nf_name */ "cib", - /* .nf_modname */ "kciblnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ OPENIBLND, - /* .nf_name */ "openib", - /* .nf_modname */ "kopeniblnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ IIBLND, - /* .nf_name */ "iib", - /* .nf_modname */ "kiiblnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ VIBLND, - /* .nf_name */ "vib", - /* .nf_modname */ "kviblnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ RALND, - /* .nf_name */ "ra", - /* .nf_modname */ "kralnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ QSWLND, - /* .nf_name */ "elan", - /* .nf_modname */ "kqswlnd", - /* .nf_addr2str */ libcfs_decnum_addr2str, - /* .nf_str2addr */ libcfs_num_str2addr, - /* .nf_parse_addrlist*/ libcfs_num_parse, - /* .nf_match_addr*/ libcfs_num_match}, - {/* .nf_type */ GMLND, - /* .nf_name */ "gm", - /* .nf_modname */ "kgmlnd", - /* .nf_addr2str */ libcfs_hexnum_addr2str, - /* .nf_str2addr */ libcfs_num_str2addr, - /* .nf_parse_addrlist*/ libcfs_num_parse, - /* .nf_match_addr*/ libcfs_num_match}, - {/* .nf_type */ MXLND, - /* .nf_name */ "mx", - /* .nf_modname */ "kmxlnd", - /* .nf_addr2str */ libcfs_ip_addr2str, - /* .nf_str2addr */ libcfs_ip_str2addr, - /* .nf_parse_addrlist*/ cfs_ip_addr_parse, - /* .nf_match_addr*/ cfs_ip_addr_match}, - {/* .nf_type */ PTLLND, - /* .nf_name */ "ptl", - /* .nf_modname */ "kptllnd", - /* .nf_addr2str */ libcfs_decnum_addr2str, - /* .nf_str2addr */ libcfs_num_str2addr, - /* .nf_parse_addrlist*/ libcfs_num_parse, - /* .nf_match_addr*/ libcfs_num_match}, - {/* .nf_type */ GNILND, - /* .nf_name */ "gni", - /* .nf_modname */ "kgnilnd", - /* .nf_addr2str */ libcfs_decnum_addr2str, - /* .nf_str2addr */ libcfs_num_str2addr, - /* .nf_parse_addrlist*/ libcfs_num_parse, - /* .nf_match_addr*/ libcfs_num_match}, - /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */ - {/* .nf_type */ -1}, -}; - -static const int libcfs_nnetstrfns = ARRAY_SIZE(libcfs_netstrfns); - -/* CAVEAT EMPTOR XscanfX - * I use "%n" at the end of a sscanf format to detect trailing junk. However - * sscanf may return immediately if it sees the terminating '0' in a string, so - * I initialise the %n variable to the expected length. If sscanf sets it; - * fine, if it doesn't, then the scan ended at the end of the string, which is - * fine too :) */ - -static struct netstrfns * -libcfs_lnd2netstrfns(int lnd) -{ - int i; - - if (lnd >= 0) - for (i = 0; i < libcfs_nnetstrfns; i++) - if (lnd == libcfs_netstrfns[i].nf_type) - return &libcfs_netstrfns[i]; - - return NULL; -} - -static struct netstrfns * -libcfs_namenum2netstrfns(const char *name) -{ - struct netstrfns *nf; - int i; - - for (i = 0; i < libcfs_nnetstrfns; i++) { - nf = &libcfs_netstrfns[i]; - if (nf->nf_type >= 0 && - !strncmp(name, nf->nf_name, strlen(nf->nf_name))) - return nf; - } - return NULL; -} - -static struct netstrfns * -libcfs_name2netstrfns(const char *name) -{ - int i; - - for (i = 0; i < libcfs_nnetstrfns; i++) - if (libcfs_netstrfns[i].nf_type >= 0 && - !strcmp(libcfs_netstrfns[i].nf_name, name)) - return &libcfs_netstrfns[i]; - - return NULL; -} - -int -libcfs_isknown_lnd(int type) -{ - return libcfs_lnd2netstrfns(type) != NULL; -} -EXPORT_SYMBOL(libcfs_isknown_lnd); - -char * -libcfs_lnd2modname(int lnd) -{ - struct netstrfns *nf = libcfs_lnd2netstrfns(lnd); - - return (nf == NULL) ? NULL : nf->nf_modname; -} -EXPORT_SYMBOL(libcfs_lnd2modname); - -char * -libcfs_lnd2str(int lnd) -{ - char *str; - struct netstrfns *nf = libcfs_lnd2netstrfns(lnd); - - if (nf != NULL) - return nf->nf_name; - - str = libcfs_next_nidstring(); - snprintf(str, LNET_NIDSTR_SIZE, "?%d?", lnd); - return str; -} -EXPORT_SYMBOL(libcfs_lnd2str); - -int -libcfs_str2lnd(const char *str) -{ - struct netstrfns *nf = libcfs_name2netstrfns(str); - - if (nf != NULL) - return nf->nf_type; - - return -1; -} -EXPORT_SYMBOL(libcfs_str2lnd); - -char * -libcfs_net2str(__u32 net) -{ - int lnd = LNET_NETTYP(net); - int num = LNET_NETNUM(net); - struct netstrfns *nf = libcfs_lnd2netstrfns(lnd); - char *str = libcfs_next_nidstring(); - - if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "<%d:%d>", lnd, num); - else if (num == 0) - snprintf(str, LNET_NIDSTR_SIZE, "%s", nf->nf_name); - else - snprintf(str, LNET_NIDSTR_SIZE, "%s%d", nf->nf_name, num); - - return str; -} -EXPORT_SYMBOL(libcfs_net2str); - -char * -libcfs_nid2str(lnet_nid_t nid) -{ - __u32 addr = LNET_NIDADDR(nid); - __u32 net = LNET_NIDNET(nid); - int lnd = LNET_NETTYP(net); - int nnum = LNET_NETNUM(net); - struct netstrfns *nf; - char *str; - int nob; - - if (nid == LNET_NID_ANY) - return "<?>"; - - nf = libcfs_lnd2netstrfns(lnd); - str = libcfs_next_nidstring(); - - if (nf == NULL) - snprintf(str, LNET_NIDSTR_SIZE, "%x@<%d:%d>", addr, lnd, nnum); - else { - nf->nf_addr2str(addr, str); - nob = strlen(str); - if (nnum == 0) - snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s", - nf->nf_name); - else - snprintf(str + nob, LNET_NIDSTR_SIZE - nob, "@%s%d", - nf->nf_name, nnum); - } - - return str; -} -EXPORT_SYMBOL(libcfs_nid2str); - -static struct netstrfns * -libcfs_str2net_internal(const char *str, __u32 *net) -{ - struct netstrfns *uninitialized_var(nf); - int nob; - unsigned int netnum; - int i; - - for (i = 0; i < libcfs_nnetstrfns; i++) { - nf = &libcfs_netstrfns[i]; - if (nf->nf_type >= 0 && - !strncmp(str, nf->nf_name, strlen(nf->nf_name))) - break; - } - - if (i == libcfs_nnetstrfns) - return NULL; - - nob = strlen(nf->nf_name); - - if (strlen(str) == (unsigned int)nob) { - netnum = 0; - } else { - if (nf->nf_type == LOLND) /* net number not allowed */ - return NULL; - - str += nob; - i = strlen(str); - if (sscanf(str, "%u%n", &netnum, &i) < 1 || - i != (int)strlen(str)) - return NULL; - } - - *net = LNET_MKNET(nf->nf_type, netnum); - return nf; -} - -__u32 -libcfs_str2net(const char *str) -{ - __u32 net; - - if (libcfs_str2net_internal(str, &net) != NULL) - return net; - - return LNET_NIDNET(LNET_NID_ANY); -} -EXPORT_SYMBOL(libcfs_str2net); - -lnet_nid_t -libcfs_str2nid(const char *str) -{ - const char *sep = strchr(str, '@'); - struct netstrfns *nf; - __u32 net; - __u32 addr; - - if (sep != NULL) { - nf = libcfs_str2net_internal(sep + 1, &net); - if (nf == NULL) - return LNET_NID_ANY; - } else { - sep = str + strlen(str); - net = LNET_MKNET(SOCKLND, 0); - nf = libcfs_lnd2netstrfns(SOCKLND); - LASSERT(nf != NULL); - } - - if (!nf->nf_str2addr(str, (int)(sep - str), &addr)) - return LNET_NID_ANY; - - return LNET_MKNID(net, addr); -} -EXPORT_SYMBOL(libcfs_str2nid); - -char * -libcfs_id2str(lnet_process_id_t id) -{ - char *str = libcfs_next_nidstring(); - - if (id.pid == LNET_PID_ANY) { - snprintf(str, LNET_NIDSTR_SIZE, - "LNET_PID_ANY-%s", libcfs_nid2str(id.nid)); - return str; - } - - snprintf(str, LNET_NIDSTR_SIZE, "%s%u-%s", - ((id.pid & LNET_PID_USERFLAG) != 0) ? "U" : "", - (id.pid & ~LNET_PID_USERFLAG), libcfs_nid2str(id.nid)); - return str; -} -EXPORT_SYMBOL(libcfs_id2str); - -int -libcfs_str2anynid(lnet_nid_t *nidp, const char *str) -{ - if (!strcmp(str, "*")) { - *nidp = LNET_NID_ANY; - return 1; - } - - *nidp = libcfs_str2nid(str); - return *nidp != LNET_NID_ANY; -} -EXPORT_SYMBOL(libcfs_str2anynid); - -/** - * Nid range list syntax. - * \verbatim - * - * <nidlist> :== <nidrange> [ ' ' <nidrange> ] - * <nidrange> :== <addrrange> '@' <net> - * <addrrange> :== '*' | - * <ipaddr_range> | - * <cfs_expr_list> - * <ipaddr_range> :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>. - * <cfs_expr_list> - * <cfs_expr_list> :== <number> | - * <expr_list> - * <expr_list> :== '[' <range_expr> [ ',' <range_expr>] ']' - * <range_expr> :== <number> | - * <number> '-' <number> | - * <number> '-' <number> '/' <number> - * <net> :== <netname> | <netname><number> - * <netname> :== "lo" | "tcp" | "o2ib" | "cib" | "openib" | "iib" | - * "vib" | "ra" | "elan" | "mx" | "ptl" - * \endverbatim - */ - -/** - * Structure to represent \<nidrange\> token of the syntax. - * - * One of this is created for each \<net\> parsed. - */ -struct nidrange { - /** - * Link to list of this structures which is built on nid range - * list parsing. - */ - struct list_head nr_link; - /** - * List head for addrrange::ar_link. - */ - struct list_head nr_addrranges; - /** - * Flag indicating that *@<net> is found. - */ - int nr_all; - /** - * Pointer to corresponding element of libcfs_netstrfns. - */ - struct netstrfns *nr_netstrfns; - /** - * Number of network. E.g. 5 if \<net\> is "elan5". - */ - int nr_netnum; -}; - -/** - * Structure to represent \<addrrange\> token of the syntax. - */ -struct addrrange { - /** - * Link to nidrange::nr_addrranges. - */ - struct list_head ar_link; - /** - * List head for cfs_expr_list::el_list. - */ - struct list_head ar_numaddr_ranges; -}; - -/** - * Parses \<addrrange\> token on the syntax. - * - * Allocates struct addrrange and links to \a nidrange via - * (nidrange::nr_addrranges) - * - * \retval 1 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\> - * \retval 0 otherwise - */ -static int -parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange) -{ - struct addrrange *addrrange; - - if (src->ls_len == 1 && src->ls_str[0] == '*') { - nidrange->nr_all = 1; - return 1; - } - - LIBCFS_ALLOC(addrrange, sizeof(struct addrrange)); - if (addrrange == NULL) - return 0; - list_add_tail(&addrrange->ar_link, &nidrange->nr_addrranges); - INIT_LIST_HEAD(&addrrange->ar_numaddr_ranges); - - return nidrange->nr_netstrfns->nf_parse_addrlist(src->ls_str, - src->ls_len, - &addrrange->ar_numaddr_ranges); -} - -/** - * Finds or creates struct nidrange. - * - * Checks if \a src is a valid network name, looks for corresponding - * nidrange on the ist of nidranges (\a nidlist), creates new struct - * nidrange if it is not found. - * - * \retval pointer to struct nidrange matching network specified via \a src - * \retval NULL if \a src does not match any network - */ -static struct nidrange * -add_nidrange(const struct cfs_lstr *src, - struct list_head *nidlist) -{ - struct netstrfns *nf; - struct nidrange *nr; - int endlen; - unsigned netnum; - - if (src->ls_len >= LNET_NIDSTR_SIZE) - return NULL; - - nf = libcfs_namenum2netstrfns(src->ls_str); - if (nf == NULL) - return NULL; - endlen = src->ls_len - strlen(nf->nf_name); - if (endlen == 0) - /* network name only, e.g. "elan" or "tcp" */ - netnum = 0; - else { - /* e.g. "elan25" or "tcp23", refuse to parse if - * network name is not appended with decimal or - * hexadecimal number */ - if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name), - endlen, &netnum, 0, MAX_NUMERIC_VALUE)) - return NULL; - } - - list_for_each_entry(nr, nidlist, nr_link) { - if (nr->nr_netstrfns != nf) - continue; - if (nr->nr_netnum != netnum) - continue; - return nr; - } - - LIBCFS_ALLOC(nr, sizeof(struct nidrange)); - if (nr == NULL) - return NULL; - list_add_tail(&nr->nr_link, nidlist); - INIT_LIST_HEAD(&nr->nr_addrranges); - nr->nr_netstrfns = nf; - nr->nr_all = 0; - nr->nr_netnum = netnum; - - return nr; -} - -/** - * Parses \<nidrange\> token of the syntax. - * - * \retval 1 if \a src parses to \<addrrange\> '@' \<net\> - * \retval 0 otherwise - */ -static int -parse_nidrange(struct cfs_lstr *src, struct list_head *nidlist) -{ - struct cfs_lstr addrrange; - struct cfs_lstr net; - struct cfs_lstr tmp; - struct nidrange *nr; - - tmp = *src; - if (cfs_gettok(src, '@', &addrrange) == 0) - goto failed; - - if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL) - goto failed; - - nr = add_nidrange(&net, nidlist); - if (nr == NULL) - goto failed; - - if (parse_addrange(&addrrange, nr) != 0) - goto failed; - - return 1; - failed: - CWARN("can't parse nidrange: \"%.*s\"\n", tmp.ls_len, tmp.ls_str); - return 0; -} - -/** - * Frees addrrange structures of \a list. - * - * For each struct addrrange structure found on \a list it frees - * cfs_expr_list list attached to it and frees the addrrange itself. - * - * \retval none - */ -static void -free_addrranges(struct list_head *list) -{ - while (!list_empty(list)) { - struct addrrange *ar; - - ar = list_entry(list->next, struct addrrange, ar_link); - - cfs_expr_list_free_list(&ar->ar_numaddr_ranges); - list_del(&ar->ar_link); - LIBCFS_FREE(ar, sizeof(struct addrrange)); - } -} - -/** - * Frees nidrange strutures of \a list. - * - * For each struct nidrange structure found on \a list it frees - * addrrange list attached to it and frees the nidrange itself. - * - * \retval none - */ -void -cfs_free_nidlist(struct list_head *list) -{ - struct list_head *pos, *next; - struct nidrange *nr; - - list_for_each_safe(pos, next, list) { - nr = list_entry(pos, struct nidrange, nr_link); - free_addrranges(&nr->nr_addrranges); - list_del(pos); - LIBCFS_FREE(nr, sizeof(struct nidrange)); - } -} -EXPORT_SYMBOL(cfs_free_nidlist); - -/** - * Parses nid range list. - * - * Parses with rigorous syntax and overflow checking \a str into - * \<nidrange\> [ ' ' \<nidrange\> ], compiles \a str into set of - * structures and links that structure to \a nidlist. The resulting - * list can be used to match a NID againts set of NIDS defined by \a - * str. - * \see cfs_match_nid - * - * \retval 1 on success - * \retval 0 otherwise - */ -int -cfs_parse_nidlist(char *str, int len, struct list_head *nidlist) -{ - struct cfs_lstr src; - struct cfs_lstr res; - int rc; - - src.ls_str = str; - src.ls_len = len; - INIT_LIST_HEAD(nidlist); - while (src.ls_str) { - rc = cfs_gettok(&src, ' ', &res); - if (rc == 0) { - cfs_free_nidlist(nidlist); - return 0; - } - rc = parse_nidrange(&res, nidlist); - if (rc == 0) { - cfs_free_nidlist(nidlist); - return 0; - } - } - return 1; -} -EXPORT_SYMBOL(cfs_parse_nidlist); - -/** - * Matches a nid (\a nid) against the compiled list of nidranges (\a nidlist). - * - * \see cfs_parse_nidlist() - * - * \retval 1 on match - * \retval 0 otherwises - */ -int cfs_match_nid(lnet_nid_t nid, struct list_head *nidlist) -{ - struct nidrange *nr; - struct addrrange *ar; - - list_for_each_entry(nr, nidlist, nr_link) { - if (nr->nr_netstrfns->nf_type != LNET_NETTYP(LNET_NIDNET(nid))) - continue; - if (nr->nr_netnum != LNET_NETNUM(LNET_NIDNET(nid))) - continue; - if (nr->nr_all) - return 1; - list_for_each_entry(ar, &nr->nr_addrranges, ar_link) - if (nr->nr_netstrfns->nf_match_addr(LNET_NIDADDR(nid), - &ar->ar_numaddr_ranges)) - return 1; - } - return 0; -} -EXPORT_SYMBOL(cfs_match_nid); |