+ 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);
+
+/**
+ * parse a string containing an id map of form "client_id:filesystem_id"
+ * into an array of __u32 * for use in mapping functions
+ *
+ * \param idmap_str map string
+ * \param idmap array[2] of __u32
+ *
+ * \retval 0 on success
+ */
+int nodemap_parse_idmap(const char *idmap_str, __u32 idmap[2])
+{
+ char *end;
+
+ if (idmap_str == NULL)
+ return -EINVAL;
+
+ idmap[0] = simple_strtoul(idmap_str, &end, 10);
+ if (end == idmap_str || *end != ':')
+ return -EINVAL;
+
+ idmap_str = end + 1;
+ idmap[1] = simple_strtoul(idmap_str, &end, 10);
+ if (end == idmap_str)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(nodemap_parse_idmap);
+
+/**
+ * add an idmap to the proper nodemap trees
+ *
+ * \param name name of nodemap
+ * \param id_type NODEMAP_UID or NODEMAP_GID
+ * \param map array[2] __u32 containing the mapA values
+ * map[0] is client id
+ * map[1] is the filesystem id
+ *
+ * \retval 0 on success
+ */
+int nodemap_add_idmap(const char *name, enum nodemap_id_type id_type,
+ const __u32 map[2])
+{
+ struct lu_nodemap *nodemap = NULL;
+ struct lu_idmap *idmap;
+ int rc = 0;
+
+ rc = nodemap_lookup(name, &nodemap);
+ if (nodemap == NULL || is_default_nodemap(nodemap))
+ GOTO(out, rc = -EINVAL);
+
+ idmap = idmap_create(map[0], map[1]);
+ if (idmap == NULL)
+ GOTO(out_putref, rc = -ENOMEM);
+
+ idmap_insert(id_type, idmap, nodemap);
+
+out_putref:
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_add_idmap);
+
+/**
+ * delete idmap from proper nodemap tree
+ *
+ * \param name name of nodemap
+ * \param id_type NODEMAP_UID or NODEMAP_GID
+ * \param map array[2] __u32 containing the mapA values
+ * map[0] is client id
+ * map[1] is the filesystem id
+ *
+ * \retval 0 on success
+ */
+int nodemap_del_idmap(const char *name, enum nodemap_id_type id_type,
+ const __u32 map[2])
+{
+ struct lu_nodemap *nodemap = NULL;
+ struct lu_idmap *idmap = NULL;
+ int rc = 0;
+
+ rc = nodemap_lookup(name, &nodemap);
+ if (nodemap == NULL || is_default_nodemap(nodemap))
+ GOTO(out, rc = -EINVAL);
+
+ idmap = idmap_search(nodemap, NODEMAP_CLIENT_TO_FS, id_type,
+ map[0]);
+ if (idmap == NULL)
+ GOTO(out_putref, rc = -EINVAL);
+
+ idmap_delete(id_type, idmap, nodemap);
+
+out_putref:
+ nodemap_putref(nodemap);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(nodemap_del_idmap);
+
+/**
+ * mapping function for nodemap idmaps
+ *
+ * \param nodemap lu_nodemap structure defining nodemap
+ * \param node_type NODEMAP_UID or NODEMAP_GID
+ * \param tree_type NODEMAP_CLIENT_TO_FS or
+ * NODEMAP_FS_TO_CLIENT
+ * \param id id to map
+ *
+ * \retval mapped id according to the rules below.
+ *
+ * if the nodemap_active is false, just return the passed id without mapping
+ *
+ * if the id to be looked up in 0, check that root access is allowed and if it
+ * is, return 0. Otherwise, return the squash uid or gid.
+ *
+ * if the nodemap is configured to trusted the ids from the client system, just
+ * return the passwd id without mapping.
+ *
+ * if by this point, we haven't returned and the nodemap in question is the
+ * default nodemap, return the dquash uid or gid.
+ *
+ * after these checks, search the proper tree for the mapping, and if found
+ * return the mapped value, otherwise return the squash uid or gid.
+ */
+__u32 nodemap_map_id(struct lu_nodemap *nodemap,
+ enum nodemap_id_type id_type,
+ enum nodemap_tree_type tree_type, __u32 id)
+{
+ struct lu_idmap *idmap = NULL;
+
+ if (!nodemap_active)
+ goto out;
+
+ if (id == 0) {
+ if (nodemap->nmf_allow_root_access)
+ goto out;
+ else
+ goto squash;
+ }
+
+ if (nodemap->nmf_trust_client_ids)
+ goto out;
+
+ if (is_default_nodemap(nodemap))
+ goto squash;
+
+ idmap = idmap_search(nodemap, tree_type, id_type, id);
+ if (idmap == NULL)
+ goto squash;
+
+ if (tree_type == NODEMAP_FS_TO_CLIENT)
+ return idmap->id_client;