Whamcloud - gitweb
LU-17922 utils: added idmap range functionality 02/55502/11
authorMaximilian Dilger <mdilger@whamcloud.com>
Thu, 20 Jun 2024 20:09:15 +0000 (16:09 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 23 Jul 2024 04:41:51 +0000 (04:41 +0000)
Added the ability to a declare a range when adding idmaps to a
nodemap. The syntax is:
 <clientid_start>-<clientid_end>:<fsid_start>[-<fsid_end>]

The uid_end value is optional. In practice this looks like:

nodemap_add_idmap --name test --idtype uid --idmap 500-510:10000

It is also now possible to delete idmap ranges with the
nodemap_del_idmap command as well with the same syntax.

Signed-off-by: Maximilian Dilger <mdilger@whamcloud.com>
Change-Id: If6a2b9ab11f7d435a6854055001e6102aac43115
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55502
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
lustre/include/lustre_nodemap.h
lustre/ptlrpc/nodemap_handler.c
lustre/tests/sanity-sec.sh

index 0df134b..10338fd 100644 (file)
@@ -132,7 +132,8 @@ int nodemap_add_member(struct lnet_nid *nid, struct obd_export *exp);
 void nodemap_del_member(struct obd_export *exp);
 int nodemap_parse_range(const char *range_string, struct lnet_nid range[2],
                        u8 *netmask);
-int nodemap_parse_idmap(char *idmap_string, __u32 idmap[2]);
+int nodemap_parse_idmap(const char *nodemap_name, char *idmap_str,
+                       __u32 idmap[2], u32 *range_count);
 int nodemap_add_range(const char *name, const struct lnet_nid nid[2],
                      u8 netmask);
 int nodemap_del_range(const char *name, const struct lnet_nid nid[2],
@@ -150,9 +151,9 @@ int nodemap_set_audit_mode(const char *name, bool enable_audit);
 int nodemap_set_forbid_encryption(const char *name, bool forbid_encryption);
 int nodemap_set_readonly_mount(const char *name, bool readonly_mount);
 bool nodemap_can_setquota(struct lu_nodemap *nodemap, __u32 qc_type, __u32 id);
-int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
+int nodemap_add_idmap(const char *nodemap_name, enum nodemap_id_type id_type,
                      const __u32 map[2]);
-int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
+int nodemap_del_idmap(const char *nodemap_name, enum nodemap_id_type id_type,
                      const __u32 map[2]);
 int nodemap_set_fileset(const char *name, const char *fileset);
 char *nodemap_get_fileset(const struct lu_nodemap *nodemap);
index feaf1aa..1d3b97c 100644 (file)
@@ -353,17 +353,25 @@ EXPORT_SYMBOL(nodemap_parse_range);
  * parse a string containing an id map of form "client_id:filesystem_id"
  * into an array of __u32 * for use in mapping functions
  *
+ * the string can also be a range of "ci_start-ci_end:fs_start[-fs_end]"
+ *
+ * \param      nodemap_name            nodemap name string
  * \param      idmap_str               map string
  * \param      idmap                   array[2] of __u32
+ * \param      range_count             potential idmap range u32
  *
  * \retval     0 on success
  * \retval     -EINVAL if idmap cannot be parsed
  */
-int nodemap_parse_idmap(char *idmap_str, __u32 idmap[2])
+int nodemap_parse_idmap(const char *nodemap_name, char *idmap_str,
+                       __u32 idmap[2], u32 *range_count)
 {
-       char                    *sep;
-       long unsigned int        idmap_buf;
-       int                      rc;
+       char *sep;
+       char *sep_range;
+       char *potential_range;
+       unsigned long id;
+       int rc;
+       int range = 1;
 
        if (idmap_str == NULL)
                return -EINVAL;
@@ -374,15 +382,52 @@ int nodemap_parse_idmap(char *idmap_str, __u32 idmap[2])
        *sep = '\0';
        sep++;
 
-       rc = kstrtoul(idmap_str, 10, &idmap_buf);
-       if (rc != 0)
+       /* see if range is passed in idmap_str */
+       sep_range = strchr(idmap_str, '-');
+       if (sep_range)
+               *sep_range++ = '\0';
+
+       rc = kstrtoul(idmap_str, 10, &id);
+       if (rc)
                return -EINVAL;
-       idmap[0] = idmap_buf;
+       idmap[0] = id;
 
-       rc = kstrtoul(sep, 10, &idmap_buf);
-       if (rc != 0)
+       /* parse cid range end if it is supplied */
+       if (sep_range) {
+               rc = kstrtoul(sep_range, 10, &id);
+               if (rc)
+                       return -EINVAL;
+
+               range = id - idmap[0] + 1;
+               if (range <= 0)
+                       return -ERANGE;
+       }
+
+       potential_range = strchr(sep, '-');
+       if (potential_range)
+               *potential_range++ = '\0';
+
+       rc = kstrtoul(sep, 10, &id);
+       if (rc)
                return -EINVAL;
-       idmap[1] = idmap_buf;
+       idmap[1] = id;
+
+       /* parse fsid range end if it is supplied */
+       if (potential_range) {
+               rc = kstrtoul(potential_range, 10, &id);
+               if (rc)
+                       return -ERANGE;
+
+               /* make sure fsid range is equal to cid range */
+               if (id - idmap[1] + 1 != range) {
+                       rc = -EINVAL;
+                       CERROR("%s: range length mismatch between client id %s-%s and fs id %s-%s: rc = %d\n",
+                              nodemap_name, idmap_str, sep_range, sep,
+                              potential_range, rc);
+                       return rc;
+               }
+       }
+       *range_count = range;
 
        return 0;
 }
@@ -522,7 +567,21 @@ out:
        return rc;
 }
 
-int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
+int nodemap_add_idmap_range(const char *nodemap_name, enum nodemap_id_type id_type,
+                           const __u32 map[2], const u32 range_count)
+{
+       int rc = 0;
+       int i;
+
+       for (i = 0; i < range_count && !rc; i++) {
+               rc = nodemap_add_idmap(nodemap_name, id_type,
+                                      (int[2]){map[0] + i, map[1] + i});
+       }
+
+       return rc;
+}
+
+int nodemap_add_idmap(const char *nodemap_name, enum nodemap_id_type id_type,
                      const __u32 map[2])
 {
        struct lu_nodemap       *nodemap = NULL;
@@ -531,7 +590,7 @@ int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
        ENTRY;
 
        mutex_lock(&active_config_lock);
-       nodemap = nodemap_lookup(name);
+       nodemap = nodemap_lookup(nodemap_name);
        if (IS_ERR(nodemap)) {
                mutex_unlock(&active_config_lock);
                GOTO(out, rc = PTR_ERR(nodemap));
@@ -563,7 +622,7 @@ EXPORT_SYMBOL(nodemap_add_idmap);
  *
  * \retval     0 on success
  */
-int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
+int nodemap_del_idmap(const char *nodemap_name, enum nodemap_id_type id_type,
                      const __u32 map[2])
 {
        struct lu_nodemap       *nodemap = NULL;
@@ -573,7 +632,7 @@ int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
        ENTRY;
 
        mutex_lock(&active_config_lock);
-       nodemap = nodemap_lookup(name);
+       nodemap = nodemap_lookup(nodemap_name);
        if (IS_ERR(nodemap)) {
                mutex_unlock(&active_config_lock);
                GOTO(out, rc = PTR_ERR(nodemap));
@@ -604,6 +663,20 @@ out:
 }
 EXPORT_SYMBOL(nodemap_del_idmap);
 
+int nodemap_del_idmap_range(const char *nodemap_name, enum nodemap_id_type id_type,
+                     const __u32 map[2], const u32 range_count)
+{
+       int rc = 0;
+       int i;
+
+       for (i = 0; i < range_count && !rc; i++) {
+               rc = nodemap_del_idmap(nodemap_name, id_type,
+                                      (int[2]) {map[0] + i, map[1] + i});
+       }
+
+       return rc;
+}
+
 /**
  * Get nodemap assigned to given export. Takes a reference on the nodemap.
  *
@@ -2023,6 +2096,7 @@ static int cfg_nodemap_cmd(enum lcfg_command_type cmd, const char *nodemap_name,
        bool bool_switch;
        u8 netmask = 0;
        u32 idmap[2];
+       u32 range_count;
        u32 int_id;
        int rc = 0;
 
@@ -2182,36 +2256,36 @@ static int cfg_nodemap_cmd(enum lcfg_command_type cmd, const char *nodemap_name,
        case LCFG_NODEMAP_ADD_UIDMAP:
        case LCFG_NODEMAP_ADD_GIDMAP:
        case LCFG_NODEMAP_ADD_PROJIDMAP:
-               rc = nodemap_parse_idmap(param, idmap);
+               rc = nodemap_parse_idmap(nodemap_name, param, idmap, &range_count);
                if (rc != 0)
                        break;
                if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
-                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
-                                              idmap);
+                       rc = nodemap_add_idmap_range(nodemap_name, NODEMAP_UID,
+                                                    idmap, range_count);
                else if (cmd == LCFG_NODEMAP_ADD_GIDMAP)
-                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
-                                              idmap);
+                       rc = nodemap_add_idmap_range(nodemap_name, NODEMAP_GID,
+                                                    idmap, range_count);
                else if (cmd == LCFG_NODEMAP_ADD_PROJIDMAP)
-                       rc = nodemap_add_idmap(nodemap_name, NODEMAP_PROJID,
-                                              idmap);
+                       rc = nodemap_add_idmap_range(nodemap_name, NODEMAP_PROJID,
+                                                    idmap, range_count);
                else
                        rc = -EINVAL;
                break;
        case LCFG_NODEMAP_DEL_UIDMAP:
        case LCFG_NODEMAP_DEL_GIDMAP:
        case LCFG_NODEMAP_DEL_PROJIDMAP:
-               rc = nodemap_parse_idmap(param, idmap);
+               rc = nodemap_parse_idmap(nodemap_name, param, idmap, &range_count);
                if (rc != 0)
                        break;
                if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
-                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
-                                              idmap);
+                       rc = nodemap_del_idmap_range(nodemap_name, NODEMAP_UID,
+                                                    idmap, range_count);
                else if (cmd == LCFG_NODEMAP_DEL_GIDMAP)
-                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
-                                              idmap);
+                       rc = nodemap_del_idmap_range(nodemap_name, NODEMAP_GID,
+                                                    idmap, range_count);
                else if (cmd == LCFG_NODEMAP_DEL_PROJIDMAP)
-                       rc = nodemap_del_idmap(nodemap_name, NODEMAP_PROJID,
-                                              idmap);
+                       rc = nodemap_del_idmap_range(nodemap_name, NODEMAP_PROJID,
+                                                    idmap, range_count);
                else
                        rc = -EINVAL;
                break;
index 3e2bb9b..f540ace 100755 (executable)
@@ -2264,6 +2264,61 @@ test_27a() {
 }
 run_test 27a "test fileset in various nodemaps"
 
+test_27aa() { #LU-17922
+       local idmap
+       local id=500
+
+       do_facet mgs $LCTL nodemap_add Test17922 ||
+               error "unable to add Test17922 as nodemap"
+       stack_trap "do_facet mgs $LCTL nodemap_del Test17922 || true"
+
+       do_facet mgs $LCTL nodemap_add_idmap --name Test17922 \
+                --idtype uid --idmap 500-509:10000-10009 ||
+                error "unable to add idmap range 500-509:10000-10009"
+
+       idmap=$(do_facet mgs $LCTL get_param nodemap.Test17922.idmap | grep idtype)
+       while IFS= read -r idmap; do
+               if (( $id <= 509 )); then
+                       [[ "$idmap" == *"client_id: $id"* ]] ||
+                               error "could not find 'client_id: ${id}' inside of ${idmap}"
+               fi
+               ((id++))
+       done < <(echo "$idmap")
+
+       do_facet mgs $LCTL nodemap_del_idmap --name Test17922 \
+                --idtype uid --idmap 505-509:10005 ||
+                       error "cannot delete idmap range 505-509:10005"
+
+       id=500
+       idmap=$(do_facet mgs $LCTL get_param nodemap.Test17922.idmap | grep idtype)
+       while IFS= read -r idmap; do
+               if (( $id <= 504 )); then
+                       [[ "$idmap" == *"client_id: $id"* ]] ||
+                               error "could not find 'client_id: ${id}' inside of ${idmap}"
+               else
+                       [[ "$idmap" =~ "client_id: $id" ]] &&
+                               error "found 'client_id: $id' in $idmap"
+               fi
+               ((id++))
+       done < <(echo "$idmap")
+
+       do_facet mgs $LCTL nodemap_del_idmap --name Test17922 \
+                --idtype uid --idmap 500-504:10000
+
+       #expected error, invalid secondary range supplied
+       do_facet mgs $LCTL nodemap_add --name Test17922 \
+                --idtype uid --idmap 500-509:10000-10010 &&
+                error "Invalid range 10000-10010 was added"
+
+       (( $(do_facet mgs $LCTL get_param nodemap.Test17922.idmap |
+               grep -c idtype) == 0 )) ||
+               error "invalid range 10000-10010 supplied and passed"
+
+       do_facet mgs $LCTL nodemap_del Test17922 ||
+               error "failed to remove nodemap Test17922"
+}
+run_test 27aa "test nodemap idmap range"
+
 test_27b() { #LU-10703
        [ "$MDS1_VERSION" -lt $(version_code 2.11.50) ] &&
                skip "Need MDS >= 2.11.50"