static atomic_t nodemap_highest_id;
/* Simple flag to determine if nodemaps are active */
-bool nodemap_idmap_active;
+bool nodemap_active;
/**
* pointer to default nodemap kept to keep from
*/
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);
+ }
+
+ idmap_delete_tree(nodemap);
+
+ lprocfs_remove(&nodemap->nm_proc_entry);
OBD_FREE_PTR(nodemap);
}
void nodemap_putref(struct lu_nodemap *nodemap)
{
LASSERT(nodemap != NULL);
- LASSERT(cfs_atomic_read(&nodemap->nm_refcount) > 0);
+ LASSERT(atomic_read(&nodemap->nm_refcount) > 0);
if (atomic_dec_and_test(&nodemap->nm_refcount))
nodemap_destroy(nodemap);
struct lu_nodemap *nodemap;
nodemap = cfs_hlist_entry(hnode, struct lu_nodemap, nm_hash);
+
return nodemap->nm_name;
}
struct lu_nodemap *nodemap;
nodemap = nodemap_hs_key(compared_hnode);
+
return !strcmp(key, nodemap->nm_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;
* 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
*/
{
int rc = 0;
+ *nodemap = NULL;
+
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);
+
+/**
+ * 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;
+ return idmap->id_fs;
+
+squash:
+ if (id_type == NODEMAP_UID)
+ return nodemap->nm_squash_uid;
+ else
+ return nodemap->nm_squash_gid;
+out:
+ return id;
+}
+EXPORT_SYMBOL(nodemap_map_id);
+
+/*
+ * 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;
}
+EXPORT_SYMBOL(nodemap_del_range);
/**
* Nodemap constructor
int rc = 0;
rc = nodemap_lookup(name, &nodemap);
- if (rc < 0)
+ if (rc == -EINVAL)
goto out;
- if (nodemap != NULL) {
+ if (rc != -ENOENT) {
nodemap_putref(nodemap);
GOTO(out, rc = -EEXIST);
}
-
OBD_ALLOC_PTR(nodemap);
if (nodemap == NULL) {
snprintf(nodemap->nm_name, sizeof(nodemap->nm_name), "%s", name);
INIT_LIST_HEAD(&(nodemap->nm_ranges));
- nodemap->nm_local_to_remote_uidmap = RB_ROOT;
- nodemap->nm_remote_to_local_uidmap = RB_ROOT;
- nodemap->nm_local_to_remote_gidmap = RB_ROOT;
- nodemap->nm_remote_to_local_gidmap = RB_ROOT;
+ nodemap->nm_fs_to_client_uidmap = RB_ROOT;
+ nodemap->nm_client_to_fs_uidmap = RB_ROOT;
+ nodemap->nm_fs_to_client_gidmap = RB_ROOT;
+ nodemap->nm_client_to_fs_gidmap = RB_ROOT;
if (is_default) {
nodemap->nm_id = LUSTRE_NODEMAP_DEFAULT_ID;
}
/**
+ * 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
*
* \param name name of nodemap
EXPORT_SYMBOL(nodemap_del);
/**
+ * activate nodemap functions
+ *
+ * \param value 1 for on, 0 for off
+ */
+void nodemap_activate(const bool value)
+{
+ nodemap_active = value;
+}
+EXPORT_SYMBOL(nodemap_activate);
+
+/**
* Cleanup nodemap module on exit
*/
static void nodemap_mod_exit(void)