Whamcloud - gitweb
LU-3527 nodemap: add NID range management 57/8057/15
authorJoshua Walgenbach <jjw@iu.edu>
Fri, 17 Jan 2014 21:21:31 +0000 (22:21 +0100)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 28 Feb 2014 23:13:07 +0000 (23:13 +0000)
The nodemap module defines a nodemap as a set of NID ranges
and a policy that is applied to them. This adds the range
management functions to nodemap. The definition of a range
is kept in the range_node structure.

The range_node structures are kept in a global rb_tree for
ease and speed of managing the range_nodes (each range_node
can be a member of eexactly one nodemap). The range_node
contains a pointer back to the nodemap of which it is a
member. The range_node also keeps the (inclusive) start and
end of the NID range is represents.

Additionally, each nodemap contains a linked list of the
pointers to the range_node in encompasses, for use in
management of the nodemap (deleting, checking ranges, etc)
to prevent walking the range_node tree.

Commands have been added to lctl to control the range management
and other nodemap policy features (squash ids, admin, trusted)
that will control its behavior with regards to ID mapping.

Unit tests have been added to sanity-sec.sh to check the
range management and policy controls.

Signed-off-by: Joshua Walgenbach <jjw@iu.edu>
Change-Id: I2b93f15de8f07a2bcef16fde27fb03a41a2063bc
Reviewed-on: http://review.whamcloud.com/8057
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andrew Perepechko <andrew_perepechko@xyratex.com>
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Reviewed-by: Ken Hornstein <kenh@cmf.nrl.navy.mil>
16 files changed:
libcfs/include/libcfs/libcfs_private.h
libcfs/libcfs/nidstrings.c
lustre/Makefile.in
lustre/include/lustre_cfg.h
lustre/include/lustre_nodemap.h
lustre/mgs/mgs_handler.c
lustre/mgs/mgs_llog.c
lustre/nodemap/Makefile.in
lustre/nodemap/nodemap_handler.c
lustre/nodemap/nodemap_internal.h
lustre/nodemap/nodemap_lproc.c
lustre/nodemap/nodemap_range.c [new file with mode: 0644]
lustre/tests/sanity-sec.sh
lustre/utils/lctl.c
lustre/utils/obd.c
lustre/utils/obdctl.h

index f27f29c..ee5f1da 100644 (file)
@@ -552,6 +552,10 @@ int                 cfs_parse_nidlist(char *str, int len, struct list_head *list);
 int             cfs_print_nidlist(char *buffer, int count,
                                   struct list_head *list);
 int             cfs_match_nid(lnet_nid_t nid, struct list_head *list);
 int             cfs_print_nidlist(char *buffer, int count,
                                   struct list_head *list);
 int             cfs_match_nid(lnet_nid_t nid, struct list_head *list);
+bool            cfs_nidrange_is_contiguous(struct list_head *nidlist);
+void            cfs_nidrange_find_min_max(struct list_head *nidlist,
+                                          char *min_nid, char *max_nid,
+                                          int nidstr_length);
 
 /** \addtogroup lnet_addr
  * @{ */
 
 /** \addtogroup lnet_addr
  * @{ */
index a78dd85..8235f0e 100644 (file)
@@ -48,6 +48,8 @@
 #endif
 #endif
 
 #endif
 #endif
 
+#define IPSTRING_LENGTH 16
+
 /* 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 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...
@@ -98,6 +100,8 @@ libcfs_next_nidstring (void)
 static int  libcfs_lo_str2addr(const char *str, int nob, __u32 *addr);
 static void libcfs_ip_addr2str(__u32 addr, char *str);
 static int  libcfs_ip_str2addr(const char *str, int nob, __u32 *addr);
 static int  libcfs_lo_str2addr(const char *str, int nob, __u32 *addr);
 static void libcfs_ip_addr2str(__u32 addr, char *str);
 static int  libcfs_ip_str2addr(const char *str, int nob, __u32 *addr);
+static bool cfs_ip_is_contiguous(struct list_head *nidlist);
+static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
 static void libcfs_decnum_addr2str(__u32 addr, char *str);
 static void libcfs_hexnum_addr2str(__u32 addr, char *str);
 static int  libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
 static void libcfs_decnum_addr2str(__u32 addr, char *str);
 static void libcfs_hexnum_addr2str(__u32 addr, char *str);
 static int  libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
@@ -107,6 +111,8 @@ static int  libcfs_num_addr_range_print(char *buffer, int count,
                                        struct list_head *list);
 static int  libcfs_ip_addr_range_print(char *buffer, int count,
                                       struct list_head *list);
                                        struct list_head *list);
 static int  libcfs_ip_addr_range_print(char *buffer, int count,
                                       struct list_head *list);
+static bool cfs_num_is_contiguous(struct list_head *nidlist);
+static void cfs_num_min_max(struct list_head *nidlist, __u32 *min, __u32 *max);
 
 struct netstrfns {
        int      nf_type;
 
 struct netstrfns {
        int      nf_type;
@@ -119,6 +125,9 @@ struct netstrfns {
        int     (*nf_print_addrlist)(char *buffer, int count,
                                     struct list_head *list);
        int     (*nf_match_addr)(__u32 addr, struct list_head *list);
        int     (*nf_print_addrlist)(char *buffer, int count,
                                     struct list_head *list);
        int     (*nf_match_addr)(__u32 addr, struct list_head *list);
+       bool    (*nf_is_contiguous)(struct list_head *nidlist);
+       void    (*nf_min_max)(struct list_head *nidlist, __u32 *min_nid,
+                               __u32 *max_nid);
 };
 
 static struct netstrfns  libcfs_netstrfns[] = {
 };
 
 static struct netstrfns  libcfs_netstrfns[] = {
@@ -129,7 +138,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_lo_str2addr,
         /* .nf_parse_addr*/  libcfs_num_parse,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
         /* .nf_str2addr  */  libcfs_lo_str2addr,
         /* .nf_parse_addr*/  libcfs_num_parse,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
-        /* .nf_match_addr*/  libcfs_num_match},
+        /* .nf_match_addr*/      libcfs_num_match,
+        /* .nf_is_contiguous */  cfs_num_is_contiguous,
+        /* .nf_min_max   */      cfs_num_min_max},
        {/* .nf_type      */  SOCKLND,
         /* .nf_name      */  "tcp",
         /* .nf_modname   */  "ksocklnd",
        {/* .nf_type      */  SOCKLND,
         /* .nf_name      */  "tcp",
         /* .nf_modname   */  "ksocklnd",
@@ -137,7 +148,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  O2IBLND,
         /* .nf_name      */  "o2ib",
         /* .nf_modname   */  "ko2iblnd",
        {/* .nf_type      */  O2IBLND,
         /* .nf_name      */  "o2ib",
         /* .nf_modname   */  "ko2iblnd",
@@ -145,7 +158,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  CIBLND,
         /* .nf_name      */  "cib",
         /* .nf_modname   */  "kciblnd",
        {/* .nf_type      */  CIBLND,
         /* .nf_name      */  "cib",
         /* .nf_modname   */  "kciblnd",
@@ -153,7 +168,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  OPENIBLND,
         /* .nf_name      */  "openib",
         /* .nf_modname   */  "kopeniblnd",
        {/* .nf_type      */  OPENIBLND,
         /* .nf_name      */  "openib",
         /* .nf_modname   */  "kopeniblnd",
@@ -161,7 +178,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  IIBLND,
         /* .nf_name      */  "iib",
         /* .nf_modname   */  "kiiblnd",
        {/* .nf_type      */  IIBLND,
         /* .nf_name      */  "iib",
         /* .nf_modname   */  "kiiblnd",
@@ -169,7 +188,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  VIBLND,
         /* .nf_name      */  "vib",
         /* .nf_modname   */  "kviblnd",
        {/* .nf_type      */  VIBLND,
         /* .nf_name      */  "vib",
         /* .nf_modname   */  "kviblnd",
@@ -177,7 +198,9 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
        {/* .nf_type      */  RALND,
         /* .nf_name      */  "ra",
         /* .nf_modname   */  "kralnd",
        {/* .nf_type      */  RALND,
         /* .nf_name      */  "ra",
         /* .nf_modname   */  "kralnd",
@@ -185,57 +208,71 @@ static struct netstrfns  libcfs_netstrfns[] = {
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_str2addr  */  libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .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*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
+       {/* .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_print_addrlist*/  libcfs_num_addr_range_print,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
-         /* .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_is_contiguous */  cfs_num_is_contiguous,
+        /* .nf_min_max   */      cfs_num_min_max},
+       {/* .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_print_addrlist*/  libcfs_num_addr_range_print,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
-         /* .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_match_addr*/      libcfs_num_match,
+        /* .nf_is_contiguous */  cfs_num_is_contiguous,
+        /* .nf_min_max   */      cfs_num_min_max},
+       {/* .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_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .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*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
+       {/* .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_print_addrlist*/  libcfs_num_addr_range_print,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
-         /* .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,
+        /* .nf_is_contiguous */  cfs_num_is_contiguous,
+        /* .nf_min_max   */      cfs_num_min_max},
+       {/* .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_print_addrlist*/  libcfs_num_addr_range_print,
         /* .nf_print_addrlist*/  libcfs_num_addr_range_print,
-         /* .nf_match_addr*/  libcfs_num_match},
-       {/* .nf_type      */  GNIIPLND,
-        /* .nf_name      */  "gip",
-        /* .nf_modname   */  "kgnilnd",
-        /* .nf_addr2str  */  libcfs_ip_addr2str,
-        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_match_addr*/      libcfs_num_match,
+        /* .nf_is_contiguous */  cfs_num_is_contiguous,
+        /* .nf_min_max   */      cfs_num_min_max},
+       {/* .nf_type      */      GNIIPLND,
+        /* .nf_name      */      "gip",
+        /* .nf_modname   */      "kgnilnd",
+        /* .nf_addr2str  */      libcfs_ip_addr2str,
+        /* .nf_str2addr  */      libcfs_ip_str2addr,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
         /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
         /* .nf_print_addrlist*/  libcfs_ip_addr_range_print,
-        /* .nf_match_addr*/  cfs_ip_addr_match},
-        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
-        {/* .nf_type      */  -1},
+        /* .nf_match_addr*/      cfs_ip_addr_match,
+        /* .nf_is_contiguous */  cfs_ip_is_contiguous,
+        /* .nf_min_max   */      cfs_ip_min_max},
+        /* placeholder for net0 alias.  It MUST BE THE LAST ENTRY */
+       {/* .nf_type      */  -1},
 };
 
 const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
 };
 
 const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]);
@@ -1027,6 +1064,318 @@ int cfs_print_nidlist(char *buffer, int count, struct list_head *nidlist)
        RETURN(i);
 }
 
        RETURN(i);
 }
 
+/**
+ * Determines minimum and maximum addresses for a single
+ * numeric address range
+ *
+ * \param      ar
+ * \param      min_nid
+ * \param      max_nid
+ */
+static void cfs_ip_ar_min_max(struct addrrange *ar, __u32 *min_nid,
+                             __u32 *max_nid)
+{
+       struct cfs_expr_list    *el;
+       struct cfs_range_expr   *re;
+       __u32                   tmp_ip_addr = 0;
+       unsigned int            min_ip[4] = {0};
+       unsigned int            max_ip[4] = {0};
+       int                     re_count = 0;
+
+       list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
+               list_for_each_entry(re, &el->el_exprs, re_link) {
+                       min_ip[re_count] = re->re_lo;
+                       max_ip[re_count] = re->re_hi;
+                       re_count++;
+               }
+       }
+
+       tmp_ip_addr = ((min_ip[0] << 24) | (min_ip[1] << 16) |
+                      (min_ip[2] << 8) | min_ip[3]);
+
+       if (min_nid != NULL)
+               *min_nid = tmp_ip_addr;
+
+       tmp_ip_addr = ((max_ip[0] << 24) | (max_ip[1] << 16) |
+                      (max_ip[2] << 8) | max_ip[3]);
+
+       if (max_nid != NULL)
+               *max_nid = tmp_ip_addr;
+}
+
+/**
+ * Determines minimum and maximum addresses for a single
+ * numeric address range
+ *
+ * \param      ar
+ * \param      min_nid
+ * \param      max_nid
+ */
+static void cfs_num_ar_min_max(struct addrrange *ar, __u32 *min_nid,
+                              __u32 *max_nid)
+{
+       struct cfs_expr_list    *el;
+       struct cfs_range_expr   *re;
+       unsigned int            min_addr = 0;
+       unsigned int            max_addr = 0;
+
+       list_for_each_entry(el, &ar->ar_numaddr_ranges, el_link) {
+               list_for_each_entry(re, &el->el_exprs, re_link) {
+                       if (re->re_lo < min_addr || min_addr == 0)
+                               min_addr = re->re_lo;
+                       if (re->re_hi > max_addr)
+                               max_addr = re->re_hi;
+               }
+       }
+
+       if (min_nid != NULL)
+               *min_nid = min_addr;
+       if (max_nid != NULL)
+               *max_nid = max_addr;
+}
+
+/**
+ * Determines whether an expression list in an nidrange contains exactly
+ * one contiguous address range. Calls the correct netstrfns for the LND
+ *
+ * \param      *nidlist
+ *
+ * \retval     true if contiguous
+ * \retval     false if not contiguous
+ */
+bool cfs_nidrange_is_contiguous(struct list_head *nidlist)
+{
+       struct nidrange         *nr;
+       struct netstrfns        *nf = NULL;
+       char                    *lndname = NULL;
+       int                     netnum = -1;
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               nf = nr->nr_netstrfns;
+               if (lndname == NULL)
+                       lndname = nf->nf_name;
+               if (netnum == -1)
+                       netnum = nr->nr_netnum;
+
+               if (strcmp(lndname, nf->nf_name) != 0 ||
+                   netnum != nr->nr_netnum)
+                       return false;
+       }
+
+       if (nf == NULL)
+               return false;
+
+       if (!nf->nf_is_contiguous(nidlist))
+               return false;
+
+       return true;
+}
+EXPORT_SYMBOL(cfs_nidrange_is_contiguous);
+
+/**
+ * Determines whether an expression list in an num nidrange contains exactly
+ * one contiguous address range.
+ *
+ * \param      *nidlist
+ *
+ * \retval     true if contiguous
+ * \retval     false if not contiguous
+ */
+static bool cfs_num_is_contiguous(struct list_head *nidlist)
+{
+       struct nidrange         *nr;
+       struct addrrange        *ar;
+       struct cfs_expr_list    *el;
+       struct cfs_range_expr   *re;
+       int                     last_hi = 0;
+       __u32                   last_end_nid = 0;
+       __u32                   current_start_nid = 0;
+       __u32                   current_end_nid = 0;
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+                       cfs_num_ar_min_max(ar, &current_start_nid,
+                                          &current_end_nid);
+                       if (last_end_nid != 0 &&
+                           (current_start_nid - last_end_nid != 1))
+                                       return false;
+                       last_end_nid = current_end_nid;
+                       list_for_each_entry(el, &ar->ar_numaddr_ranges,
+                                           el_link) {
+                               list_for_each_entry(re, &el->el_exprs,
+                                                   re_link) {
+                                       if (re->re_stride > 1)
+                                               return false;
+                                       else if (last_hi != 0 &&
+                                                re->re_hi - last_hi != 1)
+                                               return false;
+                                       last_hi = re->re_hi;
+                               }
+                       }
+               }
+       }
+
+       return true;
+}
+
+/**
+ * Determines whether an expression list in an ip nidrange contains exactly
+ * one contiguous address range.
+ *
+ * \param      *nidlist
+ *
+ * \retval     true if contiguous
+ * \retval     false if not contiguous
+ */
+static bool cfs_ip_is_contiguous(struct list_head *nidlist)
+{
+       struct nidrange         *nr;
+       struct addrrange        *ar;
+       struct cfs_expr_list    *el;
+       struct cfs_range_expr   *re;
+       int                     expr_count;
+       int                     last_hi = 255;
+       int                     last_diff = 0;
+       __u32                   last_end_nid = 0;
+       __u32                   current_start_nid = 0;
+       __u32                   current_end_nid = 0;
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+                       last_hi = 255;
+                       last_diff = 0;
+                       cfs_ip_ar_min_max(ar, &current_start_nid,
+                                         &current_end_nid);
+                       if (last_end_nid != 0 &&
+                           (current_start_nid - last_end_nid != 1))
+                                       return false;
+                       last_end_nid = current_end_nid;
+                       list_for_each_entry(el,
+                                           &ar->ar_numaddr_ranges,
+                                           el_link) {
+                               expr_count = 0;
+                               list_for_each_entry(re, &el->el_exprs,
+                                                   re_link) {
+                                       expr_count++;
+                                       if (re->re_stride > 1 ||
+                                           (last_diff > 0 && last_hi != 255) ||
+                                           (last_diff > 0 && last_hi == 255 &&
+                                            re->re_lo > 0))
+                                               return false;
+                                       last_hi = re->re_hi;
+                                       last_diff = re->re_hi - re->re_lo;
+                               }
+                       }
+               }
+       }
+
+       return true;
+}
+
+/**
+ * Takes a linked list of nidrange expressions, determines the minimum
+ * and maximum nid and creates appropriate nid structures
+ *
+ * \param      *nidlist
+ * \param      *min_nid
+ * \param      *max_nid
+ */
+void cfs_nidrange_find_min_max(struct list_head *nidlist, char *min_nid,
+                              char *max_nid, int nidstr_length)
+{
+       struct nidrange         *nr;
+       struct netstrfns        *nf = NULL;
+       int                     netnum = -1;
+       __u32                   min_addr;
+       __u32                   max_addr;
+       char                    *lndname = NULL;
+       char                    min_addr_str[IPSTRING_LENGTH];
+       char                    max_addr_str[IPSTRING_LENGTH];
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               nf = nr->nr_netstrfns;
+               lndname = nf->nf_name;
+               if (netnum == -1)
+                       netnum = nr->nr_netnum;
+
+               nf->nf_min_max(nidlist, &min_addr, &max_addr);
+       }
+       nf->nf_addr2str(min_addr, min_addr_str);
+       nf->nf_addr2str(max_addr, max_addr_str);
+
+       snprintf(min_nid, nidstr_length, "%s@%s%d", min_addr_str, lndname,
+                netnum);
+       snprintf(max_nid, nidstr_length, "%s@%s%d", max_addr_str, lndname,
+                netnum);
+}
+EXPORT_SYMBOL(cfs_nidrange_find_min_max);
+
+/**
+ * Determines the min and max NID values for num LNDs
+ *
+ * \param      *nidlist
+ * \param      *min_nid
+ * \param      *max_nid
+ */
+static void cfs_num_min_max(struct list_head *nidlist, __u32 *min_nid,
+                           __u32 *max_nid)
+{
+       struct nidrange         *nr;
+       struct addrrange        *ar;
+       unsigned int            tmp_min_addr = 0;
+       unsigned int            tmp_max_addr = 0;
+       unsigned int            min_addr = 0;
+       unsigned int            max_addr = 0;
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+                       cfs_num_ar_min_max(ar, &tmp_min_addr,
+                                          &tmp_max_addr);
+                       if (tmp_min_addr < min_addr || min_addr == 0)
+                               min_addr = tmp_min_addr;
+                       if (tmp_max_addr > max_addr)
+                               max_addr = tmp_min_addr;
+               }
+       }
+       *max_nid = max_addr;
+       *min_nid = min_addr;
+}
+
+/**
+ * Takes an nidlist and determines the minimum and maximum
+ * ip addresses.
+ *
+ * \param      *nidlist
+ * \param      *min_nid
+ * \param      *max_nid
+ */
+static void cfs_ip_min_max(struct list_head *nidlist, __u32 *min_nid,
+                          __u32 *max_nid)
+{
+       struct nidrange         *nr;
+       struct addrrange        *ar;
+       __u32                   tmp_min_ip_addr = 0;
+       __u32                   tmp_max_ip_addr = 0;
+       __u32                   min_ip_addr = 0;
+       __u32                   max_ip_addr = 0;
+
+       list_for_each_entry(nr, nidlist, nr_link) {
+               list_for_each_entry(ar, &nr->nr_addrranges, ar_link) {
+                       cfs_ip_ar_min_max(ar, &tmp_min_ip_addr,
+                                         &tmp_max_ip_addr);
+                       if (tmp_min_ip_addr < min_ip_addr || min_ip_addr == 0)
+                               min_ip_addr = tmp_min_ip_addr;
+                       if (tmp_max_ip_addr > max_ip_addr)
+                               max_ip_addr = tmp_max_ip_addr;
+               }
+       }
+
+       if (min_nid != NULL)
+               *min_nid = min_ip_addr;
+       if (max_nid != NULL)
+               *max_nid = max_ip_addr;
+}
+
 #ifdef __KERNEL__
 
 EXPORT_SYMBOL(libcfs_isknown_lnd);
 #ifdef __KERNEL__
 
 EXPORT_SYMBOL(libcfs_isknown_lnd);
index bbe0232..3e033ca 100644 (file)
@@ -3,7 +3,6 @@ subdir-m += obdclass
 subdir-m += ptlrpc
 subdir-m += obdecho
 subdir-m += mgc
 subdir-m += ptlrpc
 subdir-m += obdecho
 subdir-m += mgc
-subdir-m += nodemap
 
 @SERVER_TRUE@subdir-m += ost mgs mdt mdd ofd quota osp lod lfsck nodemap
 @CLIENT_TRUE@subdir-m += lov osc mdc lmv llite fld
 
 @SERVER_TRUE@subdir-m += ost mgs mdt mdd ofd quota osp lod lfsck nodemap
 @CLIENT_TRUE@subdir-m += lov osc mdc lmv llite fld
index 1aebf8b..2d8b83e 100644 (file)
@@ -105,6 +105,7 @@ enum lcfg_command_type {
        LCFG_NODEMAP_SQUASH_GID = 0x00ce052, /**< default map gid */
        LCFG_NODEMAP_ADD_SHKEY  = 0x00ce053, /**< add shared key to cluster */
        LCFG_NODEMAP_DEL_SHKEY  = 0x00ce054, /**< delete shared key from cluster */
        LCFG_NODEMAP_SQUASH_GID = 0x00ce052, /**< default map gid */
        LCFG_NODEMAP_ADD_SHKEY  = 0x00ce053, /**< add shared key to cluster */
        LCFG_NODEMAP_DEL_SHKEY  = 0x00ce054, /**< delete shared key from cluster */
+       LCFG_NODEMAP_TEST_NID   = 0x00ce055, /**< test for nodemap membership */
 };
 
 struct lustre_cfg_bufs {
 };
 
 struct lustre_cfg_bufs {
index a9ebad3..94bb0d7 100644 (file)
@@ -74,5 +74,13 @@ struct lu_nodemap {
 
 int nodemap_add(const char *nodemap_name);
 int nodemap_del(const char *nodemap_name);
 
 int nodemap_add(const char *nodemap_name);
 int nodemap_del(const char *nodemap_name);
+struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid);
+int nodemap_parse_range(const char *range_string, lnet_nid_t range[2]);
+int nodemap_add_range(const char *name, const lnet_nid_t nid[2]);
+int nodemap_del_range(const char *name, const lnet_nid_t nid[2]);
+int nodemap_set_allow_root(const char *name, bool allow_root);
+int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids);
+int nodemap_set_squash_uid(const char *name, uid_t uid);
+int nodemap_set_squash_gid(const char *name, gid_t gid);
 
 #endif
 
 #endif
index 5be9040..7c6b315 100644 (file)
@@ -624,11 +624,15 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
                                 struct mgs_device *mgs,
                                 struct obd_ioctl_data *data)
 {
                                 struct mgs_device *mgs,
                                 struct obd_ioctl_data *data)
 {
-       struct lustre_cfg *lcfg = NULL;
-       const char *nodemap_name;
-       char *param = NULL;
-       __u32 cmd;
-       int rc = 0;
+       struct lustre_cfg       *lcfg = NULL;
+       struct lu_nodemap       *nodemap;
+       lnet_nid_t              nid;
+       const char              *nodemap_name = NULL;
+       const char              *nidstr = NULL;
+       char                    *param = NULL;
+       int                     rc = 0;
+       __u32                   cmd;
+
        ENTRY;
 
        if (data->ioc_type != LUSTRE_CFG_TYPE) {
        ENTRY;
 
        if (data->ioc_type != LUSTRE_CFG_TYPE) {
@@ -647,7 +651,6 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
        if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
                GOTO(out_lcfg, rc = -EFAULT);
 
        if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
                GOTO(out_lcfg, rc = -EFAULT);
 
-       nodemap_name = lustre_cfg_string(lcfg, 1);
        cmd = lcfg->lcfg_command;
 
        switch (cmd) {
        cmd = lcfg->lcfg_command;
 
        switch (cmd) {
@@ -655,8 +658,39 @@ static int mgs_iocontrol_nodemap(const struct lu_env *env,
        case LCFG_NODEMAP_DEL:
                if (lcfg->lcfg_bufcount != 2)
                        GOTO(out_lcfg, rc = -EINVAL);
        case LCFG_NODEMAP_DEL:
                if (lcfg->lcfg_bufcount != 2)
                        GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
                rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
                break;
                rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
                break;
+       case LCFG_NODEMAP_TEST_NID:
+               if (lcfg->lcfg_bufcount != 2)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nidstr = lustre_cfg_string(lcfg, 1);
+               nid = libcfs_str2nid(nidstr);
+               nodemap = nodemap_classify_nid(nid);
+               memset(data->ioc_pbuf1, 0, data->ioc_plen1);
+               if (copy_to_user(data->ioc_pbuf1, nodemap->nm_name,
+                                strlen(nodemap->nm_name)) != 0)
+                       GOTO(out_lcfg, rc = -EFAULT);
+               break;
+       case LCFG_NODEMAP_ADD_RANGE:
+       case LCFG_NODEMAP_DEL_RANGE:
+               if (lcfg->lcfg_bufcount != 3)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 2);
+               rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
+               break;
+       case LCFG_NODEMAP_ADMIN:
+       case LCFG_NODEMAP_TRUSTED:
+       case LCFG_NODEMAP_SQUASH_UID:
+       case LCFG_NODEMAP_SQUASH_GID:
+               if (lcfg->lcfg_bufcount != 4)
+                       GOTO(out_lcfg, rc = -EINVAL);
+               nodemap_name = lustre_cfg_string(lcfg, 1);
+               param = lustre_cfg_string(lcfg, 3);
+               rc = mgs_nodemap_cmd(env, mgs, cmd, nodemap_name, param);
+               break;
+
        default:
                rc = -ENOTTY;
        }
        default:
                rc = -ENOTTY;
        }
index f88c10b..945dca5 100644 (file)
@@ -3896,7 +3896,10 @@ int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
                    enum lcfg_command_type cmd, const char *nodemap_name,
                    const char *param)
 {
                    enum lcfg_command_type cmd, const char *nodemap_name,
                    const char *param)
 {
-       int rc = 0;
+       lnet_nid_t      nid[2];
+       bool            bool_switch;
+       __u32           int_id;
+       int             rc = 0;
        ENTRY;
 
        switch (cmd) {
        ENTRY;
 
        switch (cmd) {
@@ -3906,6 +3909,34 @@ int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
        case LCFG_NODEMAP_DEL:
                rc = nodemap_del(nodemap_name);
                break;
        case LCFG_NODEMAP_DEL:
                rc = nodemap_del(nodemap_name);
                break;
+       case LCFG_NODEMAP_ADD_RANGE:
+               rc = nodemap_parse_range(param, nid);
+               if (rc != 0)
+                       break;
+               rc = nodemap_add_range(nodemap_name, nid);
+               break;
+       case LCFG_NODEMAP_DEL_RANGE:
+               rc = nodemap_parse_range(param, nid);
+               if (rc != 0)
+                       break;
+               rc = nodemap_del_range(nodemap_name, nid);
+               break;
+       case LCFG_NODEMAP_ADMIN:
+               bool_switch = simple_strtoul(param, NULL, 10);
+               rc = nodemap_set_allow_root(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_TRUSTED:
+               bool_switch = simple_strtoul(param, NULL, 10);
+               rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
+               break;
+       case LCFG_NODEMAP_SQUASH_UID:
+               int_id = simple_strtoul(param, NULL, 10);
+               rc = nodemap_set_squash_uid(nodemap_name, int_id);
+               break;
+       case LCFG_NODEMAP_SQUASH_GID:
+               int_id = simple_strtoul(param, NULL, 10);
+               rc = nodemap_set_squash_gid(nodemap_name, int_id);
+               break;
        default:
                rc = -EINVAL;
        }
        default:
                rc = -EINVAL;
        }
index fb34169..e6c9b53 100644 (file)
@@ -1,4 +1,4 @@
 MODULES := nodemap
 MODULES := nodemap
-nodemap-objs := nodemap_handler.o nodemap_lproc.o
+nodemap-objs := nodemap_handler.o nodemap_lproc.o nodemap_range.o
 
 @INCLUDE_RULES@
 
 @INCLUDE_RULES@
index d261d65..89e7aec 100644 (file)
@@ -62,7 +62,15 @@ static cfs_hash_t *nodemap_hash;
  */
 static void nodemap_destroy(struct lu_nodemap *nodemap)
 {
  */
 static void nodemap_destroy(struct lu_nodemap *nodemap)
 {
-       lprocfs_remove(&(nodemap->nm_proc_entry));
+       struct lu_nid_range *range;
+       struct lu_nid_range *temp;
+
+       list_for_each_entry_safe(range, temp, &nodemap->nm_ranges,
+                                rn_list) {
+               range_delete(range);
+       }
+
+       lprocfs_remove(&nodemap->nm_proc_entry);
        OBD_FREE_PTR(nodemap);
 }
 
        OBD_FREE_PTR(nodemap);
 }
 
@@ -98,6 +106,7 @@ static void *nodemap_hs_key(cfs_hlist_node_t *hnode)
        struct lu_nodemap *nodemap;
 
        nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
        struct lu_nodemap *nodemap;
 
        nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
+
        return nodemap->nm_name;
 }
 
        return nodemap->nm_name;
 }
 
@@ -107,6 +116,7 @@ static int nodemap_hs_keycmp(const void *key,
        struct lu_nodemap *nodemap;
 
        nodemap = nodemap_hs_key(compared_hnode);
        struct lu_nodemap *nodemap;
 
        nodemap = nodemap_hs_key(compared_hnode);
+
        return !strcmp(key, nodemap->nm_name);
 }
 
        return !strcmp(key, nodemap->nm_name);
 }
 
@@ -204,6 +214,10 @@ static int nodemap_init_hash(void)
  */
 static bool nodemap_name_is_valid(const char *name)
 {
  */
 static bool nodemap_name_is_valid(const char *name)
 {
+       if (strlen(name) > LUSTRE_NODEMAP_NAME_LENGTH ||
+           strlen(name) == 0)
+               return false;
+
        for (; *name != '\0'; name++) {
                if (!isalnum(*name) && *name != '_')
                        return false;
        for (; *name != '\0'; name++) {
                if (!isalnum(*name) && *name != '_')
                        return false;
@@ -217,7 +231,7 @@ static bool nodemap_name_is_valid(const char *name)
  * Look nodemap up in the nodemap hash
  *
  * \param      name            name of nodemap
  * Look nodemap up in the nodemap hash
  *
  * \param      name            name of nodemap
- * \paramA     nodemap         found nodemap or NULL
+ * \param      nodemap         found nodemap or NULL
  * \retval     lu_nodemap      named nodemap
  * \retval     NULL            nodemap doesn't exist
  */
  * \retval     lu_nodemap      named nodemap
  * \retval     NULL            nodemap doesn't exist
  */
@@ -225,14 +239,150 @@ static int nodemap_lookup(const char *name, struct lu_nodemap **nodemap)
 {
        int rc = 0;
 
 {
        int rc = 0;
 
+       *nodemap = NULL;
+
        if (!nodemap_name_is_valid(name))
                GOTO(out, rc = -EINVAL);
 
        *nodemap = cfs_hash_lookup(nodemap_hash, name);
        if (!nodemap_name_is_valid(name))
                GOTO(out, rc = -EINVAL);
 
        *nodemap = cfs_hash_lookup(nodemap_hash, name);
+       if (*nodemap == NULL)
+               rc = -ENOENT;
+
+out:
+       return rc;
+}
+
+/**
+ * classify the nid into the proper nodemap
+ *
+ * \param      nid                     nid to classify
+ * \retval     nodemap                 nodemap containing the nid
+ * \retval     default_nodemap         default nodemap
+ */
+struct lu_nodemap *nodemap_classify_nid(lnet_nid_t nid)
+{
+       struct lu_nid_range     *range;
+
+       range = range_search(nid);
+       if (range != NULL)
+               return range->rn_nodemap;
 
 
+       return default_nodemap;
+}
+EXPORT_SYMBOL(nodemap_classify_nid);
+
+/*
+ * simple check for default nodemap
+ */
+static bool is_default_nodemap(const struct lu_nodemap *nodemap)
+{
+       return nodemap->nm_id == 0;
+}
+
+/*
+ * parse a nodemap range string into two nids
+ *
+ * \param      range_str               string to parse
+ * \param      range[2]                array of two nids
+ * \reyval     0 on success
+ */
+int nodemap_parse_range(const char *range_str, lnet_nid_t range[2])
+{
+       char    buf[LNET_NIDSTR_SIZE * 2 + 2];
+       char    *ptr = NULL;
+       char    *start_nidstr;
+       char    *end_nidstr;
+       int     rc = 0;
+
+       snprintf(buf, sizeof(buf), "%s", range_str);
+       ptr = buf;
+       start_nidstr = strsep(&ptr, ":");
+       end_nidstr = strsep(&ptr, ":");
+
+       if (start_nidstr == NULL || end_nidstr == NULL)
+               GOTO(out, rc = -EINVAL);
+
+       range[0] = libcfs_str2nid(start_nidstr);
+       range[1] = libcfs_str2nid(end_nidstr);
+
+out:
+       return rc;
+
+}
+EXPORT_SYMBOL(nodemap_parse_range);
+
+/*
+ * add nid range to nodemap
+ * \param      name            nodemap name
+ * \param      range_st        string containing nid range
+ * \retval     0 on success
+ *
+ * add an range to the global range tree and attached the
+ * range to the named nodemap.
+ */
+int nodemap_add_range(const char *name, const lnet_nid_t nid[2])
+{
+       struct lu_nodemap       *nodemap = NULL;
+       struct lu_nid_range     *range;
+       int rc;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL || is_default_nodemap(nodemap))
+               GOTO(out, rc = -EINVAL);
+
+       range = range_create(nid[0], nid[1], nodemap);
+       if (range == NULL)
+               GOTO(out_putref, rc = -ENOMEM);
+
+       rc = range_insert(range);
+       if (rc != 0) {
+               CERROR("cannot insert nodemap range into '%s': rc = %d\n",
+                     nodemap->nm_name, rc);
+               list_del(&range->rn_list);
+               range_destroy(range);
+               GOTO(out_putref, rc = -ENOMEM);
+       }
+
+       list_add(&range->rn_list, &nodemap->nm_ranges);
+
+out_putref:
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_add_range);
+
+/**
+ * delete a range
+ * \param      name            nodemap name
+ * \param      range_str       string containing range
+ * \retval     0 on success
+ *
+ * Delete range from global range tree, and remove it
+ * from the list in the associated nodemap.
+ */
+int nodemap_del_range(const char *name, const lnet_nid_t nid[2])
+{
+       struct lu_nodemap       *nodemap;
+       struct lu_nid_range     *range;
+       int                     rc = 0;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL || is_default_nodemap(nodemap))
+               GOTO(out, rc = -EINVAL);
+
+       range = range_find(nid[0], nid[1]);
+       if (range == NULL)
+               GOTO(out_putref, rc = -EINVAL);
+
+       range_delete(range);
+
+out_putref:
+       nodemap_putref(nodemap);
 out:
        return rc;
 }
 out:
        return rc;
 }
+EXPORT_SYMBOL(nodemap_del_range);
 
 /**
  * Nodemap constructor
 
 /**
  * Nodemap constructor
@@ -256,14 +406,13 @@ static int nodemap_create(const char *name, bool is_default)
        int     rc = 0;
 
        rc = nodemap_lookup(name, &nodemap);
        int     rc = 0;
 
        rc = nodemap_lookup(name, &nodemap);
-       if (rc < 0)
+       if (rc == -EINVAL)
                goto out;
 
                goto out;
 
-       if (nodemap != NULL) {
+       if (rc != -ENOENT) {
                nodemap_putref(nodemap);
                GOTO(out, rc = -EEXIST);
        }
                nodemap_putref(nodemap);
                GOTO(out, rc = -EEXIST);
        }
-
        OBD_ALLOC_PTR(nodemap);
 
        if (nodemap == NULL) {
        OBD_ALLOC_PTR(nodemap);
 
        if (nodemap == NULL) {
@@ -321,6 +470,111 @@ out:
        return rc;
 }
 
        return rc;
 }
 
+/*
+ * update flag to turn on or off nodemap functions
+ * \param      name            nodemap name
+ * \param      admin_string    string containing updated value
+ * \retval     0 on success
+ *
+ * Update admin flag to turn on or off nodemap functions.
+ */
+int nodemap_set_allow_root(const char *name, bool allow_root)
+{
+       struct lu_nodemap       *nodemap = NULL;
+       int                     rc = 0;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL)
+               GOTO(out, rc = -ENOENT);
+
+       nodemap->nmf_allow_root_access = allow_root;
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_set_allow_root);
+
+/**
+ * updated trust_client_ids flag for nodemap
+ *
+ * \param      name            nodemap name
+ * \param      trust_string    new value for trust flag
+ * \retval     0 on success
+ *
+ * Update the trust_client_ids flag for a nodemap.
+ */
+int nodemap_set_trust_client_ids(const char *name, bool trust_client_ids)
+{
+       struct lu_nodemap       *nodemap = NULL;
+       int                     rc = 0;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL)
+               GOTO(out, rc = -ENOENT);
+
+       nodemap->nmf_trust_client_ids = trust_client_ids;
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_set_trust_client_ids);
+
+/**
+ * update the squash_uid for a nodemap
+ *
+ * \param      name            nodemap name
+ * \param      uid_string      string containing new squash_uid value
+ * \retval     0 on success
+ *
+ * Update the squash_uid for a nodemap. The squash_uid is the uid
+ * that the all client uids are mapped to if nodemap is active,
+ * the trust_client_ids flag is not set, and the uid is not in
+ * the idmap tree.
+ */
+int nodemap_set_squash_uid(const char *name, uid_t uid)
+{
+       struct lu_nodemap       *nodemap = NULL;
+       int                     rc = 0;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL)
+               GOTO(out, rc = -ENOENT);
+
+       nodemap->nm_squash_uid = uid;
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_set_squash_uid);
+
+/**
+ * update the squash_gid for a nodemap
+ *
+ * \param      name            nodemap name
+ * \param      gid_string      string containing new squash_gid value
+ * \retval     0 on success
+ *
+ * Update the squash_gid for a nodemap. The squash_uid is the gid
+ * that the all client gids are mapped to if nodemap is active,
+ * the trust_client_ids flag is not set, and the gid is not in
+ * the idmap tree.
+ */
+int nodemap_set_squash_gid(const char *name, gid_t gid)
+{
+       struct lu_nodemap       *nodemap = NULL;
+       int                     rc = 0;
+
+       rc = nodemap_lookup(name, &nodemap);
+       if (nodemap == NULL)
+               GOTO(out, rc = -ENOENT);
+
+       nodemap->nm_squash_gid = gid;
+       nodemap_putref(nodemap);
+out:
+       return rc;
+}
+EXPORT_SYMBOL(nodemap_set_squash_gid);
+
 /**
  * Add a nodemap
  *
 /**
  * Add a nodemap
  *
index 77dbb27..7e55136 100644 (file)
@@ -28,6 +28,7 @@
 #define _NODEMAP_INTERNAL_H
 
 #include <lustre_nodemap.h>
 #define _NODEMAP_INTERNAL_H
 
 #include <lustre_nodemap.h>
+#include <interval_tree.h>
 
 #define MODULE_STRING "nodemap"
 
 
 #define MODULE_STRING "nodemap"
 
@@ -43,8 +44,29 @@ extern struct proc_dir_entry *proc_lustre_nodemap_root;
 /* flag if nodemap is active */
 extern bool nodemap_idmap_active;
 
 /* flag if nodemap is active */
 extern bool nodemap_idmap_active;
 
+struct lu_nid_range {
+       /* unique id set my mgs */
+       unsigned int             rn_id;
+       /* lu_nodemap containing this range */
+       struct lu_nodemap       *rn_nodemap;
+       /* list for nodemap */
+       struct list_head         rn_list;
+       /* nid interval tree */
+       struct interval_node     rn_node;
+};
+
 int nodemap_procfs_init(void);
 int lprocfs_nodemap_register(const char *name, bool is_default_nodemap,
                             struct lu_nodemap *nodemap);
 int nodemap_procfs_init(void);
 int lprocfs_nodemap_register(const char *name, bool is_default_nodemap,
                             struct lu_nodemap *nodemap);
+struct lu_nid_range *range_create(lnet_nid_t min, lnet_nid_t max,
+                                 struct lu_nodemap *nodemap);
+void range_destroy(struct lu_nid_range *range);
+int range_insert(struct lu_nid_range *data);
+void range_delete(struct lu_nid_range *data);
+struct lu_nid_range *range_search(lnet_nid_t nid);
+struct lu_nid_range *range_find(lnet_nid_t start_nid, lnet_nid_t end_nid);
+int range_parse_nidstring(char *range_string, lnet_nid_t *start_nid,
+                         lnet_nid_t *end_nid);
+void range_init_tree(void);
 int nodemap_cleanup_nodemaps(void);
 #endif  /* _NODEMAP_INTERNAL_H */
 int nodemap_cleanup_nodemaps(void);
 #endif  /* _NODEMAP_INTERNAL_H */
index f44fe83..397b0d9 100644 (file)
 #define NODEMAP_LPROC_ID_LEN 16
 #define NODEMAP_LPROC_FLAG_LEN 2
 
 #define NODEMAP_LPROC_ID_LEN 16
 #define NODEMAP_LPROC_FLAG_LEN 2
 
-#define NODEMAP_PROC_DEBUG 1
-
 #include <lprocfs_status.h>
 #include <lustre_net.h>
 #include <lprocfs_status.h>
 #include <lustre_net.h>
+#include <interval_tree.h>
 #include "nodemap_internal.h"
 
 #include "nodemap_internal.h"
 
+static int nodemap_ranges_show(struct seq_file *m, void *data)
+{
+       struct lu_nodemap               *nodemap = m->private;
+       struct lu_nid_range             *range;
+       struct interval_node_extent     ext;
+
+
+       list_for_each_entry(range, &nodemap->nm_ranges, rn_list) {
+                       ext = range->rn_node.in_extent;
+                       seq_printf(m, "id: %u: { start_nid: %s, "
+                                       "end_nid: %s }\n",
+                                  range->rn_id, libcfs_nid2str(ext.start),
+                                  libcfs_nid2str(ext.end));
+       }
+
+       return 0;
+}
+
+static int nodemap_ranges_open(struct inode *inode, struct file *file)
+{
+       struct proc_dir_entry   *dir;
+       struct lu_nodemap       *nodemap;
+
+       dir = PDE(inode);
+       nodemap = dir->data;
+
+       return single_open(file, nodemap_ranges_show, nodemap);
+}
+
 static int nodemap_active_seq_show(struct seq_file *m, void *data)
 {
        return seq_printf(m, "%u\n", (unsigned int)nodemap_idmap_active);
 static int nodemap_active_seq_show(struct seq_file *m, void *data)
 {
        return seq_printf(m, "%u\n", (unsigned int)nodemap_idmap_active);
@@ -313,6 +341,13 @@ LPROC_SEQ_FOPS_RO(nodemap_squash_uid);
 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
 #endif
 
 LPROC_SEQ_FOPS_RO(nodemap_squash_gid);
 #endif
 
+const struct file_operations nodemap_ranges_fops = {
+       .open                   = nodemap_ranges_open,
+       .read                   = seq_read,
+       .llseek                 = seq_lseek,
+       .release                = single_release
+};
+
 static struct lprocfs_seq_vars lprocfs_nodemap_vars[] = {
        {
                .name           = "id",
 static struct lprocfs_seq_vars lprocfs_nodemap_vars[] = {
        {
                .name           = "id",
@@ -335,6 +370,10 @@ static struct lprocfs_seq_vars lprocfs_nodemap_vars[] = {
                .fops           = &nodemap_squash_gid_fops,
        },
        {
                .fops           = &nodemap_squash_gid_fops,
        },
        {
+               .name           = "ranges",
+               .fops           = &nodemap_ranges_fops,
+       },
+       {
                NULL
        }
 };
                NULL
        }
 };
diff --git a/lustre/nodemap/nodemap_range.c b/lustre/nodemap/nodemap_range.c
new file mode 100644 (file)
index 0000000..1f9881d
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * 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.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (C) 2013, Trustees of Indiana University
+ * Author: Joshua Walgenbach <jjw@iu.edu>
+ */
+
+#include <interval_tree.h>
+#include <lustre_net.h>
+#include "nodemap_internal.h"
+
+/*
+ * Range trees
+ *
+ * To classify clients when they connect, build a global range tree
+ * containing all admin defined ranges. Incoming clients can then be
+ * classified into their nodemaps, and the lu_nodemap structure will be
+ * set in the export structure for the connecting client. Pointers to
+ * the lu_nid_range nodes will be added to linked links within the
+ * lu_nodemap structure for reporting purposes.A
+ */
+
+static struct interval_node *range_interval_root;
+static atomic_t range_highest_id;
+
+void range_init_tree(void)
+{
+       range_interval_root = NULL;
+}
+
+/*
+ * callback for interating over the interval tree
+ *
+ * \param      n               interval_node matched
+ * \param      data            void pointer for return
+ *
+ * This dunction stops after a single match. There should be
+ * no intervals containing multiple ranges
+ */
+static enum interval_iter range_cb(struct interval_node *n, void *data)
+{
+       struct lu_nid_range     *range = container_of(n, struct lu_nid_range,
+                                                     rn_node);
+       struct lu_nid_range     **ret;
+
+       ret = data;
+       *ret = range;
+
+       return INTERVAL_ITER_STOP;
+}
+
+/*
+ * range constructor
+ *
+ * \param      min             starting nid of the range
+ * \param      max             ending nid of the range
+ * \param      nodemap         nodemap that contains this range
+ * \retval     lu_nid_range on success, NULL on failure
+ */
+struct lu_nid_range *range_create(lnet_nid_t start_nid, lnet_nid_t end_nid,
+                                 struct lu_nodemap *nodemap)
+{
+       struct lu_nid_range *range;
+
+       if (LNET_NIDNET(start_nid) != LNET_NIDNET(end_nid) ||
+           LNET_NIDADDR(start_nid) > LNET_NIDADDR(end_nid))
+               return NULL;
+
+       OBD_ALLOC_PTR(range);
+       if (range == NULL) {
+               CERROR("cannot allocate lu_nid_range of size %zu bytes\n",
+                      sizeof(*range));
+               return NULL;
+       }
+
+       range->rn_id = atomic_inc_return(&range_highest_id);
+       range->rn_nodemap = nodemap;
+       interval_set(&range->rn_node, start_nid, end_nid);
+       INIT_LIST_HEAD(&range->rn_list);
+
+       return range;
+}
+
+/*
+ * find the exact range
+ *
+ * \param      start_nid               starting nid
+ * \param      end_nid                 ending nid
+ * \retval     matching range or NULL
+ */
+struct lu_nid_range *range_find(lnet_nid_t start_nid, lnet_nid_t end_nid)
+{
+       struct lu_nid_range             *range = NULL;
+       struct interval_node            *interval = NULL;
+       struct interval_node_extent     ext = {
+               .start  = start_nid,
+               .end    = end_nid
+       };
+
+       interval = interval_find(range_interval_root, &ext);
+
+       if (interval != NULL)
+               range = container_of(interval, struct lu_nid_range,
+                                    rn_node);
+
+       return range;
+}
+
+/*
+ * range destructor
+ */
+void range_destroy(struct lu_nid_range *range)
+{
+       LASSERT(list_empty(&range->rn_list) == 0);
+       LASSERT(interval_is_intree(&range->rn_node) == 0);
+
+       OBD_FREE_PTR(range);
+}
+
+/*
+ * insert an nid range into the interval tree
+ *
+ * \param      range           range to insetr
+ * \retval     0 on success
+ *
+ * This function checks that the given nid range
+ * does not overlap so that each nid can belong
+ * to exactly one range
+ */
+int range_insert(struct lu_nid_range *range)
+{
+       struct interval_node_extent ext =
+                       range->rn_node.in_extent;
+
+       if (interval_is_overlapped(range_interval_root, &ext) != 0)
+               return -EEXIST;
+
+       interval_insert(&range->rn_node, &range_interval_root);
+
+       return 0;
+}
+
+/*
+ * delete a range from the interval tree and any
+ * associated nodemap references
+ *
+ * \param      range           range to remove
+ */
+void range_delete(struct lu_nid_range *range)
+{
+       if (range == NULL || interval_is_intree(&range->rn_node) == 0)
+               return;
+       list_del(&range->rn_list);
+       interval_erase(&range->rn_node, &range_interval_root);
+       range_destroy(range);
+}
+
+/*
+ * search the interval tree for an nid within a range
+ *
+ * \param      nid             nid to search for
+ */
+struct lu_nid_range *range_search(lnet_nid_t nid)
+{
+       struct lu_nid_range             *ret = NULL;
+       struct interval_node_extent     ext = {
+               .start  = nid,
+               .end    = nid
+       };
+
+       interval_search(range_interval_root, &ext, range_cb, &ret);
+
+       return ret;
+}
index 58eb783..4050bd3 100644 (file)
@@ -32,7 +32,8 @@ CONFDIR=/etc/lustre
 PERM_CONF=$CONFDIR/perm.conf
 FAIL_ON_ERROR=false
 
 PERM_CONF=$CONFDIR/perm.conf
 FAIL_ON_ERROR=false
 
-HN=$(hostname | sum | awk '{ print $1 }')
+HOSTNAME_CHECKSUM=$(hostname | sum | awk '{ print $1 }')
+SUBNET_CHECKSUM=$(expr $HOSTNAME_CHECKSUM % 250 + 1)
 NODEMAP_COUNT=10
 NODEMAP_RANGE_COUNT=3
 NODEMAP_IPADDR_COUNT=30
 NODEMAP_COUNT=10
 NODEMAP_RANGE_COUNT=3
 NODEMAP_IPADDR_COUNT=30
@@ -569,12 +570,14 @@ create_nodemaps() {
        local rc
 
        for (( i = 0; i < NODEMAP_COUNT; i++ )); do
        local rc
 
        for (( i = 0; i < NODEMAP_COUNT; i++ )); do
-               if ! do_facet mgs $LCTL nodemap_add ${HN}_${i}; then
+               if ! do_facet mgs $LCTL nodemap_add                     \
+                       ${HOSTNAME_CHECKSUM}_${i}; then
                        return 1
                fi
                        return 1
                fi
-               out=$(do_facet mgs $LCTL get_param nodemap.${HN}_${i}.id)
+               out=$(do_facet mgs $LCTL get_param                      \
+                       nodemap.${HOSTNAME_CHECKSUM}_${i}.id)
                ## This needs to return zero if the following statement is 1
                ## This needs to return zero if the following statement is 1
-               rc=$(echo $out | grep -c ${HN}_${i})
+               rc=$(echo $out | grep -c ${HOSTNAME_CHECKSUM}_${i})
                [[ $rc == 0 ]] && return 1
        done
        return 0
                [[ $rc == 0 ]] && return 1
        done
        return 0
@@ -586,20 +589,116 @@ delete_nodemaps() {
        local rc
 
        for ((i = 0; i < NODEMAP_COUNT; i++)); do
        local rc
 
        for ((i = 0; i < NODEMAP_COUNT; i++)); do
-               if ! do_facet mgs $LCTL nodemap_del ${HN}_${i}; then
-                       error "nodemap_del ${HN}_${i} failed with $rc"
+               if ! do_facet mgs $LCTL nodemap_del                     \
+                       ${HOSTNAME_CHECKSUM}_${i}; then
+                       error "nodemap_del ${HOSTNAME_CHECKSUM}_${i}    \
+                               failed with $rc"
                        return 3
                fi
                        return 3
                fi
-               out=$(do_facet mgs $LCTL get_param nodemap.${HN}_${i}.id)
-               rc=$(echo $out | grep -c ${HN}_${i})
+               out=$(do_facet mgs $LCTL get_param                      \
+                       nodemap.${HOSTNAME_CHECKSUM}_${i}.id)
+               rc=$(echo $out | grep -c ${HOSTNAME_CHECKSUM}_${i})
                [[ $rc != 0 ]] && return 1
        done
        return 0
 }
 
                [[ $rc != 0 ]] && return 1
        done
        return 0
 }
 
+add_range() {
+       local i
+       local j
+       local cmd="$LCTL nodemap_add_range"
+       local range
+       local rc=0
+
+       for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
+               range="$SUBNET_CHECKSUM.${2}.${j}.[1-253]@tcp"
+               if ! do_facet mgs $cmd --name $1        \
+                       --range $range; then
+                       rc=$(($rc + 1))
+               fi
+       done
+       return $rc
+}
+
+del_range() {
+       local i
+       local j
+       local cmd="$LCTL nodemap_del_range"
+       local range
+       local rc=0
+
+       for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
+               range="$SUBNET_CHECKSUM.${2}.${j}.[1-253]@tcp"
+               if ! do_facet mgs $cmd --name $1        \
+                       --range $range; then
+                       rc=$(($rc + 1))
+               fi
+       done
+       return $rc
+}
+
+modify_flags() {
+       local i
+       local proc
+       local option
+       local cmd="$LCTL nodemap_modify"
+       local rc=0
+
+       proc[0]="admin_nodemap"
+       proc[1]="trusted_nodemap"
+       option[0]="admin"
+       option[1]="trusted"
+
+       for ((idx = 0; idx < 2; idx++)); do
+               if ! do_facet mgs $cmd --name $1        \
+                       --property ${option[$idx]}      \
+                       --value 1; then
+                       rc=$((rc + 1))
+               fi
+
+               if ! do_facet mgs $cmd --name $1        \
+                       --property ${option[$idx]}      \
+                       --value 0; then
+                       rc=$((rc + 1))
+               fi
+       done
+
+       return $rc
+}
+
+squash_id() {
+       local cmd
+
+       cmd[0]="$LCTL nodemap_modify --property squash_uid"
+       cmd[1]="$LCTL nodemap_modify --property squash_gid"
+
+       if ! do_facet mgs ${cmd[$3]} --name $1 --value $2; then
+               return 1
+       fi
+}
+
+test_nid() {
+       local cmd
+
+       cmd="$LCTL nodemap_test_nid"
+
+       nid=$(do_facet mgs $cmd $1)
+
+       if [ $nid == $2 ]; then
+               return 0
+       fi
+
+       return 1
+}
+
 test_7() {
        local rc
 
 test_7() {
        local rc
 
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
        create_nodemaps
        rc=$?
        [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
        create_nodemaps
        rc=$?
        [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
@@ -615,6 +714,11 @@ run_test 7 "nodemap create and delete"
 test_8() {
        local rc
 
 test_8() {
        local rc
 
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
        # Set up nodemaps
 
        create_nodemaps
        # Set up nodemaps
 
        create_nodemaps
@@ -637,6 +741,239 @@ test_8() {
 }
 run_test 8 "nodemap reject duplicates"
 
 }
 run_test 8 "nodemap reject duplicates"
 
+test_9() {
+       local i
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! del_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_del_range failed with $rc" && return 4
+
+       rc=0
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 4
+
+       return 0
+}
+run_test 9 "nodemap range add"
+
+test_10() {
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc == 0 ]] && error "nodemap_add_range duplicate add with $rc" &&
+               return 2
+
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! del_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_del_range failed with $rc" && return 4
+
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 5
+
+       return 0
+}
+run_test 10 "nodemap reject duplicate ranges"
+
+test_11() {
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! modify_flags ${HOSTNAME_CHECKSUM}_${i}; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_modify with $rc" && return 2
+
+       rc=0
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 3
+
+       return 0
+}
+run_test 11 "nodemap modify"
+
+test_12() {
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! squash_id ${HOSTNAME_CHECKSUM}_${i} 88 0; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap squash_uid with $rc" && return 2
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! squash_id ${HOSTNAME_CHECKSUM}_${i} 88 1; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap squash_gid with $rc" && return 3
+
+       rc=0
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
+
+       return 0
+}
+run_test 12 "nodemap set squash ids"
+
+test_13() {
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               if ! add_range ${HOSTNAME_CHECKSUM}_${i} $i; then
+                       rc=$((rc + 1))
+               fi
+       done
+       [[ $rc != 0 ]] && error "nodemap_add_range failed with $rc" && return 2
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
+                       for ((k = 1; k < 253; k++)); do
+                               if ! test_nid $SUBNET_CHECKSUM.$i.$j.$k \
+                                      ${HOSTNAME_CHECKSUM}_${i}; then
+                                       rc=$((rc + 1))
+                               fi
+                       done
+               done
+       done
+       [[ $rc != 0 ]] && error "nodemap_test_nid failed with $rc" && return 3
+
+       rc=0
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
+
+       return 0
+}
+run_test 13 "test nids"
+
+test_14() {
+       local rc
+
+       remote_mgs_nodsh && skip "remote MGS with nodsh" && return
+       [ $(lustre_version_code $SINGLEMGS) -lt $(version_code 2.5.53) ] &&
+               skip "No nodemap on $(get_lustre_version) MGS, need 2.5.53+" &&
+               return
+
+       rc=0
+       create_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_add failed with $rc" && return 1
+
+       rc=0
+       for ((i = 0; i < NODEMAP_COUNT; i++)); do
+               for ((j = 0; j < NODEMAP_RANGE_COUNT; j++)); do
+                       for ((k = 1; k < 253; k++)); do
+                               if ! test_nid $SUBNET_CHECKSUM.$i.$j.$k \
+                                       default; then
+                                       rc=$((rc + 1))
+                               fi
+                       done
+               done
+       done
+       [[ $rc != 0 ]] && error "nodemap_test_nid failed with $rc" && return 3
+
+       rc=0
+       delete_nodemaps
+       rc=$?
+       [[ $rc != 0 ]] && error "nodemap_del failed with $rc" && return 4
+
+       return 0
+}
+run_test 14 "test default nodemap nid lookup"
+
+
 log "cleanup: ======================================================"
 
 sec_unsetup() {
 log "cleanup: ======================================================"
 
 sec_unsetup() {
index 9ee230c..a85a13f 100644 (file)
@@ -239,6 +239,17 @@ command_t cmdlist[] = {
        {"nodemap_del", jt_nodemap_del, 0,
         "remove a nodemap\n"
         "usage: nodemap_del <nodemap_name>"},
        {"nodemap_del", jt_nodemap_del, 0,
         "remove a nodemap\n"
         "usage: nodemap_del <nodemap_name>"},
+       {"nodemap_add_range", jt_nodemap_add_range, 0,
+        "add a range to a nodemap\n"
+        "usage: nodemap_add_range <NID range>"},
+       {"nodemap_del_range", jt_nodemap_del_range, 0,
+        "add a range to a nodemap\n"
+        "usage: nodemap_del_range <NID range>"},
+       {"nodemap_modify", jt_nodemap_modify, 0,
+        "modify a nodemap parameters"
+        "usage: nodemap_modify nodemap_name param value"},
+       {"nodemap_test_nid", jt_nodemap_test_nid, 0,
+        "usage: nodemap_test_nid <nid>"},
 
         /* Changelog commands */
         {"===  Changelogs ==", jt_noop, 0, "changelog user management"},
 
         /* Changelog commands */
         {"===  Changelogs ==", jt_noop, 0, "changelog user management"},
index ced869b..9964131 100644 (file)
@@ -81,6 +81,7 @@
 
 #define MAX_THREADS 4096
 #define MAX_BASE_ID 0xffffffff
 
 #define MAX_THREADS 4096
 #define MAX_BASE_ID 0xffffffff
+#define NIDSTRING_LENGTH 64
 struct shared_data {
         l_mutex_t mutex;
         l_cond_t  cond;
 struct shared_data {
         l_mutex_t mutex;
         l_cond_t  cond;
@@ -3408,29 +3409,41 @@ out:
         return rc;
 }
 
         return rc;
 }
 
-static int nodemap_cmd(enum lcfg_command_type cmd, int num_args, ...)
+/**
+ * Format and send the ioctl to the MGS.
+ *
+ * \param      cmd             IOCTL to send
+ * \param      ret_data        void pointer to return anything from
+ *                             ioctl
+ * \param      num_args        number of arguments to pack into the
+ *                             ioctl buffer
+ * \param      argv[]          variable number of string arguments
+ *
+ * \retval                     0 on success
+ */
+static int nodemap_cmd(enum lcfg_command_type cmd, void *ret_data,
+                      unsigned int ret_size, ...)
 {
 {
-       va_list arguments;
-       int i;
-       const char *args;
-       char *arg;
-       struct lustre_cfg_bufs bufs;
-       struct obd_ioctl_data data;
-       struct lustre_cfg *lcfg;
-       char rawbuf[MAX_IOC_BUFLEN], *buf = rawbuf;
-       int rc = 0;
+       va_list                 ap;
+       char                    *arg;
+       int                     i = 0;
+       struct lustre_cfg_bufs  bufs;
+       struct obd_ioctl_data   data;
+       struct lustre_cfg       *lcfg;
+       char                    rawbuf[MAX_IOC_BUFLEN];
+       char                    *buf = rawbuf;
+       int                     rc = 0;
 
        lustre_cfg_bufs_reset(&bufs, NULL);
 
 
        lustre_cfg_bufs_reset(&bufs, NULL);
 
-       va_start(arguments, num_args);
-
-       for (i = 0; i < num_args; i++) {
-               args = va_arg(arguments, char *);
-               arg = (char *)args;
+       va_start(ap, ret_size);
+       arg = va_arg(ap, char *);
+       while (arg != NULL) {
                lustre_cfg_bufs_set_string(&bufs, i, arg);
                lustre_cfg_bufs_set_string(&bufs, i, arg);
+               i++;
+               arg = va_arg(ap, char *);
        }
        }
-
-       va_end(arguments);
+       va_end(ap);
 
        lcfg = lustre_cfg_new(cmd, &bufs);
 
 
        lcfg = lustre_cfg_new(cmd, &bufs);
 
@@ -3451,26 +3464,49 @@ static int nodemap_cmd(enum lcfg_command_type cmd, int num_args, ...)
 
        memset(buf, 0, sizeof(rawbuf));
        rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
 
        memset(buf, 0, sizeof(rawbuf));
        rc = obd_ioctl_pack(&data, &buf, sizeof(rawbuf));
-       if (rc) {
-               fprintf(stderr, "error: invalid ioctl\n");
-               return rc;
+       if (rc != 0) {
+               fprintf(stderr, "error: invalid ioctl: %08x errno: %d with "
+                              "rc=%d\n", cmd, errno, rc);
+               goto out;
        }
        }
+
        rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NODEMAP, buf);
        rc = l_ioctl(OBD_DEV_ID, OBD_IOC_NODEMAP, buf);
-out:
-       if (rc)
-               rc = -errno;
+       if (rc != 0) {
+               fprintf(stderr, "error: invalid ioctl: %08x errno: %d with "
+                              "rc=%d\n", cmd, errno, rc);
+               goto out;
+       }
 
 
+       if (ret_data != NULL) {
+               rc = obd_ioctl_unpack(&data, buf, sizeof(rawbuf));
+               if (rc != 0)
+                       goto out;
+
+               memcpy(ret_data, data.ioc_pbuf1, data.ioc_plen1);
+               if (ret_data == NULL || sizeof(ret_data) != ret_size)
+                       rc = -errno;
+       }
+out:
        lustre_cfg_free(lcfg);
        lustre_cfg_free(lcfg);
+
        return rc;
 }
 
        return rc;
 }
 
+/**
+ * activate nodemap functions
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * argv[0]                     1 for activate or 0 for deactivate
+ *
+ * \retval                     0 on success
+ */
 int jt_nodemap_activate(int argc, char **argv)
 {
 int jt_nodemap_activate(int argc, char **argv)
 {
-       enum lcfg_command_type cmd;
-       int rc = 0;
+       int rc;
 
 
-       cmd = LCFG_NODEMAP_ACTIVATE;
-       rc = nodemap_cmd(cmd, 1, argv[0]);
+       rc = nodemap_cmd(LCFG_NODEMAP_ACTIVATE, NULL, 0, argv[0], NULL);
 
        if (rc != 0) {
                errno = -rc;
 
        if (rc != 0) {
                errno = -rc;
@@ -3480,19 +3516,27 @@ int jt_nodemap_activate(int argc, char **argv)
        return rc;
 }
 
        return rc;
 }
 
+/**
+ * add a nodemap
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * argv[0]                     nodemap name
+ *
+ * \retval                     0 on success
+ */
 int jt_nodemap_add(int argc, char **argv)
 {
 int jt_nodemap_add(int argc, char **argv)
 {
-       enum lcfg_command_type cmd;
-       int rc = 0;
+       int rc;
 
 
-       cmd = LCFG_NODEMAP_ADD;
        rc = llapi_nodemap_exists(argv[1]);
        if (rc == 0) {
                fprintf(stderr, "error: %s existing nodemap name\n", argv[1]);
                return 1;
        }
 
        rc = llapi_nodemap_exists(argv[1]);
        if (rc == 0) {
                fprintf(stderr, "error: %s existing nodemap name\n", argv[1]);
                return 1;
        }
 
-       rc = nodemap_cmd(cmd, 2, argv[0], argv[1]);
+       rc = nodemap_cmd(LCFG_NODEMAP_ADD, NULL, 0, argv[0], argv[1], NULL);
 
        if (rc != 0) {
                errno = -rc;
 
        if (rc != 0) {
                errno = -rc;
@@ -3502,20 +3546,27 @@ int jt_nodemap_add(int argc, char **argv)
        return rc;
 }
 
        return rc;
 }
 
+/**
+ * delete a nodemap
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * argv[0]                     nodemap name
+ *
+ * \retval                     0 on success
+ */
 int jt_nodemap_del(int argc, char **argv)
 {
 int jt_nodemap_del(int argc, char **argv)
 {
-       enum lcfg_command_type cmd;
-       int rc = 0;
+       int rc;
 
 
-       cmd = LCFG_NODEMAP_DEL;
        rc = llapi_nodemap_exists(argv[1]);
        rc = llapi_nodemap_exists(argv[1]);
-
        if (rc != 0) {
                fprintf(stderr, "error: %s not existing nodemap name\n",
                        argv[1]);
                return rc;
        }
        if (rc != 0) {
                fprintf(stderr, "error: %s not existing nodemap name\n",
                        argv[1]);
                return rc;
        }
-       rc = nodemap_cmd(cmd, 2, argv[0], argv[1]);
+       rc = nodemap_cmd(LCFG_NODEMAP_DEL, NULL, 0, argv[0], argv[1], NULL);
 
        if (rc != 0) {
                errno = -rc;
 
        if (rc != 0) {
                errno = -rc;
@@ -3525,6 +3576,300 @@ int jt_nodemap_del(int argc, char **argv)
        return rc;
 }
 
        return rc;
 }
 
+/**
+ * test a nid for nodemap membership
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * argv[0]                     properly formatted nid
+ *
+ * \retval                     0 on success
+ */
+int jt_nodemap_test_nid(int argc, char **argv)
+{
+
+       char    rawbuf[MAX_IOC_BUFLEN];
+       int     rc;
+
+       rc = nodemap_cmd(LCFG_NODEMAP_TEST_NID, &rawbuf, sizeof(rawbuf),
+                        argv[0], argv[1], NULL);
+       if (rc == 0)
+               printf("%s\n", (char *)rawbuf);
+
+       return rc;
+}
+
+/**
+ * add an nid range to a nodemap
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * --name                      nodemap name
+ * --range                     properly formatted nid range
+ *
+ * \retval                     0 on success
+ */
+int jt_nodemap_add_range(int argc, char **argv)
+{
+       char                    *nodemap_name = NULL;
+       char                    *nodemap_range = NULL;
+       struct list_head        nidlist;
+       char                    min_nid[LNET_NIDSTR_SIZE + 1];
+       char                    max_nid[LNET_NIDSTR_SIZE + 1];
+       char                    nid_range[2 * LNET_NIDSTR_SIZE + 2];
+       int                     rc = 0;
+       int                     c;
+
+       static struct option long_options[] = {
+               {
+                       .name           = "name",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'n',
+               },
+               {
+                       .name           = "range",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'r',
+               },
+               {
+                       NULL
+               }
+       };
+
+       INIT_LIST_HEAD(&nidlist);
+
+       while ((c = getopt_long(argc, argv, "n:r:",
+                               long_options, NULL)) != -1) {
+               switch (c) {
+               case 'n':
+                       nodemap_name = optarg;
+                       break;
+               case 'r':
+                       nodemap_range = optarg;
+                       break;
+               }
+       }
+
+       if (nodemap_name == NULL || nodemap_range == NULL) {
+               fprintf(stderr, "usage: nodemap_add_range --name <name> "
+                               "--range <range>\n");
+               return -1;
+       }
+
+       if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range),
+                             &nidlist) <= 0) {
+               fprintf(stderr, "error: %s: can't parse nid range: %s\n",
+                       jt_cmdname(argv[0]), nodemap_range);
+               return -1;
+       }
+
+       if (!cfs_nidrange_is_contiguous(&nidlist)) {
+               fprintf(stderr, "error: %s: nodemap ranges must be "
+                       "contiguous\n", jt_cmdname(argv[0]));
+               return -1;
+       }
+
+       cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0],
+                                 LNET_NIDSTR_SIZE);
+       snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid);
+
+       rc = nodemap_cmd(LCFG_NODEMAP_ADD_RANGE, NULL, 0, argv[0],
+                        nodemap_name, nid_range, NULL);
+       if (rc != 0) {
+               errno = -rc;
+               fprintf(stderr, "error: %s: cannot add range '%s' to nodemap "
+                               "'%s': rc = %d\n",
+                       jt_cmdname(argv[0]), nodemap_range, nodemap_name, rc);
+       }
+
+       return rc;
+}
+
+/**
+ * delete an nid range to a nodemap
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * --name                      nodemap name
+ * --range                     properly formatted nid range
+ *
+ * \retval                     0 on success
+ */
+int jt_nodemap_del_range(int argc, char **argv)
+{
+       char                    *nodemap_name = NULL;
+       char                    *nodemap_range = NULL;
+       struct list_head        nidlist;
+       char                    min_nid[LNET_NIDSTR_SIZE + 1];
+       char                    max_nid[LNET_NIDSTR_SIZE + 1];
+       char                    nid_range[2 * LNET_NIDSTR_SIZE + 2];
+       int                     rc = 0;
+       int                     c;
+
+       static struct option long_options[] = {
+               {
+                       .name           = "name",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'n',
+               },
+               {
+                       .name           = "range",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'r',
+               },
+               {
+                       NULL
+               }
+       };
+
+       INIT_LIST_HEAD(&nidlist);
+
+       while ((c = getopt_long(argc, argv, "n:r:",
+                               long_options, NULL)) != -1) {
+               switch (c) {
+               case 'n':
+                       nodemap_name = optarg;
+                       break;
+               case 'r':
+                       nodemap_range = optarg;
+                       break;
+               }
+       }
+
+       if (nodemap_name == NULL || nodemap_range == NULL) {
+               fprintf(stderr, "usage: nodemap_del_range --name <name> "
+                               "--range <range>\n");
+               return -1;
+       }
+
+       if (cfs_parse_nidlist(nodemap_range, strlen(nodemap_range),
+                             &nidlist) <= 0) {
+               fprintf(stderr, "error: %s: can't parse nid range: %s\n",
+                       jt_cmdname(argv[0]), nodemap_range);
+               return -1;
+       }
+
+       if (!cfs_nidrange_is_contiguous(&nidlist)) {
+               fprintf(stderr, "error: %s: nodemap ranges must be "
+                       "contiguous\n", jt_cmdname(argv[0]));
+               return -1;
+       }
+
+       cfs_nidrange_find_min_max(&nidlist, &min_nid[0], &max_nid[0],
+                                 LNET_NIDSTR_SIZE);
+       snprintf(nid_range, sizeof(nid_range), "%s:%s", min_nid, max_nid);
+
+       rc = nodemap_cmd(LCFG_NODEMAP_DEL_RANGE, NULL, 0, argv[0],
+                        nodemap_name, nid_range, NULL);
+       if (rc != 0) {
+               errno = -rc;
+               fprintf(stderr, "error: %s: cannot delete range '%s' to "
+                              "nodemap '%s': rc = %d\n",
+                       jt_cmdname(argv[0]), nodemap_range, nodemap_name, rc);
+       }
+
+       return rc;
+}
+
+/**
+ * modify a nodemap's behavior
+ *
+ * \param      argc            number of args
+ * \param      argv[]          variable string arguments
+ *
+ * --name                      nodemap name
+ * --property                  nodemap property to change
+ *                             admin, trusted, squash_uid, squash_gid)
+ * --value                     value to set property
+ *
+ * \retval                     0 on success
+ */
+int jt_nodemap_modify(int argc, char **argv)
+{
+       int c;
+       int rc = 0;
+       enum lcfg_command_type cmd = 0;
+       char *nodemap_name = NULL, *param = NULL, *value = NULL;
+
+       static struct option long_options[] = {
+               {
+                       .name           = "name",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'n',
+               },
+               {
+                       .name           = "property",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'p',
+               },
+               {
+                       .name           = "value",
+                       .has_arg        = required_argument,
+                       .flag           = 0,
+                       .val            = 'v',
+               },
+               {
+                       NULL
+               }
+       };
+
+       while ((c = getopt_long(argc, argv, "n:p:v:",
+                               long_options, NULL)) != -1) {
+               switch (c) {
+               case 'n':
+                       nodemap_name = optarg;
+                       break;
+               case 'p':
+                       param = optarg;
+                       break;
+               case 'v':
+                       value = optarg;
+                       break;
+               }
+       }
+
+       if (nodemap_name == NULL || param == NULL || value == NULL) {
+               fprintf(stderr, "usage: nodemap_modify --name <name> "
+                               "--property <range> --value <value>\n");
+               return -1;
+       }
+
+       if (strcmp("admin", param) == 0) {
+               cmd = LCFG_NODEMAP_ADMIN;
+       } else if (strcmp("trusted", param) == 0) {
+               cmd = LCFG_NODEMAP_TRUSTED;
+       } else if (strcmp("squash_uid", param) == 0) {
+               cmd = LCFG_NODEMAP_SQUASH_UID;
+       } else if (strcmp("squash_gid", param) == 0) {
+               cmd = LCFG_NODEMAP_SQUASH_GID;
+       } else {
+               fprintf(stderr, "error: %s: nodemap_modify invalid "
+                               "subcommand: %s\n",
+                       jt_cmdname(argv[0]), param);
+               return -1;
+       }
+
+       rc = nodemap_cmd(cmd, NULL, 0, argv[0], nodemap_name, param,
+                        value, NULL);
+       if (rc != 0) {
+               errno = -rc;
+               fprintf(stderr, "error: %s: cannot modify nodemap '%s' "
+                              "to param '%s': value '%s': rc = %d\n",
+                       jt_cmdname(argv[0]), nodemap_name, param, value, rc);
+       }
+
+       return rc;
+}
+
 /*
  * this function tranforms a rule [start-end/step] into an array
  * of matching numbers
 /*
  * this function tranforms a rule [start-end/step] into an array
  * of matching numbers
index c30db68..49d5d40 100644 (file)
@@ -136,6 +136,10 @@ int jt_pool_cmd(int argc, char **argv);
 int jt_nodemap_activate(int argc, char **argv);
 int jt_nodemap_add(int argc, char **argv);
 int jt_nodemap_del(int argc, char **argv);
 int jt_nodemap_activate(int argc, char **argv);
 int jt_nodemap_add(int argc, char **argv);
 int jt_nodemap_del(int argc, char **argv);
+int jt_nodemap_modify(int argc, char **argv);
+int jt_nodemap_add_range(int argc, char **argv);
+int jt_nodemap_test_nid(int argc, char **argv);
+int jt_nodemap_del_range(int argc, char **argv);
 int jt_changelog_register(int argc, char **argv);
 int jt_changelog_deregister(int argc, char **argv);
 
 int jt_changelog_register(int argc, char **argv);
 int jt_changelog_deregister(int argc, char **argv);